]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.20-netfilter-1.2.8_20030924.patch
- obsolete
[packages/kernel.git] / linux-2.4.20-netfilter-1.2.8_20030924.patch
1 diff -Nur --exclude '*.orig' linux-2.4.20.org/Documentation/Configure.help linux-2.4.20/Documentation/Configure.help
2 --- linux-2.4.20.org/Documentation/Configure.help       Wed Sep 24 08:52:58 2003
3 +++ linux-2.4.20/Documentation/Configure.help   Wed Sep 24 09:18:15 2003
4 @@ -2543,6 +2543,50 @@
5    If you want to compile it as a module, say M here and read
6    <file:Documentation/modules.txt>.  If unsure, say `N'.
7  
8 +Amanda protocol support
9 +CONFIG_IP_NF_AMANDA
10 +  If you are running the Amanda backup package (http://www.amanda.org/)
11 +  on this machine or machines that will be MASQUERADED through this
12 +  machine, then you may want to enable this feature.  This allows the
13 +  connection tracking and natting code to allow the sub-channels that
14 +  Amanda requires for communication of the backup data, messages and
15 +  index.
16 +
17 +  If you want to compile it as a module, say M here and read
18 +  Documentation/modules.txt.  If unsure, say `N'.
19 +
20 +
21 +CuSeeMe protocol support
22 +CONFIG_IP_NF_CUSEEME
23 +  The CuSeeMe conferencing protocol is problematic when used in
24 +  conjunction with NAT; even though there are no random ports used for
25 +  extra connections, the messages contain IP addresses inside them.
26 +  This NAT helper mangles the IP address inside packets so both
27 +  parties don't get confused.
28 +
29 +  If you want to compile it as a module, say M here and read
30 +  <file:Documentation/modules.txt>.  If unsure, say `Y'.
31 +
32 +MMS protocol support
33 +CONFIG_IP_NF_MMS
34 +  Tracking MMS (Microsoft Windows Media Services) connections
35 +  could be problematic if random ports are used to send the
36 +  streaming content. This option allows users to track streaming
37 +  connections over random UDP or TCP ports.
38 +
39 +  If you want to compile it as a module, say M here and read
40 +  <file:Documentation/modules.txt>.  If unsure, say `Y'.
41 +
42 +Quake III Arena protocol support
43 +CONFIG_IP_NF_QUAKE3
44 +  Quake III Arena  connection tracking helper. This module allows for a
45 +  stricter firewall rulebase if one only allows traffic to a master
46 +  server. Connections to Quake III server IP addresses and ports returned
47 +  by the master server will be tracked automatically.
48 +
49 +  If you want to compile it as a module, say M here and read
50 +  <file:Documentation/modules.txt>.  If unsure, say `Y'.
51 +
52  IRC Send/Chat protocol support
53  CONFIG_IP_NF_IRC
54    There is a commonly-used extension to IRC called
55 @@ -2557,6 +2601,118 @@
56    If you want to compile it as a module, say 'M' here and read
57    Documentation/modules.txt.  If unsure, say 'N'.
58  
59 +TFTP protocol support
60 +CONFIG_IP_NF_TFTP
61 +  TFTP connection tracking helper, this is required depending
62 +  on how restrictive your ruleset is.
63 +  If you are using a tftp client behind -j SNAT or -j MASQUERADING
64 +  you will need this.
65 +
66 +  If you want to compile it as a module, say M here and read
67 +  Documentation/modules.txt.  If unsure, say `Y'.
68 +
69 +Per connection mark support
70 +CONFIG_IP_NF_CONNTRACK_MARK
71 +  This option enables support for connection marks, used by the
72 +  `CONNMARK' target and `connmark' match. Similar to the mark value
73 +  of packets, but this mark value is kept in the conntrack session
74 +  instead of the individual packets.
75 +
76 +CONNMARK target support
77 +CONFIG_IP_NF_TARGET_CONNMARK
78 +  This option adds a `CONNMARK' target, which allows one to manipulate
79 +  the connection mark value.  Similar to the MARK target, but
80 +  affects the connection mark value rather than the packet mark value.
81 +
82 +  If you want to compile it as a module, say M here and read
83 +  Documentation/modules.txt.  The module will be called
84 +  ipt_CONNMARK.o.  If unsure, say `N'.
85 +
86 +connmark match support
87 +CONFIP_IP_NF_MATCH_CONNMARK
88 +  This option adds a `connmark' match, which allows you to match the
89 +  connection mark value previously set for the session by `CONNMARK'. 
90 +
91 +Eggdrop bot support
92 +CONFIG_IP_NF_EGG
93 +  If you are running an eggdrop hub bot on this machine, then you
94 +  may want to enable this feature. This enables eggdrop bots to share
95 +  their user file to other eggdrop bots.
96 +
97 +  If you want to compile it as a module, say M here and read
98 +  Documentation/modules.txt.  If unsure, say `N'.
99 +
100 +H.323 (netmeeting) support
101 +CONFIG_IP_NF_H323
102 +  H.323 is a standard signalling protocol used by teleconferencing
103 +  softwares like netmeeting. With the ip_conntrack_h323 and
104 +  the ip_nat_h323 modules you can support the protocol on a connection
105 +  tracking/NATing firewall.
106 +
107 +  If you want to compile it as a module, say 'M' here and read
108 +  Documentation/modules.txt.  If unsure, say 'N'.
109 +
110 +PPTP conntrack and NAT support
111 +CONFIG_IP_NF_PPTP
112 +  This module adds support for PPTP (Point to Point Tunnelling Protocol, 
113 +  RFC2637) conncection tracking and NAT. 
114 +
115 +  If you are running PPTP sessions over a stateful firewall or NAT box,
116 +  you may want to enable this feature.  
117 +
118 +  Please note that not all PPTP modes of operation are supported yet.
119 +  For more info, read top of the file net/ipv4/netfilter/ip_conntrack_pptp.c
120 +
121 +  If you want to compile it as a module, say M here and read
122 +  Documentation/modules.txt.  If unsure, say `N'.
123 +
124 +GRE protocol conntrack and NAT support
125 +CONFIG_IP_NF_CT_PROTO_GRE
126 +  This module adds generic support for connection tracking and NAT of the
127 +  GRE protocol (RFC1701, RFC2784).  Please note that this will only work
128 +  with GRE connections using the key field of the GRE header.
129 +
130 +  You will need GRE support to enable PPTP support.
131 +
132 +  If you want to compile it as a module, say `M' here and read
133 +  Documentation/modules.txt.  If unsire, say `N'.
134 +
135 +RSH protocol support
136 +CONFIG_IP_NF_RSH
137 +  The RSH connection tracker is required if the dynamic
138 +  stderr "Server to Client" connection is to occur during a
139 +  normal RSH session.  This typically operates as follows;
140 +
141 +    Client 0:1023 --> Server 514    (stream 1 - stdin/stdout)
142 +    Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
143 +
144 +  This connection tracker will identify new RSH sessions,
145 +  extract the outbound session details, and notify netfilter
146 +  of pending "related" sessions.
147 +
148 +  Warning: This module could be dangerous. It is not "best
149 +           practice" to use RSH, use SSH in all instances.
150 +           (see rfc1244, rfc1948, rfc2179, etc ad-nauseum)
151 +
152 +
153 +  If you want to compile it as a module, say M here and read
154 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
155 +
156 +Talk protocol support
157 +CONFIG_IP_NF_TALK
158 +  The talk protocols (both otalk/talk - or talk/ntalk, to confuse
159 +  you by the different namings about which is old or which is new :-)
160 +  use an additional channel to setup the talk session and a separated
161 +  data channel for the actual conversation (like in FTP). Both the 
162 +  initiating and the setup channels are over UDP, while the data channel 
163 +  is over TCP, on a random port. The conntrack part of this extension
164 +  will enable you to let in/out talk sessions easily by matching these
165 +  connections as RELATED by the state match, while the NAT part helps
166 +  you to let talk sessions trough a NAT machine.
167 +
168 +  If you want to compile it as a module, say 'M' here and read
169 +  Documentation/modules.txt.  If unsure, say 'N'.
170 +
171  FTP protocol support
172  CONFIG_IP_NF_FTP
173    Tracking FTP connections is problematic: special helpers are
174 @@ -2584,6 +2740,33 @@
175    If you want to compile it as a module, say M here and read
176    <file:Documentation/modules.txt>.  If unsure, say `N'.
177  
178 +recent match support
179 +CONFIG_IP_NF_MATCH_RECENT
180 +  This match is used for creating one or many lists of recently
181 +  used addresses and then matching against that/those list(s).
182 +
183 +  Short options are available by using 'iptables -m recent -h'
184 +  Official Website: <http://snowman.net/projects/ipt_recent/>
185 +
186 +  If you want to compile it as a module, say M here and read
187 +  Documentation/modules.txt.  If unsure, say `N'.
188 +
189 +quota match support
190 +CONFIG_IP_NF_MATCH_QUOTA
191 +  This match implements network quotas.
192 +
193 +  If you want to compile it as a module, say M here and read
194 +  Documentation/modules.txt.  If unsure, say `N'.
195 +
196 +
197 +addrtype match support
198 +CONFIG_IP_NF_MATCH_ADDRTYPE
199 +  This option allows you to match what routing thinks of an address,
200 +  eg. UNICAST, LOCAL, BROADCAST, ...
201 +
202 +  If you want to compile it as a module, say M here and read
203 +  Documentation/modules.txt.  If unsure, say `N'.
204 +
205  limit match support
206  CONFIG_IP_NF_MATCH_LIMIT
207    limit matching allows you to control the rate at which a rule can be
208 @@ -2635,6 +2818,14 @@
209    If you want to compile it as a module, say M here and read
210    <file:Documentation/modules.txt>.  If unsure, say `N'.
211  
212 +Multiple port with ranges match support
213 +CONFIG_IP_NF_MATCH_MPORT
214 +  This is an enhanced multiport match which supports port
215 +  ranges as well as single ports.
216 +
217 +  If you want to compile it as a module, say M here and read
218 +  Documentation/modules.txt.  If unsure, say `N'.
219 +
220  Multiple port match support
221  CONFIG_IP_NF_MATCH_MULTIPORT
222    Multiport matching allows you to match TCP or UDP packets based on
223 @@ -2652,6 +2843,18 @@
224    If you want to compile it as a module, say M here and read
225    Documentation/modules.txt.  If unsure, say `N'.
226  
227 +U32 patch support
228 +CONFIG_IP_NF_MATCH_U32
229 +  U32 allows you to extract quantities of up to 4 bytes from a packet,
230 +  AND them with specified masks, shift them by specified amounts and
231 +  test whether the results are in any of a set of specified ranges.
232 +  The specification of what to extract is general enough to skip over
233 +  headers with lengths stored in the packet, as in IP or TCP header
234 +  lengths.
235 +
236 +  Details and examples are in the kernel module source.
237 +
238 +
239  LENGTH match support
240  CONFIG_IP_NF_MATCH_LENGTH
241    This option allows you to match the length of a packet against a
242 @@ -2690,6 +2893,132 @@
243  
244   
245  
246 +Fuzzy Logic Controller match support
247 +CONFIG_IP_NF_MATCH_FUZZY
248 +  This option adds a `fuzzy' match,
249 +  which allows you to match packets according to a fuzzy logic
250 +  based law .
251
252 +  If you want to compile it as a module, say M here and read
253 +  Documentation/modules.txt.  If unsure, say `N'.
254 +
255 +
256 +iprange match support
257 +CONFIG_IP_NF_MATCH_IPRANGE
258 +  This option makes possible to match IP addresses against
259 +  IP address ranges.
260 +
261 +  If you want to compile it as a module, say M here and read
262 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
263 +
264 +
265 +IPV4OPTIONS patch support
266 +CONFIG_IP_NF_MATCH_IPV4OPTIONS
267 +  This option adds a IPV4OPTIONS match.
268 +  It allows you to filter options like source routing,
269 +  record route, timestamp and router-altert.
270 +
271 +  If you say Y here, try iptables -m ipv4options --help for more information.
272
273 +  If you want to compile it as a module, say M here and read
274 +  Documentation/modules.txt.  If unsure, say `N'.
275 +
276 +
277 +Nth match support
278 +CONFIG_IP_NF_MATCH_NTH
279 +  This option adds a `Nth' match, which allow you to make
280 +  rules that match every Nth packet.  By default there are 
281 +  16 different counters.
282 +
283 +[options]
284 +   --every     Nth              Match every Nth packet
285 +  [--counter]  num              Use counter 0-15 (default:0)
286 +  [--start]    num              Initialize the counter at the number 'num'
287 +                                instead of 0. Must be between 0 and Nth-1
288 +  [--packet]   num              Match on 'num' packet. Must be between 0
289 +                                and Nth-1.
290 +
291 +                                If --packet is used for a counter than
292 +                                there must be Nth number of --packet
293 +                                rules, covering all values between 0 and
294 +                                Nth-1 inclusively.
295
296 +  If you want to compile it as a module, say M here and read
297 +  Documentation/modules.txt.  If unsure, say `N'.
298 +
299 +
300 +OSF match support
301 +CONFIG_IP_NF_MATCH_OSF
302 +
303 +  The idea of passive OS fingerprint matching exists for quite a long time,
304 +  but was created as extension fo OpenBSD pf only some weeks ago.
305 +  Original idea was lurked in some OpenBSD mailing list (thanks
306 +  grange@open...) and than adopted for Linux netfilter in form of this code.
307 +
308 +  Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
309 +  his excellent p0f and than changed a bit for more convenience.
310 +
311 +  This module compares some data(WS, MSS, options and it's order, ttl,
312 +  df and others) from first SYN packet (actually from packets with SYN
313 +  bit set) with hardcoded in fingers[] table ones.
314 +
315 +  If you say Y here, try iptables -m osf --help for more information.
316
317 +  If you want to compile it as a module, say M here and read
318 +  Documentation/modules.txt.  If unsure, say `N'.
319 +
320 +psd match support
321 +CONFIG_IP_NF_MATCH_PSD
322 +  This option adds a `psd' match, which allows you to create rules in
323 +  any iptables table wich will detect TCP and UDP port scans.
324
325 +  If you want to compile it as a module, say M here and read
326 +  Documentation/modules.txt.  If unsure, say `N'.
327 +
328 +
329 +Random match support
330 +CONFIG_IP_NF_MATCH_RANDOM
331 +  This option adds a `random' match,
332 +  which allow you to match packets randomly
333 +  following a given probability.
334
335 +  If you want to compile it as a module, say M here and read
336 +  Documentation/modules.txt.  If unsure, say `N'.
337 +
338 +
339 +REALM match support
340 +CONFIG_IP_NF_MATCH_REALM
341 +  This option adds a `realm' match, which allows you to use the realm
342 +  key from the routing subsytem inside iptables.
343 +
344 +  This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option 
345 +  in tc world.
346 +
347 +  If you want to compile it as a module, say M here and read
348 +  Documentation/modules.txt.  If unsure, say `N'.
349 +
350 +
351 +TIME patch support
352 +CONFIG_IP_NF_MATCH_TIME
353 +  This option adds a `time' match, which allows you
354 +  to matchbased on the packet arrival time
355 +  (arrival time at the machine which the netfilter is running on) or
356 +  departure time (for locally generated packets).
357 +
358 +  If you say Y here, try iptables -m time --help for more information.
359
360 +  If you want to compile it as a module, say M here and read
361 +  Documentation/modules.txt.  If unsure, say `N'.
362 +
363 +
364 +Condition variable match support
365 +CONFIG_IP_NF_MATCH_CONDITION
366 +  This option allows you to match firewall rules against condition
367 +  variables stored in the /proc/net/ipt_condition directory.
368 +
369 +  If you want to compile it as a module, say M here and read
370 +  Documentation/modules.txt.  If unsure, say `N'.
371 +
372  TOS match support
373  CONFIG_IP_NF_MATCH_TOS
374    TOS matching allows you to match packets based on the Type Of
375 @@ -2710,6 +3039,44 @@
376    Documentation/modules.txt.  If unsure, say `N'.
377  
378  
379 +Connections/IP limit match support
380 +CONFIG_IP_NF_MATCH_CONNLIMIT
381 +  This match allows you to restrict the number of parallel TCP
382 +  connections to a server per client IP address (or address block).
383 +
384 +  If you want to compile it as a module, say M here and read
385 +  Documentation/modules.txt.  If unsure, say `N'.
386 +
387 +RPC match support
388 +CONFIG_IP_NF_MATCH_RPC
389 +  This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
390 +  matcher and tracker.
391 +
392 +  This option supplies two connection tracking modules;
393 +  ip_conntrack_rpc_udp and ip_conntrack_rpc_tcp, which track
394 +  portmapper requests using UDP and TCP respectively.
395 +
396 +  This option also adds an RPC match module for iptables, which
397 +  matches both via the old "record match" method and a new
398 +  "procedure match" method. The older method matches all RPC
399 +  procedure packets that relate to previously recorded packets
400 +  seen querying a portmapper. The newer method matches only
401 +  those RPC procedure packets explicitly specified by the user,
402 +  and that can then be related to previously recorded packets
403 +  seen querying a portmapper.
404 +
405 +  These three modules are required if RPCs are to be filtered
406 +  accurately; as RPCs are allocated pseudo-randomly to UDP and
407 +  TCP ports as they register with the portmapper.
408 +
409 +  Up to 8 portmapper ports per module, and up to 128 RPC
410 +  procedures per iptables rule, may be specified by the user,
411 +  to enable effective RPC management.
412 +
413 +
414 +  If you want to compile it as a module, say M here and read
415 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
416 +
417  Connection state match support
418  CONFIG_IP_NF_MATCH_STATE
419    Connection state matching allows you to match packets based on their
420 @@ -2719,6 +3086,14 @@
421    If you want to compile it as a module, say M here and read
422    <file:Documentation/modules.txt>.  If unsure, say `N'.
423  
424 +String match support (EXPERIMENTAL)
425 +CONFIG_IP_NF_MATCH_STRING
426 +  String matching alows you to match packets which contain a
427 +  specified string of characters.
428 +
429 +  If you want to compile it as a module, say M here and read
430 +  Documentation/modules.txt.  If unsure, say `N'.
431 +
432  Unclean match support
433  CONFIG_IP_NF_MATCH_UNCLEAN
434    Unclean packet matching matches any strange or invalid packets, by
435 @@ -2735,6 +3110,52 @@
436    If you want to compile it as a module, say M here and read
437    <file:Documentation/modules.txt>.  If unsure, say `N'.
438  
439 +TARPIT target support
440 +CONFIG_IP_NF_TARGET_TARPIT
441 +  Adds a TARPIT target to iptables, which captures and holds
442 +  incoming TCP connections using no local per-connection resources.
443 +  Connections are accepted, but immediately switched to the persist
444 +  state (0 byte window), in which the remote side stops sending data
445 +  and asks to continue every 60-240 seconds.  Attempts to close the
446 +  connection are ignored, forcing the remote side to time out the
447 +  connection in 12-24 minutes.
448 +
449 +  This offers similar functionality to LaBrea
450 +  <http://www.hackbusters.net/LaBrea/> but doesn't require dedicated
451 +  hardware or IPs.  Any TCP port that you would normally DROP or REJECT
452 +  can instead become a tarpit.
453 +
454 +raw table support (required for NOTRACK/TRACE)
455 +CONFIG_IP_NF_RAW
456 +  This option adds a `raw' table to iptables. This table is the very
457 +  first in the netfilter framework and hooks in at the PREROUTING
458 +  and OUTPUT chains.
459 +
460 +  If you want to compile it as a module, say M here and read
461 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
462 +
463 +TRACE target support
464 +CONFIG_IP_NF_TARGET_TRACE
465 +  The TRACE target allows packets to be traced as those
466 +  matches any subsequent rule in any table/rule. The matched
467 +  rule and the packet is logged with the prefix
468 +
469 +  TRACE: tablename/chainname/rulenum  
470 +
471 +  If you want to compile it as a module, say M here and read
472 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
473 +
474 +NOTRACK target support
475 +CONFIG_IP_NF_TARGET_NOTRACK
476 +  The NOTRACK target allows a select rule to specify
477 +  which packets *not* to enter the conntrack/NAT
478 +  subsystem with all the consequences (no ICMP error tracking,
479 +  no protocol helpers for the selected packets).
480 +
481 +  If you want to compile it as a module, say M here and read
482 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
483 +
484 +
485  Packet filtering
486  CONFIG_IP_NF_FILTER
487    Packet filtering defines a table `filter', which has a series of
488 @@ -2744,6 +3165,24 @@
489    If you want to compile it as a module, say M here and read
490    <file:Documentation/modules.txt>.  If unsure, say `N'.
491  
492 +IPV4OPTSSTRIP target support
493 +CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP
494 +  This option adds an IPV4OPTSSTRIP target.
495 +  This target allows you to strip all IP options in a packet.
496
497 +  If you want to compile it as a module, say M here and read
498 +  Documentation/modules.txt.  If unsure, say `N'.
499 +
500 +
501 +NETLINK target support
502 +CONFIG_IP_NF_TARGET_NETLINK
503 +  The NETLINK target allows you to recieve packets in userspace via
504 +  the kernel firewall netlink socket. Apps such as fwmon
505 +  (http://firestorm.geek-ware.co.uk) can then recieve and dislpay
506 +  these packets. This option is basically a re-implementation of the
507 +  ipchains -o option.
508 +
509 +
510  REJECT target support
511  CONFIG_IP_NF_TARGET_REJECT
512    The REJECT target allows a filtering rule to specify that an ICMP
513 @@ -2808,6 +3247,27 @@
514    If you want to compile it as a module, say M here and read
515    <file:Documentation/modules.txt>.  If unsure, say `N'.
516  
517 +NETMAP target support
518 +CONFIG_IP_NF_TARGET_NETMAP
519 +  NETMAP is an implementation of static 1:1 NAT mapping of network
520 +  addresses. It maps the network address part, while keeping the
521 +  host address part intact. It is similar to Fast NAT, except that
522 +  Netfilter's connection tracking doesn't work well with Fast NAT.
523 +
524 +  If you want to compile it as a module, say M here and read
525 +  Documentation/modules.txt.  The module will be called
526 +  ipt_NETMAP.o.  If unsure, say `N'.
527 +
528 +SAME NAT target support
529 +CONFIG_IP_NF_TARGET_SAME
530 +  This option adds a `SAME' target, which works like the standard
531 +  SNAT target, but attempts to give clients the same IP for all
532 +  connections.
533 +
534 +  If you want to compile it as a module, say M here and read
535 +  Documentation/modules.txt.  The module will be called
536 +  ipt_SAME.o.  If unsure, say `N'.
537 +
538  REDIRECT target support
539  CONFIG_IP_NF_TARGET_REDIRECT
540    REDIRECT is a special case of NAT: all incoming connections are
541 @@ -2866,6 +3326,42 @@
542    If you want to compile it as a module, say M here and read
543    <file:Documentation/modules.txt>.  If unsure, say `N'.
544  
545 +IMQ target support
546 +CONFIG_IP_NF_TARGET_IMQ
547 +  This option adds a `IMQ' target which is used to specify if and
548 +  to which imq device packets should get enqueued/dequeued.
549 +
550 +  If you want to compile it as a module, say M here and read
551 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
552 +
553 +IPMARK target support
554 +CONFIG_IP_NF_TARGET_IPMARK
555 +  This option adds a `IPMARK' target, which allows you to create rules
556 +  in the `mangle' table which alter the netfilter mark (nfmark) field
557 +  basing on the source or destination ip address of the packet.
558 +  This is very useful for very fast massive mangling and marking.
559 +
560 +  If you want to compile it as a module, say M here and read
561 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
562 +
563 +
564 +
565 +ROUTE target support
566 +CONFIG_IP_NF_TARGET_ROUTE
567 +  This option adds a `ROUTE' target, which enables you to setup unusual
568 +  routes. For example, the ROUTE lets you route a received packet through 
569 +  an interface or towards a host, even if the regular destination of the 
570 +  packet is the router itself. The ROUTE target is also able to change the 
571 +  incoming interface of a packet.
572 +
573 +  The target can be or not a final target. It has to be used inside the 
574 +  mangle table.
575 +  
576 +  If you want to compile it as a module, say M here and read
577 +  Documentation/modules.txt.  The module will be called ipt_ROUTE.o.
578 +  If unsure, say `N'.
579 +
580 +
581  MARK target support
582  CONFIG_IP_NF_TARGET_MARK
583    This option adds a `MARK' target, which allows you to create rules
584 @@ -2933,6 +3429,73 @@
585    If you want to compile it as a module, say M here and read
586    Documentation/modules.txt.  If unsure, say `N'.
587  
588 +TTL target support
589 +CONFIG_IP_NF_TARGET_TTL
590 +  This option adds a `TTL' target, which enables the user to set
591 +  the TTL value or increment / decrement the TTL value by a given
592 +  amount.
593 +
594 +  If you want to compile it as a module, say M here and read
595 +  Documentation/modules.txt.  If unsure, say `N'.
596 +
597 +pool match and target support
598 +CONFIG_IP_NF_MATCH_POOL
599 +  Pool matching lets you use bitmaps with one bit per address from some
600 +  range of IP addresses; the match depends on whether a checked source
601 +  or destination address has its bit set in the pool.
602 +
603 +  There is also a POOL netfilter target, which can be used to set or remove
604 +  the addresses of a packet from a pool.
605 +
606 +  To define and use pools, you need userlevel utilities: a patched iptables,
607 +  and the program ippool(8), which defines the pools and their bounds.
608 +  The current release of pool matching is ippool-0.0.2, and can be found
609 +  in the archives of the netfilter mailing list at
610 +  http://lists.samba.org/netfilter/.
611 +
612 +  If you want to compile it as a module, say M here and read
613 +  Documentation/modules.txt.  If unsure, say `N'.
614 +
615 +pool match and target statistics gathering
616 +CONFIG_IP_POOL_STATISTICS
617 +  This option controls whether usage gathering code is compiled into the
618 +  ip_pool module.  Disabling statistics may be substantially faster.
619 +
620 +CLASSIFY target support
621 +CONFIG_IP_NF_TARGET_CLASSIFY
622 +  This option adds a `CLASSIFY' target, which enables the user to set
623 +  the priority of a packet. Some qdiscs can use this value for classification,
624 +  among these are:
625 +
626 +  atm, cbq, dsmark, pfifo_fast, htb, prio
627 +
628 +  If you want to compile it as a module, say M here and read
629 +  Documentation/modules.txt.  If unsure, say `N'.
630 +
631 +TCPLAG target support
632 +CONFIG_IP_NF_TARGET_TCPLAG
633 +  This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
634 +  FORWARD chains.
635 +
636 +  This target has no effect on packets but will passively monitor TCP/IP
637 +  connections and send lag estimates to syslog. Lag estimates are
638 +  generated by considering the time delay between SEQ and matching ACK,
639 +  which does not map precisely to any particular network property.
640 +  We can say that a fast network will typically give smaller lag values
641 +  than a slow network.
642 +
643 +  Safest option is to choose `M' here and compile as a module,
644 +  the module will do nothing until activated using the `iptables' utility.
645 +
646 +
647 +XOR target support
648 +CONFIG_IP_NF_TARGET_XOR
649 +  This option adds a `XOR' target, which can encrypt TCP and 
650 +  UDP traffic using a simple XOR encryption.
651 +
652 +  If you want to compile it as a module, say M here and read
653 +  Documentation/modules.txt.  If unsure, say `N'.
654 +
655  LOG target support
656  CONFIG_IP_NF_TARGET_LOG
657    This option adds a `LOG' target, which allows you to create rules in
658 @@ -2972,6 +3535,93 @@
659    If you want to compile it as a module, say M here and read
660    Documentation/modules.txt.  If unsure, say `N'.
661  
662 +AH/ESP match support (EXPERIMENTAL)
663 +CONFIG_IP6_NF_MATCH_AHESP
664 +  These two match extensions (`ah' and `esp') allow you to match a
665 +  range of SPIs inside AH or ESP headers of IPv6 packets.
666
667 +  If you want to compile it as a module, say M here and read
668 +  Documentation/modules.txt.  If unsure, say `N'.
669 +
670 +
671 +Fragmentation header match support (EXPERIMENTAL)
672 +CONFIG_IP6_NF_MATCH_FRAG
673 +  This match extension (`frag') allow you to select the packet based on the
674 +  fileds of the fragmentation header of the IPv6 packets.
675
676 +  If you want to compile it as a module, say M here and read
677 +  Documentation/modules.txt.  If unsure, say `N'.
678 +
679 +
680 +IPv6 Extension Headers Match (EXPERIMENTAL)
681 +CONFIG_IP6_NF_MATCH_IPV6HEADER
682 +  extension header matching allows you to controll the packets based
683 +  on their extension headers.
684 +  
685 +  If you want to compile it as a module, say M here and read
686 +  Documentation/modules.txt.  If unsure, say `N'.
687 +
688 +
689 +Fragmentation header match support (EXPERIMENTAL)
690 +CONFIG_IP6_NF_MATCH_OPTS
691 +  These match extensions (`hbh' and `dst') allow you to select the packet 
692 +  based on the fileds of the option header of the IPv6 packets.
693
694 +  If you want to compile it as a module, say M here and read
695 +  Documentation/modules.txt.  If unsure, say `N'.
696 +
697 +
698 +Fragmentation header match support (EXPERIMENTAL)
699 +CONFIG_IP6_NF_MATCH_RT
700 +  This match extension (`rt') allow you to select the packet based on the
701 +  fileds of the routing header of the IPv6 packets.
702
703 +  If you want to compile it as a module, say M here and read
704 +  Documentation/modules.txt.  If unsure, say `N'.
705 +
706 +
707 +Fuzzy Logic Controller match support
708 +CONFIG_IP6_NF_MATCH_FUZZY
709 +  This option adds a `fuzzy' match, which allows you to match
710 +  packets according to a fuzzy logic based law.
711 +
712 +  If you want to compile it as a module, say M here and read
713 +  Documentation/modules.txt.  If unsure, say `N'.
714 +
715 +
716 +Nth match support
717 +CONFIG_IP6_NF_MATCH_NTH
718 +  This option adds a `Nth' match, which allow you to make
719 +  rules that match every Nth packet.  By default there are 
720 +  16 different counters.
721 +
722 +[options]
723 +   --every     Nth              Match every Nth packet
724 +  [--counter]  num              Use counter 0-15 (default:0)
725 +  [--start]    num              Initialize the counter at the number 'num'
726 +                                instead of 0. Must be between 0 and Nth-1
727 +  [--packet]   num              Match on 'num' packet. Must be between 0
728 +                                and Nth-1.
729 +
730 +                                If --packet is used for a counter than
731 +                                there must be Nth number of --packet
732 +                                rules, covering all values between 0 and
733 +                                Nth-1 inclusively.
734
735 +  If you want to compile it as a module, say M here and read
736 +  Documentation/modules.txt.  If unsure, say `N'.
737 +
738 +
739 +Random match support
740 +CONFIG_IP6_NF_MATCH_RANDOM
741 +  This option adds a `random' match,
742 +  which allow you to match packets randomly
743 +  following a given probability.
744
745 +  If you want to compile it as a module, say M here and read
746 +  Documentation/modules.txt.  If unsure, say `N'.
747 +
748 +
749  MAC address match support
750  CONFIG_IP6_NF_MATCH_MAC
751    mac matching allows you to match packets based on the source
752 @@ -2988,6 +3638,14 @@
753    If you want to compile it as a module, say M here and read
754    Documentation/modules.txt.  If unsure, say `N'.
755  
756 +Condition variable match support
757 +CONFIG_IP6_NF_MATCH_CONDITION
758 +  This option allows you to match firewall rules against condition
759 +  variables stored in the /proc/net/ipt_condition directory.
760 +
761 +  If you want to compile it as a module, say M here and read
762 +  Documentation/modules.txt.  If unsure, say `N'.
763 +
764  Netfilter MARK match support
765  CONFIG_IP6_NF_MATCH_MARK
766    Netfilter mark matching allows you to match packets based on the
767 @@ -3031,6 +3689,35 @@
768    If you want to compile it as a module, say M here and read
769    <file:Documentation/modules.txt>.  If unsure, say `N'.
770  
771 +REJECT target support
772 +CONFIG_IP6_NF_TARGET_REJECT
773 +  The REJECT target allows a filtering rule to specify that an ICMPv6
774 +  error should be issued in response to an incoming packet, rather
775 +  than silently being dropped.
776 +
777 +  If you want to compile it as a module, say M here and read
778 +  Documentation/modules.txt.  If unsure, say `N'.
779 +
780 +raw table support (required for TRACE)
781 +CONFIG_IP6_NF_RAW
782 +  This option adds a `raw' table to ip6tables. This table is the very
783 +  first in the netfilter framework and hooks in at the PREROUTING
784 +  and OUTPUT chains.
785 +
786 +  If you want to compile it as a module, say M here and read
787 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
788 +
789 +TRACE target support
790 +CONFIG_IP6_NF_TARGET_TRACE
791 +  The TRACE target allows packets to be traced as those
792 +  matches any subsequent rule in any table/rule. The matched
793 +  rule and the packet is logged with the prefix
794 +
795 +  TRACE: tablename/chainname/rulenum  
796
797 +  If you want to compile it as a module, say M here and read
798 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
799 +
800  Packet filtering
801  CONFIG_IP6_NF_FILTER
802    Packet filtering defines a table `filter', which has a series of
803 @@ -3049,6 +3736,26 @@
804    If you want to compile it as a module, say M here and read
805    <file:Documentation/modules.txt>.  If unsure, say `N'.
806  
807 +IMQ target support
808 +CONFIG_IP6_NF_TARGET_IMQ
809 +  This option adds a `IMQ' target which is used to specify if and
810 +  to which imq device packets should get enqueued/dequeued.
811 +
812 +  If you want to compile it as a module, say M here and read
813 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
814 +
815 +ROUTE target support
816 +CONFIG_IP6_NF_TARGET_ROUTE
817 +  This option adds a `ROUTE' target, which enables you to setup unusual
818 +  routes. The ROUTE target is also able to change the incoming interface
819 +  of a packet.
820 +
821 +  The target can be or not a final target. It has to be used inside the 
822 +  mangle table.
823 +  
824 +  Not working as a module.
825 +
826 +
827  MARK target support
828  CONFIG_IP6_NF_TARGET_MARK
829    This option adds a `MARK' target, which allows you to create rules
830 @@ -3061,6 +3768,11 @@
831    If you want to compile it as a module, say M here and read
832    <file:Documentation/modules.txt>.  If unsure, say `N'.
833  
834 +ARP payload mangling
835 +CONFIG_IP_NF_ARP_MANGLE
836 +  Allows altering the ARP packet payload: source and destination
837 +  hardware and network addresses.
838 +
839  TCP Explicit Congestion Notification support
840  CONFIG_INET_ECN
841    Explicit Congestion Notification (ECN) allows routers to notify
842 @@ -3096,6 +3808,22 @@
843  
844    If you want to compile it as a module, say M here and read
845    <file:Documentation/modules.txt>.  If unsure, say `N'.
846 +
847 +HL match support
848 +CONFIG_IP6_NF_MATCH_HL
849 +  This option adds a `hl' match, which allows you match the value of
850 +  the IPv6 Hop Limit field.
851 +
852 +  If you want to compile it as a module, say M here and read
853 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
854 +
855 +HL target support
856 +CONFIG_IP6_NF_TARGET_HL
857 +  This option adds a `HL' target, which allows you to modify the value of
858 +  IPv6 Hop Limit field.
859 +
860 +  If you want to compile it as a module, say M here and read
861 +  <file:Documentation/modules.txt>.  If unsure, say `N'.
862  
863  LOG target support
864  CONFIG_IP6_NF_TARGET_LOG
865 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/jhash.h linux-2.4.20/include/linux/jhash.h
866 --- linux-2.4.20.org/include/linux/jhash.h      Thu Jan  1 00:00:00 1970
867 +++ linux-2.4.20/include/linux/jhash.h  Wed Sep 24 09:16:14 2003
868 @@ -0,0 +1,143 @@
869 +#ifndef _LINUX_JHASH_H
870 +#define _LINUX_JHASH_H
871 +
872 +/* jhash.h: Jenkins hash support.
873 + *
874 + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
875 + *
876 + * http://burtleburtle.net/bob/hash/
877 + *
878 + * These are the credits from Bob's sources:
879 + *
880 + * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
881 + * hash(), hash2(), hash3, and mix() are externally useful functions.
882 + * Routines to test the hash are included if SELF_TEST is defined.
883 + * You can use this free for any purpose.  It has no warranty.
884 + *
885 + * Copyright (C) 2003 David S. Miller (davem@redhat.com)
886 + *
887 + * I've modified Bob's hash to be useful in the Linux kernel, and
888 + * any bugs present are surely my fault.  -DaveM
889 + */
890 +
891 +/* NOTE: Arguments are modified. */
892 +#define __jhash_mix(a, b, c) \
893 +{ \
894 +  a -= b; a -= c; a ^= (c>>13); \
895 +  b -= c; b -= a; b ^= (a<<8); \
896 +  c -= a; c -= b; c ^= (b>>13); \
897 +  a -= b; a -= c; a ^= (c>>12);  \
898 +  b -= c; b -= a; b ^= (a<<16); \
899 +  c -= a; c -= b; c ^= (b>>5); \
900 +  a -= b; a -= c; a ^= (c>>3);  \
901 +  b -= c; b -= a; b ^= (a<<10); \
902 +  c -= a; c -= b; c ^= (b>>15); \
903 +}
904 +
905 +/* The golden ration: an arbitrary value */
906 +#define JHASH_GOLDEN_RATIO     0x9e3779b9
907 +
908 +/* The most generic version, hashes an arbitrary sequence
909 + * of bytes.  No alignment or length assumptions are made about
910 + * the input key.
911 + */
912 +static inline u32 jhash(void *key, u32 length, u32 initval)
913 +{
914 +       u32 a, b, c, len;
915 +       u8 *k = key;
916 +
917 +       len = length;
918 +       a = b = JHASH_GOLDEN_RATIO;
919 +       c = initval;
920 +
921 +       while (len >= 12) {
922 +               a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
923 +               b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
924 +               c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
925 +
926 +               __jhash_mix(a,b,c);
927 +
928 +               k += 12;
929 +               len -= 12;
930 +       }
931 +
932 +       c += length;
933 +       switch (len) {
934 +       case 11: c += ((u32)k[10]<<24);
935 +       case 10: c += ((u32)k[9]<<16);
936 +       case 9 : c += ((u32)k[8]<<8);
937 +       case 8 : b += ((u32)k[7]<<24);
938 +       case 7 : b += ((u32)k[6]<<16);
939 +       case 6 : b += ((u32)k[5]<<8);
940 +       case 5 : b += k[4];
941 +       case 4 : a += ((u32)k[3]<<24);
942 +       case 3 : a += ((u32)k[2]<<16);
943 +       case 2 : a += ((u32)k[1]<<8);
944 +       case 1 : a += k[0];
945 +       };
946 +
947 +       __jhash_mix(a,b,c);
948 +
949 +       return c;
950 +}
951 +
952 +/* A special optimized version that handles 1 or more of u32s.
953 + * The length parameter here is the number of u32s in the key.
954 + */
955 +static inline u32 jhash2(u32 *k, u32 length, u32 initval)
956 +{
957 +       u32 a, b, c, len;
958 +
959 +       a = b = JHASH_GOLDEN_RATIO;
960 +       c = initval;
961 +       len = length;
962 +
963 +       while (len >= 3) {
964 +               a += k[0];
965 +               b += k[1];
966 +               c += k[2];
967 +               __jhash_mix(a, b, c);
968 +               k += 3; len -= 3;
969 +       }
970 +
971 +       c += length * 4;
972 +
973 +       switch (len) {
974 +       case 2 : b += k[1];
975 +       case 1 : a += k[0];
976 +       };
977 +
978 +       __jhash_mix(a,b,c);
979 +
980 +       return c;
981 +}
982 +
983 +
984 +/* A special ultra-optimized versions that knows they are hashing exactly
985 + * 3, 2 or 1 word(s).
986 + *
987 + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
988 + *       done at the end is not done here.
989 + */
990 +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
991 +{
992 +       a += JHASH_GOLDEN_RATIO;
993 +       b += JHASH_GOLDEN_RATIO;
994 +       c += initval;
995 +
996 +       __jhash_mix(a, b, c);
997 +
998 +       return c;
999 +}
1000 +
1001 +static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
1002 +{
1003 +       return jhash_3words(a, b, 0, initval);
1004 +}
1005 +
1006 +static inline u32 jhash_1word(u32 a, u32 initval)
1007 +{
1008 +       return jhash_3words(a, 0, 0, initval);
1009 +}
1010 +
1011 +#endif /* _LINUX_JHASH_H */
1012 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter.h linux-2.4.20/include/linux/netfilter.h
1013 --- linux-2.4.20.org/include/linux/netfilter.h  Thu Nov 22 19:47:48 2001
1014 +++ linux-2.4.20/include/linux/netfilter.h      Wed Sep 24 09:18:12 2003
1015 @@ -19,9 +19,11 @@
1016  #define NF_REPEAT 4
1017  #define NF_MAX_VERDICT NF_REPEAT
1018  
1019 -/* Generic cache responses from hook functions. */
1020 -#define NFC_ALTERED 0x8000
1021 +/* Generic cache responses from hook functions.
1022 +   <= 0x2000 is used for protocol-flags. */
1023  #define NFC_UNKNOWN 0x4000
1024 +#define NFC_ALTERED 0x8000
1025 +#define NFC_TRACE   0x10000
1026  
1027  #ifdef __KERNEL__
1028  #include <linux/config.h>
1029 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_arp/arpt_mangle.h linux-2.4.20/include/linux/netfilter_arp/arpt_mangle.h
1030 --- linux-2.4.20.org/include/linux/netfilter_arp/arpt_mangle.h  Thu Jan  1 00:00:00 1970
1031 +++ linux-2.4.20/include/linux/netfilter_arp/arpt_mangle.h      Wed Sep 24 09:16:17 2003
1032 @@ -0,0 +1,26 @@
1033 +#ifndef _ARPT_MANGLE_H
1034 +#define _ARPT_MANGLE_H
1035 +#include <linux/netfilter_arp/arp_tables.h>
1036 +
1037 +#define ARPT_MANGLE_ADDR_LEN_MAX sizeof(struct in_addr)
1038 +struct arpt_mangle
1039 +{
1040 +       char src_devaddr[ARPT_DEV_ADDR_LEN_MAX];
1041 +       char tgt_devaddr[ARPT_DEV_ADDR_LEN_MAX];
1042 +       union {
1043 +               struct in_addr src_ip;
1044 +       } u_s;
1045 +       union {
1046 +               struct in_addr tgt_ip;
1047 +       } u_t;
1048 +       u_int8_t flags;
1049 +       int target;
1050 +};
1051 +
1052 +#define ARPT_MANGLE_SDEV 0x01
1053 +#define ARPT_MANGLE_TDEV 0x02
1054 +#define ARPT_MANGLE_SIP 0x04
1055 +#define ARPT_MANGLE_TIP 0x08
1056 +#define ARPT_MANGLE_MASK 0x0f
1057 +
1058 +#endif /* _ARPT_MANGLE_H */
1059 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack.h
1060 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack.h        Thu Nov 28 23:53:15 2002
1061 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack.h    Wed Sep 24 09:18:16 2003
1062 @@ -6,6 +6,7 @@
1063  
1064  #include <linux/config.h>
1065  #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
1066 +#include <linux/bitops.h>
1067  #include <asm/atomic.h>
1068  
1069  enum ip_conntrack_info
1070 @@ -41,29 +42,50 @@
1071         /* Conntrack should never be early-expired. */
1072         IPS_ASSURED_BIT = 2,
1073         IPS_ASSURED = (1 << IPS_ASSURED_BIT),
1074 +
1075 +       /* Connection is confirmed: originating packet has left box */
1076 +       IPS_CONFIRMED_BIT = 3,
1077 +       IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
1078  };
1079  
1080  #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
1081  #include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
1082 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
1083  
1084  /* per conntrack: protocol private data */
1085  union ip_conntrack_proto {
1086         /* insert conntrack proto private data here */
1087 +       struct ip_ct_gre gre;
1088         struct ip_ct_tcp tcp;
1089         struct ip_ct_icmp icmp;
1090  };
1091  
1092  union ip_conntrack_expect_proto {
1093         /* insert expect proto private data here */
1094 +       struct ip_ct_gre_expect gre;
1095  };
1096  
1097  /* Add protocol helper include file here */
1098 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
1099 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
1100 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
1101 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
1102 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
1103 +
1104 +#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
1105 +
1106  #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
1107  #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
1108  
1109  /* per expectation: application helper private data */
1110  union ip_conntrack_expect_help {
1111         /* insert conntrack helper private data (expect) here */
1112 +       struct ip_ct_talk_expect exp_talk_info;
1113 +       struct ip_ct_rsh_expect exp_rsh_info;
1114 +       struct ip_ct_pptp_expect exp_pptp_info;
1115 +       struct ip_ct_mms_expect exp_mms_info;
1116 +       struct ip_ct_h225_expect exp_h225_info;
1117 +       struct ip_ct_amanda_expect exp_amanda_info;
1118         struct ip_ct_ftp_expect exp_ftp_info;
1119         struct ip_ct_irc_expect exp_irc_info;
1120  
1121 @@ -77,16 +99,23 @@
1122  /* per conntrack: application helper private data */
1123  union ip_conntrack_help {
1124         /* insert conntrack helper private data (master) here */
1125 +       struct ip_ct_talk_master ct_talk_info;
1126 +       struct ip_ct_rsh_master ct_rsh_info;
1127 +       struct ip_ct_pptp_master ct_pptp_info;
1128 +       struct ip_ct_mms_master ct_mms_info;
1129 +       struct ip_ct_h225_master ct_h225_info;
1130         struct ip_ct_ftp_master ct_ftp_info;
1131         struct ip_ct_irc_master ct_irc_info;
1132  };
1133  
1134  #ifdef CONFIG_IP_NF_NAT_NEEDED
1135  #include <linux/netfilter_ipv4/ip_nat.h>
1136 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
1137  
1138  /* per conntrack: nat application helper private data */
1139  union ip_conntrack_nat_help {
1140         /* insert nat helper private data here */
1141 +       struct ip_nat_pptp nat_pptp_info;
1142  };
1143  #endif
1144  
1145 @@ -159,7 +188,7 @@
1146         struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
1147  
1148         /* Have we seen traffic both ways yet? (bitset) */
1149 -       volatile unsigned long status;
1150 +       unsigned long status;
1151  
1152         /* Timer function; drops refcnt when it goes off. */
1153         struct timer_list timeout;
1154 @@ -198,6 +227,9 @@
1155         } nat;
1156  #endif /* CONFIG_IP_NF_NAT_NEEDED */
1157  
1158 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
1159 +       unsigned long mark;
1160 +#endif
1161  };
1162  
1163  /* get master conntrack via master expectation */
1164 @@ -238,6 +270,9 @@
1165  extern void ip_ct_refresh(struct ip_conntrack *ct,
1166                           unsigned long extra_jiffies);
1167  
1168 +/* Kill conntrack */
1169 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
1170 +
1171  /* These are for NAT.  Icky. */
1172  /* Call me when a conntrack is destroyed. */
1173  extern void (*ip_conntrack_destroyed)(struct ip_conntrack *conntrack);
1174 @@ -254,9 +289,12 @@
1175  /* It's confirmed if it is, or has been in the hash table. */
1176  static inline int is_confirmed(struct ip_conntrack *ct)
1177  {
1178 -       return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL;
1179 +       return test_bit(IPS_CONFIRMED_BIT, &ct->status);
1180  }
1181  
1182  extern unsigned int ip_conntrack_htable_size;
1183 +
1184 +/* A fake conntrack entry which never vanishes. */
1185 +extern struct ip_conntrack ip_conntrack_untracked;
1186  #endif /* __KERNEL__ */
1187  #endif /* _IP_CONNTRACK_H */
1188 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_amanda.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_amanda.h
1189 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_amanda.h Thu Jan  1 00:00:00 1970
1190 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_amanda.h     Wed Sep 24 09:16:14 2003
1191 @@ -0,0 +1,29 @@
1192 +#ifndef _IP_CONNTRACK_AMANDA_H
1193 +#define _IP_CONNTRACK_AMANDA_H
1194 +/* AMANDA tracking. */
1195 +
1196 +#ifdef __KERNEL__
1197 +
1198 +#include <linux/netfilter_ipv4/lockhelp.h>
1199 +
1200 +/* Protects amanda part of conntracks */
1201 +DECLARE_LOCK_EXTERN(ip_amanda_lock);
1202 +
1203 +#endif
1204 +
1205 +struct conn {
1206 +       char* match;
1207 +       int matchlen;
1208 +};
1209 +
1210 +#define NUM_MSGS       3
1211 +
1212 +
1213 +struct ip_ct_amanda_expect
1214 +{
1215 +       u_int16_t port;         /* port number of this expectation */
1216 +       u_int16_t offset;       /* offset of the port specification in ctrl packet */
1217 +       u_int16_t len;          /* the length of the port number specification */
1218 +};
1219 +
1220 +#endif /* _IP_CONNTRACK_AMANDA_H */
1221 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_core.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_core.h
1222 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_core.h   Thu Nov 28 23:53:15 2002
1223 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_core.h       Wed Sep 24 09:16:17 2003
1224 @@ -1,5 +1,6 @@
1225  #ifndef _IP_CONNTRACK_CORE_H
1226  #define _IP_CONNTRACK_CORE_H
1227 +#include <linux/netfilter.h>
1228  #include <linux/netfilter_ipv4/lockhelp.h>
1229  
1230  /* This header is used to share core functionality between the
1231 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h
1232 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h        Thu Jan  1 00:00:00 1970
1233 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_cuseeme.h    Wed Sep 24 09:17:38 2003
1234 @@ -0,0 +1,70 @@
1235 +#ifndef _IP_CT_CUSEEME
1236 +#define _IP_CT_CUSEEME
1237 +
1238 +#define CUSEEME_PORT 7648
1239 +
1240 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
1241 +
1242 +#pragma pack(1)
1243 +/* CuSeeMe data header */
1244 +struct cu_header {
1245 +       u_int16_t       dest_family;
1246 +       u_int16_t       dest_port;
1247 +       u_int32_t       dest_addr;
1248 +       int16_t         family;
1249 +       u_int16_t       port;
1250 +       u_int32_t       addr;
1251 +       u_int32_t       seq;
1252 +       u_int16_t       msg;
1253 +       u_int16_t       data_type;
1254 +                               /* possible values:
1255 +                                * 1    small video
1256 +                                * 2    big video
1257 +                                * 3    audio
1258 +                                * 100  acknowledge connectivity when there
1259 +                                *      is nothing else to send
1260 +                                * 101  OpenContinue packet
1261 +                                * 104  display a text message and 
1262 +                                *      disconnect (used by reflector to
1263 +                                *      kick clients off)
1264 +                                * 105  display a text message (welcome
1265 +                                *      message from reflector)
1266 +                                * 106  exchanged among reflectors for
1267 +                                *      reflector interoperation
1268 +                                * 107  carry aux stream data when there is
1269 +                                *      no video to piggy-back on
1270 +                                * 108  obsolete (used in Mac alpha version)
1271 +                                * 109  obsolete (used in Mac alpha version)
1272 +                                * 110  used for data rate control
1273 +                                * 111  used for data rate control
1274 +                                * 256  aux data control messages
1275 +                                * 257  aux data packets
1276 +                                * */
1277 +       u_int16_t       packet_len;
1278 +};
1279 +
1280 +/* Open Continue Header */
1281 +struct oc_header {
1282 +       struct cu_header        cu_head;
1283 +       u_int16_t       client_count; /* Number of client info structs */
1284 +       u_int32_t       seq_no;
1285 +       char            user_name[20];
1286 +       char            stuff[4];     /* Flags, version stuff, etc */
1287 +};
1288 +
1289 +/* Client info structures */
1290 +struct client_info {
1291 +       u_int32_t       address;      /* Client address */
1292 +       char            stuff[8];     /* Flags, pruning bitfield, packet counts, etc */
1293 +};
1294 +#pragma pack()
1295 +
1296 +/* This structure is per expected connection */
1297 +struct ip_ct_cuseeme_expect {
1298 +};
1299 +
1300 +/* This structure exists only once per master */
1301 +struct ip_ct_cuseeme_master {
1302 +};
1303 +
1304 +#endif /* _IP_CT_CUSEEME */
1305 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_h323.h
1306 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_h323.h   Thu Jan  1 00:00:00 1970
1307 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_h323.h       Wed Sep 24 09:17:43 2003
1308 @@ -0,0 +1,30 @@
1309 +#ifndef _IP_CONNTRACK_H323_H
1310 +#define _IP_CONNTRACK_H323_H
1311 +/* H.323 connection tracking. */
1312 +
1313 +#ifdef __KERNEL__
1314 +/* Protects H.323 related data */
1315 +DECLARE_LOCK_EXTERN(ip_h323_lock);
1316 +#endif
1317 +
1318 +/* Default H.225 port */
1319 +#define H225_PORT      1720
1320 +
1321 +/* This structure is per expected connection */
1322 +struct ip_ct_h225_expect {
1323 +       u_int16_t port;                 /* Port of the H.225 helper/RTCP/RTP channel */
1324 +       enum ip_conntrack_dir dir;      /* Direction of the original connection */
1325 +       unsigned int offset;            /* offset of the address in the payload */
1326 +};
1327 +
1328 +/* This structure exists only once per master */
1329 +struct ip_ct_h225_master {
1330 +       int is_h225;                            /* H.225 or H.245 connection */
1331 +#ifdef CONFIG_IP_NF_NAT_NEEDED
1332 +       enum ip_conntrack_dir dir;              /* Direction of the original connection */
1333 +       u_int32_t seq[IP_CT_DIR_MAX];           /* Exceptional packet mangling for signal addressess... */
1334 +       unsigned int offset[IP_CT_DIR_MAX];     /* ...and the offset of the addresses in the payload */
1335 +#endif
1336 +};
1337 +
1338 +#endif /* _IP_CONNTRACK_H323_H */
1339 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_mms.h
1340 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_mms.h    Thu Jan  1 00:00:00 1970
1341 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_mms.h        Wed Sep 24 09:17:48 2003
1342 @@ -0,0 +1,31 @@
1343 +#ifndef _IP_CONNTRACK_MMS_H
1344 +#define _IP_CONNTRACK_MMS_H
1345 +/* MMS tracking. */
1346 +
1347 +#ifdef __KERNEL__
1348 +#include <linux/netfilter_ipv4/lockhelp.h>
1349 +
1350 +DECLARE_LOCK_EXTERN(ip_mms_lock);
1351 +
1352 +#define MMS_PORT                         1755
1353 +#define MMS_SRV_MSG_ID                   196610
1354 +
1355 +#define MMS_SRV_MSG_OFFSET               36
1356 +#define MMS_SRV_UNICODE_STRING_OFFSET    60
1357 +#define MMS_SRV_CHUNKLENLV_OFFSET        16
1358 +#define MMS_SRV_CHUNKLENLM_OFFSET        32
1359 +#define MMS_SRV_MESSAGELENGTH_OFFSET     8
1360 +#endif
1361 +
1362 +/* This structure is per expected connection */
1363 +struct ip_ct_mms_expect {
1364 +       u_int32_t len;
1365 +       u_int32_t padding;
1366 +       u_int16_t port;
1367 +};
1368 +
1369 +/* This structure exists only once per master */
1370 +struct ip_ct_mms_master {
1371 +};
1372 +
1373 +#endif /* _IP_CONNTRACK_MMS_H */
1374 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_pptp.h
1375 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_pptp.h   Thu Jan  1 00:00:00 1970
1376 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_pptp.h       Wed Sep 24 09:17:55 2003
1377 @@ -0,0 +1,313 @@
1378 +/* PPTP constants and structs */
1379 +#ifndef _CONNTRACK_PPTP_H
1380 +#define _CONNTRACK_PPTP_H
1381 +
1382 +/* state of the control session */
1383 +enum pptp_ctrlsess_state {
1384 +       PPTP_SESSION_NONE,                      /* no session present */
1385 +       PPTP_SESSION_ERROR,                     /* some session error */
1386 +       PPTP_SESSION_STOPREQ,                   /* stop_sess request seen */
1387 +       PPTP_SESSION_REQUESTED,                 /* start_sess request seen */
1388 +       PPTP_SESSION_CONFIRMED,                 /* session established */
1389 +};
1390 +
1391 +/* state of the call inside the control session */
1392 +enum pptp_ctrlcall_state {
1393 +       PPTP_CALL_NONE,
1394 +       PPTP_CALL_ERROR,
1395 +       PPTP_CALL_OUT_REQ,
1396 +       PPTP_CALL_OUT_CONF,
1397 +       PPTP_CALL_IN_REQ,
1398 +       PPTP_CALL_IN_REP,
1399 +       PPTP_CALL_IN_CONF,
1400 +       PPTP_CALL_CLEAR_REQ,
1401 +};
1402 +
1403 +
1404 +/* conntrack private data */
1405 +struct ip_ct_pptp_master {
1406 +       enum pptp_ctrlsess_state sstate;        /* session state */
1407 +
1408 +       /* everything below is going to be per-expectation in newnat,
1409 +        * since there could be more than one call within one session */
1410 +       enum pptp_ctrlcall_state cstate;        /* call state */
1411 +       u_int16_t pac_call_id;                  /* call id of PAC, host byte order */
1412 +       u_int16_t pns_call_id;                  /* call id of PNS, host byte order */
1413 +};
1414 +
1415 +/* conntrack_expect private member */
1416 +struct ip_ct_pptp_expect {
1417 +       enum pptp_ctrlcall_state cstate;        /* call state */
1418 +       u_int16_t pac_call_id;                  /* call id of PAC */
1419 +       u_int16_t pns_call_id;                  /* call id of PNS */
1420 +};
1421 +
1422 +
1423 +#ifdef __KERNEL__
1424 +
1425 +#include <linux/netfilter_ipv4/lockhelp.h>
1426 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
1427 +
1428 +#define IP_CONNTR_PPTP         PPTP_CONTROL_PORT
1429 +
1430 +union pptp_ctrl_union {
1431 +                void                           *rawreq;
1432 +               struct PptpStartSessionRequest  *sreq;
1433 +               struct PptpStartSessionReply    *srep;
1434 +               struct PptpStopSessionReqest    *streq;
1435 +               struct PptpStopSessionReply     *strep;
1436 +                struct PptpOutCallRequest       *ocreq;
1437 +                struct PptpOutCallReply         *ocack;
1438 +                struct PptpInCallRequest        *icreq;
1439 +                struct PptpInCallReply          *icack;
1440 +                struct PptpInCallConnected      *iccon;
1441 +               struct PptpClearCallRequest     *clrreq;
1442 +                struct PptpCallDisconnectNotify *disc;
1443 +                struct PptpWanErrorNotify       *wanerr;
1444 +                struct PptpSetLinkInfo          *setlink;
1445 +};
1446 +
1447 +
1448 +
1449 +#define PPTP_CONTROL_PORT      1723
1450 +
1451 +#define PPTP_PACKET_CONTROL    1
1452 +#define PPTP_PACKET_MGMT       2
1453 +
1454 +#define PPTP_MAGIC_COOKIE      0x1a2b3c4d
1455 +
1456 +struct pptp_pkt_hdr {
1457 +       __u16   packetLength;
1458 +       __u16   packetType;
1459 +       __u32   magicCookie;
1460 +};
1461 +
1462 +/* PptpControlMessageType values */
1463 +#define PPTP_START_SESSION_REQUEST     1
1464 +#define PPTP_START_SESSION_REPLY       2
1465 +#define PPTP_STOP_SESSION_REQUEST      3
1466 +#define PPTP_STOP_SESSION_REPLY                4
1467 +#define PPTP_ECHO_REQUEST              5
1468 +#define PPTP_ECHO_REPLY                        6
1469 +#define PPTP_OUT_CALL_REQUEST          7
1470 +#define PPTP_OUT_CALL_REPLY            8
1471 +#define PPTP_IN_CALL_REQUEST           9
1472 +#define PPTP_IN_CALL_REPLY             10
1473 +#define PPTP_IN_CALL_CONNECT           11
1474 +#define PPTP_CALL_CLEAR_REQUEST                12
1475 +#define PPTP_CALL_DISCONNECT_NOTIFY    13
1476 +#define PPTP_WAN_ERROR_NOTIFY          14
1477 +#define PPTP_SET_LINK_INFO             15
1478 +
1479 +#define PPTP_MSG_MAX                   15
1480 +
1481 +/* PptpGeneralError values */
1482 +#define PPTP_ERROR_CODE_NONE           0
1483 +#define PPTP_NOT_CONNECTED             1
1484 +#define PPTP_BAD_FORMAT                        2
1485 +#define PPTP_BAD_VALUE                 3
1486 +#define PPTP_NO_RESOURCE               4
1487 +#define PPTP_BAD_CALLID                        5
1488 +#define PPTP_REMOVE_DEVICE_ERROR       6
1489 +
1490 +struct PptpControlHeader {
1491 +       __u16   messageType;
1492 +       __u16   reserved;
1493 +};
1494 +
1495 +/* FramingCapability Bitmap Values */
1496 +#define PPTP_FRAME_CAP_ASYNC           0x1
1497 +#define PPTP_FRAME_CAP_SYNC            0x2
1498 +
1499 +/* BearerCapability Bitmap Values */
1500 +#define PPTP_BEARER_CAP_ANALOG         0x1
1501 +#define PPTP_BEARER_CAP_DIGITAL                0x2
1502 +
1503 +struct PptpStartSessionRequest {
1504 +       __u16   protocolVersion;
1505 +       __u8    reserved1;
1506 +       __u8    reserved2;
1507 +       __u32   framingCapability;
1508 +       __u32   bearerCapability;
1509 +       __u16   maxChannels;
1510 +       __u16   firmwareRevision;
1511 +       __u8    hostName[64];
1512 +       __u8    vendorString[64];
1513 +};
1514 +
1515 +/* PptpStartSessionResultCode Values */
1516 +#define PPTP_START_OK                  1
1517 +#define PPTP_START_GENERAL_ERROR       2
1518 +#define PPTP_START_ALREADY_CONNECTED   3
1519 +#define PPTP_START_NOT_AUTHORIZED      4
1520 +#define PPTP_START_UNKNOWN_PROTOCOL    5
1521 +
1522 +struct PptpStartSessionReply {
1523 +       __u16   protocolVersion;
1524 +       __u8    resultCode;
1525 +       __u8    generalErrorCode;
1526 +       __u32   framingCapability;
1527 +       __u32   bearerCapability;
1528 +       __u16   maxChannels;
1529 +       __u16   firmwareRevision;
1530 +       __u8    hostName[64];
1531 +       __u8    vendorString[64];
1532 +};
1533 +
1534 +/* PptpStopReasons */
1535 +#define PPTP_STOP_NONE                 1
1536 +#define PPTP_STOP_PROTOCOL             2
1537 +#define PPTP_STOP_LOCAL_SHUTDOWN       3
1538 +
1539 +struct PptpStopSessionRequest {
1540 +       __u8    reason;
1541 +};
1542 +
1543 +/* PptpStopSessionResultCode */
1544 +#define PPTP_STOP_OK                   1
1545 +#define PPTP_STOP_GENERAL_ERROR                2
1546 +
1547 +struct PptpStopSessionReply {
1548 +       __u8    resultCode;
1549 +       __u8    generalErrorCode;
1550 +};
1551 +
1552 +struct PptpEchoRequest {
1553 +       __u32 identNumber;
1554 +};
1555 +
1556 +/* PptpEchoReplyResultCode */
1557 +#define PPTP_ECHO_OK                   1
1558 +#define PPTP_ECHO_GENERAL_ERROR                2
1559 +
1560 +struct PptpEchoReply {
1561 +       __u32   identNumber;
1562 +       __u8    resultCode;
1563 +       __u8    generalErrorCode;
1564 +       __u16   reserved;
1565 +};
1566 +
1567 +/* PptpFramingType */
1568 +#define PPTP_ASYNC_FRAMING             1
1569 +#define PPTP_SYNC_FRAMING              2
1570 +#define PPTP_DONT_CARE_FRAMING         3
1571 +
1572 +/* PptpCallBearerType */
1573 +#define PPTP_ANALOG_TYPE               1
1574 +#define PPTP_DIGITAL_TYPE              2
1575 +#define PPTP_DONT_CARE_BEARER_TYPE     3
1576 +
1577 +struct PptpOutCallRequest {
1578 +       __u16   callID;
1579 +       __u16   callSerialNumber;
1580 +       __u32   minBPS;
1581 +       __u32   maxBPS;
1582 +       __u32   bearerType;
1583 +       __u32   framingType;
1584 +       __u16   packetWindow;
1585 +       __u16   packetProcDelay;
1586 +       __u16   reserved1;
1587 +       __u16   phoneNumberLength;
1588 +       __u16   reserved2;
1589 +       __u8    phoneNumber[64];
1590 +       __u8    subAddress[64];
1591 +};
1592 +
1593 +/* PptpCallResultCode */
1594 +#define PPTP_OUTCALL_CONNECT           1
1595 +#define PPTP_OUTCALL_GENERAL_ERROR     2
1596 +#define PPTP_OUTCALL_NO_CARRIER                3
1597 +#define PPTP_OUTCALL_BUSY              4
1598 +#define PPTP_OUTCALL_NO_DIAL_TONE      5
1599 +#define PPTP_OUTCALL_TIMEOUT           6
1600 +#define PPTP_OUTCALL_DONT_ACCEPT       7
1601 +
1602 +struct PptpOutCallReply {
1603 +       __u16   callID;
1604 +       __u16   peersCallID;
1605 +       __u8    resultCode;
1606 +       __u8    generalErrorCode;
1607 +       __u16   causeCode;
1608 +       __u32   connectSpeed;
1609 +       __u16   packetWindow;
1610 +       __u16   packetProcDelay;
1611 +       __u32   physChannelID;
1612 +};
1613 +
1614 +struct PptpInCallRequest {
1615 +       __u16   callID;
1616 +       __u16   callSerialNumber;
1617 +       __u32   callBearerType;
1618 +       __u32   physChannelID;
1619 +       __u16   dialedNumberLength;
1620 +       __u16   dialingNumberLength;
1621 +       __u8    dialedNumber[64];
1622 +       __u8    dialingNumber[64];
1623 +       __u8    subAddress[64];
1624 +};
1625 +
1626 +/* PptpInCallResultCode */
1627 +#define PPTP_INCALL_ACCEPT             1
1628 +#define PPTP_INCALL_GENERAL_ERROR      2
1629 +#define PPTP_INCALL_DONT_ACCEPT                3
1630 +
1631 +struct PptpInCallReply {
1632 +       __u16   callID;
1633 +       __u16   peersCallID;
1634 +       __u8    resultCode;
1635 +       __u8    generalErrorCode;
1636 +       __u16   packetWindow;
1637 +       __u16   packetProcDelay;
1638 +       __u16   reserved;
1639 +};
1640 +
1641 +struct PptpInCallConnected {
1642 +       __u16   peersCallID;
1643 +       __u16   reserved;
1644 +       __u32   connectSpeed;
1645 +       __u16   packetWindow;
1646 +       __u16   packetProcDelay;
1647 +       __u32   callFramingType;
1648 +};
1649 +
1650 +struct PptpClearCallRequest {
1651 +       __u16   callID;
1652 +       __u16   reserved;
1653 +};
1654 +
1655 +struct PptpCallDisconnectNotify {
1656 +       __u16   callID;
1657 +       __u8    resultCode;
1658 +       __u8    generalErrorCode;
1659 +       __u16   causeCode;
1660 +       __u16   reserved;
1661 +       __u8    callStatistics[128];
1662 +};
1663 +
1664 +struct PptpWanErrorNotify {
1665 +       __u16   peersCallID;
1666 +       __u16   reserved;
1667 +       __u32   crcErrors;
1668 +       __u32   framingErrors;
1669 +       __u32   hardwareOverRuns;
1670 +       __u32   bufferOverRuns;
1671 +       __u32   timeoutErrors;
1672 +       __u32   alignmentErrors;
1673 +};
1674 +
1675 +struct PptpSetLinkInfo {
1676 +       __u16   peersCallID;
1677 +       __u16   reserved;
1678 +       __u32   sendAccm;
1679 +       __u32   recvAccm;
1680 +};
1681 +
1682 +
1683 +struct pptp_priv_data {
1684 +       __u16   call_id;
1685 +       __u16   mcall_id;
1686 +       __u16   pcall_id;
1687 +};
1688 +
1689 +#endif /* __KERNEL__ */
1690 +#endif /* _CONNTRACK_PPTP_H */
1691 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
1692 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h      Thu Jan  1 00:00:00 1970
1693 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h  Wed Sep 24 09:17:55 2003
1694 @@ -0,0 +1,123 @@
1695 +#ifndef _CONNTRACK_PROTO_GRE_H
1696 +#define _CONNTRACK_PROTO_GRE_H
1697 +#include <asm/byteorder.h>
1698 +
1699 +/* GRE PROTOCOL HEADER */
1700 +
1701 +/* GRE Version field */
1702 +#define GRE_VERSION_1701       0x0
1703 +#define GRE_VERSION_PPTP       0x1
1704 +
1705 +/* GRE Protocol field */
1706 +#define GRE_PROTOCOL_PPTP      0x880B
1707 +
1708 +/* GRE Flags */
1709 +#define GRE_FLAG_C             0x80
1710 +#define GRE_FLAG_R             0x40
1711 +#define GRE_FLAG_K             0x20
1712 +#define GRE_FLAG_S             0x10
1713 +#define GRE_FLAG_A             0x80
1714 +
1715 +#define GRE_IS_C(f)    ((f)&GRE_FLAG_C)
1716 +#define GRE_IS_R(f)    ((f)&GRE_FLAG_R)
1717 +#define GRE_IS_K(f)    ((f)&GRE_FLAG_K)
1718 +#define GRE_IS_S(f)    ((f)&GRE_FLAG_S)
1719 +#define GRE_IS_A(f)    ((f)&GRE_FLAG_A)
1720 +
1721 +/* GRE is a mess: Four different standards */
1722 +struct gre_hdr {
1723 +#if defined(__LITTLE_ENDIAN_BITFIELD)
1724 +       __u16   rec:3,
1725 +               srr:1,
1726 +               seq:1,
1727 +               key:1,
1728 +               routing:1,
1729 +               csum:1,
1730 +               version:3,
1731 +               reserved:4,
1732 +               ack:1;
1733 +#elif defined(__BIG_ENDIAN_BITFIELD)
1734 +       __u16   csum:1,
1735 +               routing:1,
1736 +               key:1,
1737 +               seq:1,
1738 +               srr:1,
1739 +               rec:3,
1740 +               ack:1,
1741 +               reserved:4,
1742 +               version:3;
1743 +#else
1744 +#error "Adjust your <asm/byteorder.h> defines"
1745 +#endif
1746 +       __u16   protocol;
1747 +};
1748 +
1749 +/* modified GRE header for PPTP */
1750 +struct gre_hdr_pptp {
1751 +       __u8  flags;            /* bitfield */
1752 +       __u8  version;          /* should be GRE_VERSION_PPTP */
1753 +       __u16 protocol;         /* should be GRE_PROTOCOL_PPTP */
1754 +       __u16 payload_len;      /* size of ppp payload, not inc. gre header */
1755 +       __u16 call_id;          /* peer's call_id for this session */
1756 +       __u32 seq;              /* sequence number.  Present if S==1 */
1757 +       __u32 ack;              /* seq number of highest packet recieved by */
1758 +                               /*  sender in this session */
1759 +};
1760 +
1761 +
1762 +/* this is part of ip_conntrack */
1763 +struct ip_ct_gre {
1764 +       unsigned int stream_timeout;
1765 +       unsigned int timeout;
1766 +};
1767 +
1768 +/* this is part of ip_conntrack_expect */
1769 +struct ip_ct_gre_expect {
1770 +       struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
1771 +};
1772 +
1773 +#ifdef __KERNEL__
1774 +struct ip_conntrack_expect;
1775 +
1776 +/* structure for original <-> reply keymap */
1777 +struct ip_ct_gre_keymap {
1778 +       struct list_head list;
1779 +
1780 +       struct ip_conntrack_tuple tuple;
1781 +};
1782 +
1783 +
1784 +/* add new tuple->key_reply pair to keymap */
1785 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
1786 +                        struct ip_conntrack_tuple *t,
1787 +                        int reply);
1788 +
1789 +/* change an existing keymap entry */
1790 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
1791 +                            struct ip_conntrack_tuple *t);
1792 +
1793 +/* delete keymap entries */
1794 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
1795 +
1796 +
1797 +/* get pointer to gre key, if present */
1798 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
1799 +{
1800 +       if (!greh->key)
1801 +               return NULL;
1802 +       if (greh->csum || greh->routing)
1803 +               return (u_int32_t *) (greh+sizeof(*greh)+4);
1804 +       return (u_int32_t *) (greh+sizeof(*greh));
1805 +}
1806 +
1807 +/* get pointer ot gre csum, if present */
1808 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
1809 +{
1810 +       if (!greh->csum)
1811 +               return NULL;
1812 +       return (u_int16_t *) (greh+sizeof(*greh));
1813 +}
1814 +
1815 +#endif /* __KERNEL__ */
1816 +
1817 +#endif /* _CONNTRACK_PROTO_GRE_H */
1818 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
1819 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_protocol.h       Thu Nov 28 23:53:15 2002
1820 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_protocol.h   Wed Sep 24 09:18:12 2003
1821 @@ -57,6 +57,12 @@
1822  extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
1823  extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
1824  
1825 +/* Get the tuple from the packet and return 1 if it's succeeded. */
1826 +extern int
1827 +ip_conntrack_get_tuple(const struct iphdr *iph, size_t len,
1828 +                      struct ip_conntrack_tuple *tuple,
1829 +                      struct ip_conntrack_protocol *protocol);
1830 +
1831  /* Existing built-in protocols */
1832  extern struct ip_conntrack_protocol ip_conntrack_protocol_tcp;
1833  extern struct ip_conntrack_protocol ip_conntrack_protocol_udp;
1834 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_quake3.h
1835 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_quake3.h Thu Jan  1 00:00:00 1970
1836 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_quake3.h     Wed Sep 24 09:17:58 2003
1837 @@ -0,0 +1,21 @@
1838 +#ifndef _IP_CT_QUAKE3
1839 +#define _IP_CT_QUAKE3
1840 +
1841 +/* Don't confuse with 27960, often used as the Server Port */
1842 +#define QUAKE3_MASTER_PORT 27950
1843 +
1844 +struct quake3_search {
1845 +       const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
1846 +       const char *pattern;
1847 +       size_t plen;
1848 +}; 
1849 +
1850 +/* This structure is per expected connection */
1851 +struct ip_ct_quake3_expect {
1852 +};
1853 +
1854 +/* This structure exists only once per master */
1855 +struct ip_ct_quake3_master {
1856 +};
1857 +
1858 +#endif /* _IP_CT_QUAKE3 */
1859 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_rpc.h
1860 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_rpc.h    Thu Jan  1 00:00:00 1970
1861 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_rpc.h        Wed Sep 24 09:18:01 2003
1862 @@ -0,0 +1,68 @@
1863 +/* RPC extension for IP connection tracking, Version 2.2
1864 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
1865 + *     - original rpc tracking module
1866 + *     - "recent" connection handling for kernel 2.3+ netfilter
1867 + *
1868 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1869 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
1870 + *
1871 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1872 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
1873 + *     - extended matching to support filtering on procedures
1874 + *
1875 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
1876 + *
1877 + *     This program is free software; you can redistribute it and/or
1878 + *     modify it under the terms of the GNU General Public License
1879 + *     as published by the Free Software Foundation; either version
1880 + *     2 of the License, or (at your option) any later version.
1881 + **
1882 + */
1883 +
1884 +#include <asm/param.h>
1885 +#include <linux/sched.h>
1886 +#include <linux/timer.h>
1887 +#include <linux/stddef.h>
1888 +#include <linux/list.h>
1889 +
1890 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1891 +
1892 +#ifndef _IP_CONNTRACK_RPC_H
1893 +#define _IP_CONNTRACK_RPC_H
1894 +
1895 +#define RPC_PORT       111
1896 +
1897 +
1898 +/* Datum in RPC packets are encoded in XDR */
1899 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
1900 +
1901 +/* Fast timeout, to deny DoS atacks */
1902 +#define EXP (60 * HZ)
1903 +
1904 +/* Normal timeouts */
1905 +#define EXPIRES (180 * HZ)
1906 +
1907 +/* For future conections RPC, using client's cache bindings
1908 + * I'll use ip_conntrack_lock to lock these lists      */
1909 +
1910 +/* This identifies each request and stores protocol */
1911 +struct request_p {
1912 +       struct list_head list;
1913 +
1914 +       u_int32_t xid;   
1915 +       u_int32_t ip;
1916 +       u_int16_t port;
1917 +       
1918 +       /* Protocol */
1919 +       u_int16_t proto;
1920 +
1921 +       struct timer_list timeout;
1922 +};
1923 +
1924 +static inline int request_p_cmp(const struct request_p *p, u_int32_t xid, 
1925 +                               u_int32_t ip, u_int32_t port) {
1926 +       return (p->xid == xid && p->ip == ip && p->port);
1927 +
1928 +}
1929 +
1930 +#endif /* _IP_CONNTRACK_RPC_H */
1931 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_rsh.h
1932 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_rsh.h    Thu Jan  1 00:00:00 1970
1933 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_rsh.h        Wed Sep 24 09:18:03 2003
1934 @@ -0,0 +1,35 @@
1935 +/* RSH extension for IP connection tracking, Version 1.0
1936 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
1937 + * based on HW's ip_conntrack_irc.c     
1938 + *
1939 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
1940 + *
1941 + *      This program is free software; you can redistribute it and/or
1942 + *      modify it under the terms of the GNU General Public License
1943 + *      as published by the Free Software Foundation; either version
1944 + *      2 of the License, or (at your option) any later version.
1945 + */
1946 +#ifndef _IP_CONNTRACK_RSH_H
1947 +#define _IP_CONNTRACK_RSH_H
1948 +
1949 +#ifdef __KERNEL__
1950 +#include <linux/netfilter_ipv4/lockhelp.h>
1951 +
1952 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
1953 +#endif
1954 +
1955 +
1956 +#define RSH_PORT       514
1957 +
1958 +/* This structure is per expected connection */
1959 +struct ip_ct_rsh_expect
1960 +{
1961 +       u_int16_t port;
1962 +};
1963 +
1964 +/* This structure exists only once per master */
1965 +struct ip_ct_rsh_master {
1966 +};
1967 +
1968 +#endif /* _IP_CONNTRACK_RSH_H */
1969 +
1970 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_talk.h
1971 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_talk.h   Thu Jan  1 00:00:00 1970
1972 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_talk.h       Wed Sep 24 09:18:08 2003
1973 @@ -0,0 +1,152 @@
1974 +#ifndef _IP_CONNTRACK_TALK_H
1975 +#define _IP_CONNTRACK_TALK_H
1976 +/* TALK tracking. */
1977 +
1978 +#ifdef __KERNEL__
1979 +#include <linux/in.h>
1980 +#include <linux/netfilter_ipv4/lockhelp.h>
1981 +
1982 +/* Protects talk part of conntracks */
1983 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1984 +#endif
1985 +
1986 +
1987 +#define TALK_PORT      517
1988 +#define NTALK_PORT     518
1989 +
1990 +/* talk structures and constants from <protocols/talkd.h> */
1991 +
1992 +/*
1993 + * 4.3BSD struct sockaddr
1994 + */
1995 +struct talk_addr {
1996 +       u_int16_t ta_family;
1997 +       u_int16_t ta_port;
1998 +       u_int32_t ta_addr;
1999 +       u_int32_t ta_junk1;
2000 +       u_int32_t ta_junk2;
2001 +};
2002 +
2003 +#define        TALK_OLD_NSIZE  9
2004 +#define        TALK_NSIZE      12
2005 +#define        TALK_TTY_NSIZE  16
2006 +
2007 +/*
2008 + * Client->server request message formats.
2009 + */
2010 +struct talk_msg {
2011 +       u_char  type;           /* request type, see below */
2012 +       char    l_name[TALK_OLD_NSIZE];/* caller's name */
2013 +       char    r_name[TALK_OLD_NSIZE];/* callee's name */
2014 +       u_char  pad;
2015 +       u_int32_t id_num;       /* message id */
2016 +       int32_t pid;            /* caller's process id */
2017 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
2018 +       struct  talk_addr addr;         /* old (4.3) style */
2019 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
2020 +};
2021 +
2022 +struct ntalk_msg {
2023 +       u_char  vers;           /* protocol version */
2024 +       u_char  type;           /* request type, see below */
2025 +       u_char  answer;         /* not used */
2026 +       u_char  pad;
2027 +       u_int32_t id_num;       /* message id */
2028 +       struct  talk_addr addr;         /* old (4.3) style */
2029 +       struct  talk_addr ctl_addr;     /* old (4.3) style */
2030 +       int32_t pid;            /* caller's process id */
2031 +       char    l_name[TALK_NSIZE];/* caller's name */
2032 +       char    r_name[TALK_NSIZE];/* callee's name */
2033 +       char    r_tty[TALK_TTY_NSIZE];/* callee's tty name */
2034 +};
2035 +
2036 +struct ntalk2_msg {
2037 +       u_char  vers;           /* talk protocol version    */
2038 +       u_char  type;           /* request type             */
2039 +       u_char  answer;         /*  */
2040 +       u_char  extended;       /* !0 if additional parts   */
2041 +       u_int32_t id_num;       /* message id number (dels) */
2042 +       struct  talk_addr addr;         /* target address   */
2043 +       struct  talk_addr ctl_addr;     /* reply to address */
2044 +       int32_t pid;            /* caller's process id */
2045 +       char    l_name[TALK_NSIZE];  /* caller's name */
2046 +       char    r_name[TALK_NSIZE];  /* callee's name */
2047 +       char    r_tty[TALK_TTY_NSIZE];    /* callee's tty */
2048 +};
2049 +
2050 +/*
2051 + * Server->client response message formats.
2052 + */
2053 +struct talk_response {
2054 +       u_char  type;           /* type of request message, see below */
2055 +       u_char  answer;         /* response to request message, see below */
2056 +       u_char  pad[2];
2057 +       u_int32_t id_num;       /* message id */
2058 +       struct  talk_addr addr; /* address for establishing conversation */
2059 +};
2060 +
2061 +struct ntalk_response {
2062 +       u_char  vers;           /* protocol version */
2063 +       u_char  type;           /* type of request message, see below */
2064 +       u_char  answer;         /* response to request message, see below */
2065 +       u_char  pad;
2066 +       u_int32_t id_num;       /* message id */
2067 +       struct  talk_addr addr; /* address for establishing conversation */
2068 +};
2069 +
2070 +struct ntalk2_response {
2071 +       u_char  vers;           /* protocol version         */
2072 +       u_char  type;           /* type of request message  */
2073 +       u_char  answer;         /* response to request      */
2074 +       u_char  rvers;          /* Version of answering vers*/
2075 +       u_int32_t id_num;       /* message id number        */
2076 +       struct  talk_addr addr; /* address for connection   */
2077 +       /* This is at the end to compatiblize this with NTALK version.   */
2078 +       char    r_name[TALK_NSIZE]; /* callee's name            */
2079 +};
2080 +
2081 +#define TALK_STR(data, talk_str, member) ((struct talk_str *)data)->member)
2082 +#define TALK_RESP(data, ver, member) (ver ? ((struct ntalk_response *)data)->member : ((struct talk_response *)data)->member)
2083 +#define TALK_MSG(data, ver, member) (ver ? ((struct ntalk_msg *)data)->member : ((struct talk_msg *)data)->member)
2084 +
2085 +#define        TALK_VERSION    0               /* protocol versions */
2086 +#define        NTALK_VERSION   1
2087 +#define        NTALK2_VERSION  2
2088 +
2089 +/* message type values */
2090 +#define LEAVE_INVITE   0       /* leave invitation with server */
2091 +#define LOOK_UP                1       /* check for invitation by callee */
2092 +#define DELETE         2       /* delete invitation by caller */
2093 +#define ANNOUNCE       3       /* announce invitation by caller */
2094 +/* NTALK2 */
2095 +#define REPLY_QUERY    4       /* request reply data from local daemon */
2096 +
2097 +/* answer values */
2098 +#define SUCCESS                0       /* operation completed properly */
2099 +#define NOT_HERE       1       /* callee not logged in */
2100 +#define FAILED         2       /* operation failed for unexplained reason */
2101 +#define MACHINE_UNKNOWN        3       /* caller's machine name unknown */
2102 +#define PERMISSION_DENIED 4    /* callee's tty doesn't permit announce */
2103 +#define UNKNOWN_REQUEST        5       /* request has invalid type value */
2104 +#define        BADVERSION      6       /* request has invalid protocol version */
2105 +#define        BADADDR         7       /* request has invalid addr value */
2106 +#define        BADCTLADDR      8       /* request has invalid ctl_addr value */
2107 +/* NTALK2 */
2108 +#define NO_CALLER      9       /* no-one calling answer from REPLY   */
2109 +#define TRY_HERE       10      /* Not on this machine, try this      */
2110 +#define SELECTIVE_REFUSAL 11   /* User Filter refusal.               */
2111 +#define MAX_RESPONSE_TYPE 11   /* Make sure this is updated          */
2112 +
2113 +/* We don't really need much for talk */
2114 +struct ip_ct_talk_expect
2115 +{
2116 +       /* Port that was to be used */
2117 +       u_int16_t port;
2118 +};
2119 +
2120 +/* This structure exists only once per master */
2121 +struct ip_ct_talk_master
2122 +{
2123 +};
2124 +
2125 +#endif /* _IP_CONNTRACK_TALK_H */
2126 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_tftp.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_tftp.h
2127 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_tftp.h   Thu Jan  1 00:00:00 1970
2128 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_tftp.h       Wed Sep 24 09:16:14 2003
2129 @@ -0,0 +1,13 @@
2130 +#ifndef _IP_CT_TFTP
2131 +#define _IP_CT_TFTP
2132 +
2133 +#define TFTP_PORT 69
2134 +
2135 +struct tftphdr {
2136 +       u_int16_t opcode;
2137 +};
2138 +
2139 +#define TFTP_OPCODE_READ       1
2140 +#define TFTP_OPCODE_WRITE      2
2141 +
2142 +#endif /* _IP_CT_TFTP */
2143 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
2144 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_conntrack_tuple.h  Mon Feb 25 19:38:13 2002
2145 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_conntrack_tuple.h      Wed Sep 24 09:17:55 2003
2146 @@ -14,7 +14,7 @@
2147  union ip_conntrack_manip_proto
2148  {
2149         /* Add other protocols here. */
2150 -       u_int16_t all;
2151 +       u_int32_t all;
2152  
2153         struct {
2154                 u_int16_t port;
2155 @@ -25,6 +25,9 @@
2156         struct {
2157                 u_int16_t id;
2158         } icmp;
2159 +       struct {
2160 +               u_int32_t key;
2161 +       } gre;
2162  };
2163  
2164  /* The manipulable part of the tuple. */
2165 @@ -44,7 +47,7 @@
2166                 u_int32_t ip;
2167                 union {
2168                         /* Add other protocols here. */
2169 -                       u_int16_t all;
2170 +                       u_int64_t all;
2171  
2172                         struct {
2173                                 u_int16_t port;
2174 @@ -55,6 +58,11 @@
2175                         struct {
2176                                 u_int8_t type, code;
2177                         } icmp;
2178 +                       struct {
2179 +                               u_int16_t protocol;
2180 +                               u_int8_t version;
2181 +                               u_int32_t key;
2182 +                       } gre;
2183                 } u;
2184  
2185                 /* The protocol. */
2186 @@ -62,6 +70,14 @@
2187         } dst;
2188  };
2189  
2190 +/* This is optimized opposed to a memset of the whole structure.  Everything we
2191 + * really care about is the  source/destination unions */
2192 +#define IP_CT_TUPLE_BLANK(tuple)                               \
2193 +       do {                                                    \
2194 +               (tuple)->src.u.all = 0;                         \
2195 +               (tuple)->dst.u.all = 0;                         \
2196 +       } while (0)
2197 +
2198  enum ip_conntrack_dir
2199  {
2200         IP_CT_DIR_ORIGINAL,
2201 @@ -72,10 +88,16 @@
2202  #ifdef __KERNEL__
2203  
2204  #define DUMP_TUPLE(tp)                                         \
2205 -DEBUGP("tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n",    \
2206 +DEBUGP("tuple %p: %u %u.%u.%u.%u:%u -> %u.%u.%u.%u:%u\n",      \
2207         (tp), (tp)->dst.protonum,                               \
2208 -       NIPQUAD((tp)->src.ip), ntohs((tp)->src.u.all),          \
2209 -       NIPQUAD((tp)->dst.ip), ntohs((tp)->dst.u.all))
2210 +       NIPQUAD((tp)->src.ip), ntohl((tp)->src.u.all),          \
2211 +       NIPQUAD((tp)->dst.ip), ntohl((tp)->dst.u.all))
2212 +
2213 +#define DUMP_TUPLE_RAW(x)                                              \
2214 +       DEBUGP("tuple %p: %u %u.%u.%u.%u:0x%08x -> %u.%u.%u.%u:0x%08x\n",\
2215 +       (x), (x)->dst.protonum,                                         \
2216 +       NIPQUAD((x)->src.ip), ntohl((x)->src.u.all),                    \
2217 +       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.all))
2218  
2219  #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
2220  
2221 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_logging.h linux-2.4.20/include/linux/netfilter_ipv4/ip_logging.h
2222 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_logging.h  Thu Jan  1 00:00:00 1970
2223 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_logging.h      Wed Sep 24 09:16:23 2003
2224 @@ -0,0 +1,20 @@
2225 +/* IPv4 macros for the internal logging interface. */
2226 +#ifndef __IP_LOGGING_H
2227 +#define __IP_LOGGING_H
2228 +
2229 +#ifdef __KERNEL__
2230 +#include <linux/socket.h>
2231 +#include <linux/netfilter_logging.h>
2232 +
2233 +#define nf_log_ip_packet(pskb,hooknum,in,out,fmt,args...) \
2234 +       nf_log_packet(AF_INET,pskb,hooknum,in,out,fmt,##args)
2235 +
2236 +#define nf_log_ip(pfh,len,fmt,args...) \
2237 +       nf_log(AF_INET,pfh,len,fmt,##args)
2238 +
2239 +#define nf_ip_log_register(logging) nf_log_register(AF_INET,logging)
2240 +#define nf_ip_log_unregister(logging) nf_log_unregister(AF_INET,logging)
2241 +       
2242 +#endif /*__KERNEL__*/
2243 +
2244 +#endif /*__IP_LOGGING_H*/
2245 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_helper.h linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_helper.h
2246 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_helper.h       Thu Nov 28 23:53:15 2002
2247 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_helper.h   Wed Sep 24 09:16:14 2003
2248 @@ -50,6 +50,13 @@
2249                                 unsigned int match_len,
2250                                 char *rep_buffer,
2251                                 unsigned int rep_len);
2252 +extern int ip_nat_mangle_udp_packet(struct sk_buff **skb,
2253 +                               struct ip_conntrack *ct,
2254 +                               enum ip_conntrack_info ctinfo,
2255 +                               unsigned int match_offset,
2256 +                               unsigned int match_len,
2257 +                               char *rep_buffer,
2258 +                               unsigned int rep_len);
2259  extern int ip_nat_seq_adjust(struct sk_buff *skb,
2260                                 struct ip_conntrack *ct,
2261                                 enum ip_conntrack_info ctinfo);
2262 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_pptp.h linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_pptp.h
2263 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_pptp.h Thu Jan  1 00:00:00 1970
2264 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_pptp.h     Wed Sep 24 09:17:55 2003
2265 @@ -0,0 +1,11 @@
2266 +/* PPTP constants and structs */
2267 +#ifndef _NAT_PPTP_H
2268 +#define _NAT_PPTP_H
2269 +
2270 +/* conntrack private data */
2271 +struct ip_nat_pptp {
2272 +       u_int16_t pns_call_id;          /* NAT'ed PNS call id */
2273 +       u_int16_t pac_call_id;          /* NAT'ed PAC call id */
2274 +};
2275 +
2276 +#endif /* _NAT_PPTP_H */
2277 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_rule.h linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_rule.h
2278 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_nat_rule.h Thu Nov 28 23:53:15 2002
2279 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_nat_rule.h     Wed Sep 24 09:16:27 2003
2280 @@ -14,5 +14,10 @@
2281                             const struct net_device *out,
2282                             struct ip_conntrack *ct,
2283                             struct ip_nat_info *info);
2284 +
2285 +extern unsigned int
2286 +alloc_null_binding(struct ip_conntrack *conntrack,
2287 +                  struct ip_nat_info *info,
2288 +                  unsigned int hooknum);
2289  #endif
2290  #endif /* _IP_NAT_RULE_H */
2291 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ip_pool.h linux-2.4.20/include/linux/netfilter_ipv4/ip_pool.h
2292 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ip_pool.h     Thu Jan  1 00:00:00 1970
2293 +++ linux-2.4.20/include/linux/netfilter_ipv4/ip_pool.h Wed Sep 24 09:16:59 2003
2294 @@ -0,0 +1,64 @@
2295 +#ifndef _IP_POOL_H
2296 +#define _IP_POOL_H
2297 +
2298 +/***************************************************************************/
2299 +/*  This program is free software; you can redistribute it and/or modify   */
2300 +/*  it under the terms of the GNU General Public License as published by   */
2301 +/*  the Free Software Foundation; either version 2 of the License, or     */
2302 +/*  (at your option) any later version.                                           */
2303 +/*                                                                        */
2304 +/*  This program is distributed in the hope that it will be useful,       */
2305 +/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
2306 +/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
2307 +/*  GNU General Public License for more details.                          */
2308 +/*                                                                        */
2309 +/*  You should have received a copy of the GNU General Public License     */
2310 +/*  along with this program; if not, write to the Free Software                   */
2311 +/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/
2312 +/***************************************************************************/
2313 +
2314 +/* A sockopt of such quality has hardly ever been seen before on the open
2315 + * market!  This little beauty, hardly ever used: above 64, so it's
2316 + * traditionally used for firewalling, not touched (even once!) by the
2317 + * 2.0, 2.2 and 2.4 kernels!
2318 + *
2319 + * Comes with its own certificate of authenticity, valid anywhere in the
2320 + * Free world!
2321 + *
2322 + * Rusty, 19.4.2000
2323 + */
2324 +#define SO_IP_POOL 81
2325 +
2326 +typedef int ip_pool_t;                 /* pool index */
2327 +#define IP_POOL_NONE   ((ip_pool_t)-1)
2328 +
2329 +struct ip_pool_request {
2330 +       int op;
2331 +       ip_pool_t index;
2332 +       u_int32_t addr;
2333 +       u_int32_t addr2;
2334 +};
2335 +
2336 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
2337 +
2338 +#define IP_POOL_BAD001         0x00000010
2339 +
2340 +#define IP_POOL_FLUSH          0x00000011      /* req.index, no arguments */
2341 +#define IP_POOL_INIT           0x00000012      /* from addr to addr2 incl. */
2342 +#define IP_POOL_DESTROY                0x00000013      /* req.index, no arguments */
2343 +#define IP_POOL_ADD_ADDR       0x00000014      /* add addr to pool */
2344 +#define IP_POOL_DEL_ADDR       0x00000015      /* del addr from pool */
2345 +#define IP_POOL_HIGH_NR                0x00000016      /* result in req.index */
2346 +#define IP_POOL_LOOKUP         0x00000017      /* result in addr and addr2 */
2347 +#define IP_POOL_USAGE          0x00000018      /* result in addr */
2348 +#define IP_POOL_TEST_ADDR      0x00000019      /* result (0/1) returned */
2349 +
2350 +#ifdef __KERNEL__
2351 +
2352 +/* NOTE: ip_pool_match() and ip_pool_mod() expect ADDR to be host byte order */
2353 +extern int ip_pool_match(ip_pool_t pool, u_int32_t addr);
2354 +extern int ip_pool_mod(ip_pool_t pool, u_int32_t addr, int isdel);
2355 +
2356 +#endif
2357 +
2358 +#endif /*_IP_POOL_H*/
2359 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_CLASSIFY.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_CLASSIFY.h
2360 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_CLASSIFY.h        Thu Jan  1 00:00:00 1970
2361 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_CLASSIFY.h    Wed Sep 24 09:17:14 2003
2362 @@ -0,0 +1,8 @@
2363 +#ifndef _IPT_CLASSIFY_H
2364 +#define _IPT_CLASSIFY_H
2365 +
2366 +struct ipt_classify_target_info {
2367 +       u_int32_t priority;
2368 +};
2369 +
2370 +#endif /*_IPT_CLASSIFY_H */
2371 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_CONNMARK.h
2372 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_CONNMARK.h        Thu Jan  1 00:00:00 1970
2373 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_CONNMARK.h    Wed Sep 24 09:17:17 2003
2374 @@ -0,0 +1,15 @@
2375 +#ifndef _IPT_CONNMARK_H_target
2376 +#define _IPT_CONNMARK_H_target
2377 +
2378 +enum {
2379 +    IPT_CONNMARK_SET = 0,
2380 +    IPT_CONNMARK_SAVE,
2381 +    IPT_CONNMARK_RESTORE
2382 +};
2383 +
2384 +struct ipt_connmark_target_info {
2385 +       unsigned long mark;
2386 +       u_int8_t mode;
2387 +};
2388 +
2389 +#endif /*_IPT_CONNMARK_H_target*/
2390 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_IMQ.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_IMQ.h
2391 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_IMQ.h     Thu Jan  1 00:00:00 1970
2392 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_IMQ.h Wed Sep 24 09:17:19 2003
2393 @@ -0,0 +1,8 @@
2394 +#ifndef _IPT_IMQ_H
2395 +#define _IPT_IMQ_H
2396 +
2397 +struct ipt_imq_info {
2398 +       unsigned int todev;     /* target imq device */
2399 +};
2400 +
2401 +#endif /* _IPT_IMQ_H */
2402 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_IPMARK.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_IPMARK.h
2403 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_IPMARK.h  Thu Jan  1 00:00:00 1970
2404 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_IPMARK.h      Wed Sep 24 09:17:23 2003
2405 @@ -0,0 +1,13 @@
2406 +#ifndef _IPT_IPMARK_H_target
2407 +#define _IPT_IPMARK_H_target
2408 +
2409 +struct ipt_ipmark_target_info {
2410 +       unsigned long andmask;
2411 +       unsigned long ormask;
2412 +       unsigned int addr;
2413 +};
2414 +
2415 +#define IPT_IPMARK_SRC    0
2416 +#define IPT_IPMARK_DST    1
2417 +
2418 +#endif /*_IPT_IPMARK_H_target*/
2419 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_NETLINK.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_NETLINK.h
2420 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_NETLINK.h Thu Jan  1 00:00:00 1970
2421 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_NETLINK.h     Wed Sep 24 09:16:32 2003
2422 @@ -0,0 +1,27 @@
2423 +#ifndef _IPT_FWMON_H
2424 +#define _IPT_FWMON_H
2425 +
2426 +/* Bitmask macros */
2427 +#define MASK(x,y) (x & y)
2428 +#define MASK_SET(x,y) x |= y
2429 +#define MASK_UNSET(x,y) x &= ~y
2430 +
2431 +#define USE_MARK       0x00000001
2432 +#define USE_DROP       0x00000002
2433 +#define USE_SIZE       0x00000004
2434 +
2435 +struct ipt_nldata
2436 +{      
2437 +       unsigned int flags;
2438 +       unsigned int mark;
2439 +       unsigned int size;
2440 +};
2441 +
2442 +/* Old header */
2443 +struct netlink_t {
2444 +       unsigned int len;
2445 +       unsigned int mark;
2446 +       char iface[IFNAMSIZ];
2447 +};
2448 +
2449 +#endif /*_IPT_FWMON_H*/
2450 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_REJECT.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_REJECT.h
2451 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_REJECT.h  Fri Jul 14 19:20:23 2000
2452 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_REJECT.h      Wed Sep 24 09:18:09 2003
2453 @@ -9,11 +9,13 @@
2454         IPT_ICMP_ECHOREPLY,
2455         IPT_ICMP_NET_PROHIBITED,
2456         IPT_ICMP_HOST_PROHIBITED,
2457 -       IPT_TCP_RESET
2458 +       IPT_TCP_RESET,
2459 +       IPT_ICMP_ADMIN_PROHIBITED
2460  };
2461  
2462  struct ipt_reject_info {
2463         enum ipt_reject_with with;      /* reject type */
2464 +       u_int8_t fake_source_address;  /* 1: fake src addr with original packet dest, 0: no fake */
2465  };
2466  
2467 -#endif /*_IPT_REJECT_H*/
2468 +#endif /* _IPT_REJECT_H */
2469 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ROUTE.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_ROUTE.h
2470 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ROUTE.h   Thu Jan  1 00:00:00 1970
2471 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_ROUTE.h       Wed Sep 24 09:17:25 2003
2472 @@ -0,0 +1,22 @@
2473 +/* Header file for iptables ipt_ROUTE target
2474 + *
2475 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
2476 + *
2477 + * This software is distributed under GNU GPL v2, 1991
2478 + */
2479 +#ifndef _IPT_ROUTE_H_target
2480 +#define _IPT_ROUTE_H_target
2481 +
2482 +#define IPT_ROUTE_IFNAMSIZ 16
2483 +
2484 +struct ipt_route_target_info {
2485 +       char      oif[IPT_ROUTE_IFNAMSIZ];      /* Output Interface Name */
2486 +       char      iif[IPT_ROUTE_IFNAMSIZ];      /* Input Interface Name  */
2487 +       u_int32_t gw;                           /* IP address of gateway */
2488 +       u_int8_t  flags;
2489 +};
2490 +
2491 +/* Values for "flags" field */
2492 +#define IPT_ROUTE_CONTINUE        0x01
2493 +
2494 +#endif /*_IPT_ROUTE_H_target*/
2495 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_SAME.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_SAME.h
2496 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_SAME.h    Thu Jan  1 00:00:00 1970
2497 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_SAME.h        Wed Sep 24 09:16:38 2003
2498 @@ -0,0 +1,19 @@
2499 +#ifndef _IPT_SAME_H
2500 +#define _IPT_SAME_H
2501 +
2502 +#define IPT_SAME_MAX_RANGE     10
2503 +
2504 +#define IPT_SAME_NODST         0x01
2505 +
2506 +struct ipt_same_info
2507 +{
2508 +       unsigned char info;
2509 +       u_int32_t rangesize;
2510 +       u_int32_t ipnum;
2511 +       u_int32_t *iparray;
2512 +
2513 +       /* hangs off end. */
2514 +       struct ip_nat_range range[IPT_SAME_MAX_RANGE];
2515 +};
2516 +
2517 +#endif /*_IPT_SAME_H*/
2518 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_TCPLAG.h
2519 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_TCPLAG.h  Thu Jan  1 00:00:00 1970
2520 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_TCPLAG.h      Wed Sep 24 09:17:29 2003
2521 @@ -0,0 +1,10 @@
2522 +#ifndef _IPT_TCPLAG_H
2523 +#define _IPT_TCPLAG_H
2524 +
2525 +struct ipt_tcplag
2526 +{
2527 +       unsigned char level;
2528 +       unsigned char prefix[ 15 ];
2529 +};
2530 +
2531 +#endif
2532 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_TTL.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_TTL.h
2533 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_TTL.h     Thu Jan  1 00:00:00 1970
2534 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_TTL.h Wed Sep 24 09:16:40 2003
2535 @@ -0,0 +1,21 @@
2536 +/* TTL modification module for IP tables
2537 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2538 +
2539 +#ifndef _IPT_TTL_H
2540 +#define _IPT_TTL_H
2541 +
2542 +enum {
2543 +       IPT_TTL_SET = 0,
2544 +       IPT_TTL_INC,
2545 +       IPT_TTL_DEC
2546 +};
2547 +
2548 +#define IPT_TTL_MAXMODE        IPT_TTL_DEC
2549 +
2550 +struct ipt_TTL_info {
2551 +       u_int8_t        mode;
2552 +       u_int8_t        ttl;
2553 +};
2554 +
2555 +
2556 +#endif
2557 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ULOG.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_ULOG.h
2558 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ULOG.h    Mon Feb 25 19:38:13 2002
2559 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_ULOG.h        Wed Sep 24 09:16:23 2003
2560 @@ -11,6 +11,9 @@
2561  #define NETLINK_NFLOG  5
2562  #endif
2563  
2564 +#define ULOG_DEFAULT_NLGROUP   1
2565 +#define ULOG_DEFAULT_QTHRESHOLD        1
2566 +
2567  #define ULOG_MAC_LEN   80
2568  #define ULOG_PREFIX_LEN        32
2569  
2570 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_XOR.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_XOR.h
2571 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_XOR.h     Thu Jan  1 00:00:00 1970
2572 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_XOR.h Wed Sep 24 09:17:31 2003
2573 @@ -0,0 +1,9 @@
2574 +#ifndef _IPT_XOR_H
2575 +#define _IPT_XOR_H
2576 +
2577 +struct ipt_XOR_info {
2578 +       char            key[30];
2579 +       u_int8_t        block_size;
2580 +};
2581 +
2582 +#endif /* _IPT_XOR_H */
2583 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_addrtype.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_addrtype.h
2584 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_addrtype.h        Thu Jan  1 00:00:00 1970
2585 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_addrtype.h    Wed Sep 24 09:17:32 2003
2586 @@ -0,0 +1,11 @@
2587 +#ifndef _IPT_ADDRTYPE_H
2588 +#define _IPT_ADDRTYPE_H
2589 +
2590 +struct ipt_addrtype_info {
2591 +       u_int16_t       source;         /* source-type mask */
2592 +       u_int16_t       dest;           /* dest-type mask */
2593 +       int             invert_source;
2594 +       int             invert_dest;
2595 +};
2596 +
2597 +#endif
2598 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_condition.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_condition.h
2599 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_condition.h       Thu Jan  1 00:00:00 1970
2600 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_condition.h   Wed Sep 24 09:17:34 2003
2601 @@ -0,0 +1,11 @@
2602 +#ifndef __IPT_CONDITION_MATCH__
2603 +#define __IPT_CONDITION_MATCH__
2604 +
2605 +#define CONDITION_NAME_LEN  32
2606 +
2607 +struct condition_info {
2608 +       char name[CONDITION_NAME_LEN];
2609 +       int  invert;
2610 +};
2611 +
2612 +#endif
2613 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_connlimit.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_connlimit.h
2614 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_connlimit.h       Thu Jan  1 00:00:00 1970
2615 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_connlimit.h   Wed Sep 24 09:16:42 2003
2616 @@ -0,0 +1,12 @@
2617 +#ifndef _IPT_CONNLIMIT_H
2618 +#define _IPT_CONNLIMIT_H
2619 +
2620 +struct ipt_connlimit_data;
2621 +
2622 +struct ipt_connlimit_info {
2623 +       int limit;
2624 +       int inverse;
2625 +       u_int32_t mask;
2626 +       struct ipt_connlimit_data *data;
2627 +};
2628 +#endif /* _IPT_CONNLIMIT_H */
2629 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_connmark.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_connmark.h
2630 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_connmark.h        Thu Jan  1 00:00:00 1970
2631 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_connmark.h    Wed Sep 24 09:17:17 2003
2632 @@ -0,0 +1,9 @@
2633 +#ifndef _IPT_CONNMARK_H
2634 +#define _IPT_CONNMARK_H
2635 +
2636 +struct ipt_connmark_info {
2637 +       unsigned long mark, mask;
2638 +       u_int8_t invert;
2639 +};
2640 +
2641 +#endif /*_IPT_CONNMARK_H*/
2642 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_conntrack.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_conntrack.h
2643 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_conntrack.h       Thu Nov 28 23:53:15 2002
2644 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_conntrack.h   Wed Sep 24 09:18:12 2003
2645 @@ -11,6 +11,8 @@
2646  #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
2647  #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
2648  
2649 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_IS_REPLY+3))
2650 +
2651  /* flags, invflags: */
2652  #define IPT_CONNTRACK_STATE    0x01
2653  #define IPT_CONNTRACK_PROTO    0x02
2654 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_fuzzy.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_fuzzy.h
2655 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_fuzzy.h   Thu Jan  1 00:00:00 1970
2656 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_fuzzy.h       Wed Sep 24 09:16:44 2003
2657 @@ -0,0 +1,21 @@
2658 +#ifndef _IPT_FUZZY_H
2659 +#define _IPT_FUZZY_H
2660 +
2661 +#include <linux/param.h>
2662 +#include <linux/types.h>
2663 +
2664 +#define MAXFUZZYRATE 10000000
2665 +#define MINFUZZYRATE 3
2666 +
2667 +struct ipt_fuzzy_info {
2668 +       u_int32_t minimum_rate;
2669 +       u_int32_t maximum_rate;
2670 +       u_int32_t packets_total;
2671 +       u_int32_t bytes_total;
2672 +       u_int32_t previous_time;
2673 +       u_int32_t present_time;
2674 +       u_int32_t mean_rate;
2675 +       u_int8_t acceptance_rate;
2676 +};
2677 +
2678 +#endif /*_IPT_FUZZY_H*/
2679 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_iprange.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_iprange.h
2680 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_iprange.h Thu Jan  1 00:00:00 1970
2681 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_iprange.h     Wed Sep 24 09:16:47 2003
2682 @@ -0,0 +1,23 @@
2683 +#ifndef _IPT_IPRANGE_H
2684 +#define _IPT_IPRANGE_H
2685 +
2686 +#define IPRANGE_SRC            0x01    /* Match source IP address */
2687 +#define IPRANGE_DST            0x02    /* Match destination IP address */
2688 +#define IPRANGE_SRC_INV                0x10    /* Negate the condition */
2689 +#define IPRANGE_DST_INV                0x20    /* Negate the condition */
2690 +
2691 +struct ipt_iprange {
2692 +       /* Inclusive: network order. */
2693 +       u_int32_t min_ip, max_ip;
2694 +};
2695 +
2696 +struct ipt_iprange_info
2697 +{
2698 +       struct ipt_iprange src;
2699 +       struct ipt_iprange dst;
2700 +
2701 +       /* Flags from above */
2702 +       u_int8_t flags;
2703 +};
2704 +
2705 +#endif /* _IPT_IPRANGE_H */
2706 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ipv4options.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_ipv4options.h
2707 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_ipv4options.h     Thu Jan  1 00:00:00 1970
2708 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_ipv4options.h Wed Sep 24 09:16:49 2003
2709 @@ -0,0 +1,21 @@
2710 +#ifndef __ipt_ipv4options_h_included__
2711 +#define __ipt_ipv4options_h_included__
2712 +
2713 +#define IPT_IPV4OPTION_MATCH_SSRR              0x01  /* For strict source routing */
2714 +#define IPT_IPV4OPTION_MATCH_LSRR              0x02  /* For loose source routing */
2715 +#define IPT_IPV4OPTION_DONT_MATCH_SRR          0x04  /* any source routing */
2716 +#define IPT_IPV4OPTION_MATCH_RR                        0x08  /* For Record route */
2717 +#define IPT_IPV4OPTION_DONT_MATCH_RR           0x10
2718 +#define IPT_IPV4OPTION_MATCH_TIMESTAMP         0x20  /* For timestamp request */
2719 +#define IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP    0x40
2720 +#define IPT_IPV4OPTION_MATCH_ROUTER_ALERT      0x80  /* For router-alert */
2721 +#define IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT 0x100
2722 +#define IPT_IPV4OPTION_MATCH_ANY_OPT           0x200 /* match packet with any option */
2723 +#define IPT_IPV4OPTION_DONT_MATCH_ANY_OPT      0x400 /* match packet with no option */
2724 +
2725 +struct ipt_ipv4options_info {
2726 +       u_int16_t options;
2727 +};
2728 +
2729 +
2730 +#endif /* __ipt_ipv4options_h_included__ */
2731 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_mark.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_mark.h
2732 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_mark.h    Fri Mar 17 18:56:20 2000
2733 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_mark.h        Wed Sep 24 09:18:10 2003
2734 @@ -1,9 +1,16 @@
2735  #ifndef _IPT_MARK_H
2736  #define _IPT_MARK_H
2737  
2738 +enum {
2739 +        IPT_MARK_BIT_OP_NONE,
2740 +        IPT_MARK_BIT_OP_AND,
2741 +        IPT_MARK_BIT_OP_OR
2742 +};
2743 +
2744  struct ipt_mark_info {
2745      unsigned long mark, mask;
2746      u_int8_t invert;
2747 +    u_int8_t bit_op;
2748  };
2749  
2750  #endif /*_IPT_MARK_H*/
2751 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_mport.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_mport.h
2752 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_mport.h   Thu Jan  1 00:00:00 1970
2753 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_mport.h       Wed Sep 24 09:16:51 2003
2754 @@ -0,0 +1,24 @@
2755 +#ifndef _IPT_MPORT_H
2756 +#define _IPT_MPORT_H
2757 +#include <linux/netfilter_ipv4/ip_tables.h>
2758 +
2759 +#define IPT_MPORT_SOURCE (1<<0)
2760 +#define IPT_MPORT_DESTINATION (1<<1)
2761 +#define IPT_MPORT_EITHER (IPT_MPORT_SOURCE|IPT_MPORT_DESTINATION)
2762 +
2763 +#define IPT_MULTI_PORTS        15
2764 +
2765 +/* Must fit inside union ipt_matchinfo: 32 bytes */
2766 +/* every entry in ports[] except for the last one has one bit in pflags
2767 + * associated with it. If this bit is set, the port is the first port of
2768 + * a portrange, with the next entry being the last.
2769 + * End of list is marked with pflags bit set and port=65535.
2770 + * If 14 ports are used (last one does not have a pflag), the last port
2771 + * is repeated to fill the last entry in ports[] */
2772 +struct ipt_mport
2773 +{
2774 +       u_int8_t flags:2;                       /* Type of comparison */
2775 +       u_int16_t pflags:14;                    /* Port flags */
2776 +       u_int16_t ports[IPT_MULTI_PORTS];       /* Ports */
2777 +};
2778 +#endif /*_IPT_MPORT_H*/
2779 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_nth.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_nth.h
2780 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_nth.h     Thu Jan  1 00:00:00 1970
2781 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_nth.h Wed Sep 24 09:16:53 2003
2782 @@ -0,0 +1,19 @@
2783 +#ifndef _IPT_NTH_H
2784 +#define _IPT_NTH_H
2785 +
2786 +#include <linux/param.h>
2787 +#include <linux/types.h>
2788 +
2789 +#ifndef IPT_NTH_NUM_COUNTERS
2790 +#define IPT_NTH_NUM_COUNTERS 16
2791 +#endif
2792 +
2793 +struct ipt_nth_info {
2794 +       u_int8_t every;
2795 +       u_int8_t not;
2796 +       u_int8_t startat;
2797 +       u_int8_t counter;
2798 +       u_int8_t packet;
2799 +};
2800 +
2801 +#endif /*_IPT_NTH_H*/
2802 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_osf.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_osf.h
2803 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_osf.h     Thu Jan  1 00:00:00 1970
2804 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_osf.h Wed Sep 24 09:16:57 2003
2805 @@ -0,0 +1,120 @@
2806 +/*
2807 + * ipt_osf.h
2808 + *
2809 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
2810 + *
2811 + *
2812 + * This program is free software; you can redistribute it and/or modify
2813 + * it under the terms of the GNU General Public License as published by
2814 + * the Free Software Foundation; either version 2 of the License, or
2815 + * (at your option) any later version.
2816 + *
2817 + * This program is distributed in the hope that it will be useful,
2818 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2819 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2820 + * GNU General Public License for more details.
2821 + *
2822 + * You should have received a copy of the GNU General Public License
2823 + * along with this program; if not, write to the Free Software
2824 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2825 + */
2826 +
2827 +#ifndef _IPT_OSF_H
2828 +#define _IPT_OSF_H
2829 +
2830 +#define MAXGENRELEN            32
2831 +#define MAXDETLEN              64
2832 +
2833 +#include <linux/list.h>
2834 +
2835 +struct ipt_osf_info
2836 +{
2837 +       char                    genre[MAXGENRELEN];
2838 +       int                     len;
2839 +       int                     invert; /* UNSUPPORTED */
2840 +};
2841 +
2842 +struct osf_wc
2843 +{
2844 +       char                    wc;
2845 +       unsigned long           val;
2846 +};
2847 +
2848 +/* This struct represents IANA options
2849 + * http://www.iana.org/assignments/tcp-parameters
2850 + */
2851 +struct osf_opt
2852 +{
2853 +       unsigned char           kind;
2854 +       unsigned char           length;
2855 +       struct osf_wc           wc;
2856 +};
2857 +
2858 +#ifdef __KERNEL__
2859 +
2860 +struct osf_finger
2861 +{
2862 +       struct list_head        flist;
2863 +       struct osf_wc           wss;
2864 +       unsigned char           ttl;
2865 +       unsigned char           df;
2866 +       unsigned long           ss;
2867 +       char                    genre[MAXGENRELEN];
2868 +       
2869 +       /* Not needed, but for consistency with original table from Michal Zalewski */
2870 +       char                    details[MAXDETLEN]; 
2871 +
2872 +       int                     opt_num;
2873 +       struct osf_opt          opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
2874 +
2875 +};
2876 +
2877 +/* Defines for IANA option kinds */
2878 +
2879 +#define OSFOPT_EOL             0       /* End of options */
2880 +#define OSFOPT_NOP             1       /* NOP */
2881 +#define OSFOPT_MSS             2       /* Maximum segment size */
2882 +#define OSFOPT_WSO             3       /* Window scale option */
2883 +#define OSFOPT_SACKP           4       /* SACK permitted */
2884 +#define OSFOPT_SACK            5       /* SACK */
2885 +#define OSFOPT_ECHO            6       
2886 +#define OSFOPT_ECHOREPLY       7
2887 +#define OSFOPT_TS              8       /* Timestamp option */
2888 +#define OSFOPT_POCP            9       /* Partial Order Connection Permitted */
2889 +#define OSFOPT_POSP            10      /* Partial Order Service Profile */
2890 +/* Others are not used in current OSF */
2891 +
2892 +static struct osf_opt IANA_opts[] = 
2893 +{
2894 +       {0, 1,},
2895 +       {1, 1,},
2896 +       {2, 4,},
2897 +       {3, 3,},
2898 +       {4, 2,},
2899 +       {5, 1 ,}, /* SACK length is not defined */
2900 +       {6, 6,},
2901 +       {7, 6,},
2902 +       {8, 10,},
2903 +       {9, 2,},
2904 +       {10, 3,},
2905 +       {11, 1,}, /* CC: Suppose 1 */
2906 +       {12, 1,}, /* the same */
2907 +       {13, 1,}, /* and here too */
2908 +       {14, 3,},
2909 +       {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
2910 +       {16, 1,},
2911 +       {17, 1,},
2912 +       {18, 3,},
2913 +       {19, 18,},
2914 +       {20, 1,},
2915 +       {21, 1,},
2916 +       {22, 1,},
2917 +       {23, 1,},
2918 +       {24, 1,},
2919 +       {25, 1,},
2920 +       {26, 1,},
2921 +};
2922 +
2923 +#endif /* __KERNEL__ */
2924 +
2925 +#endif /* _IPT_OSF_H */
2926 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_pool.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_pool.h
2927 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_pool.h    Thu Jan  1 00:00:00 1970
2928 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_pool.h        Wed Sep 24 09:16:59 2003
2929 @@ -0,0 +1,25 @@
2930 +#ifndef _IPT_POOL_H
2931 +#define _IPT_POOL_H
2932 +
2933 +#include <linux/netfilter_ipv4/ip_pool.h>
2934 +
2935 +#define IPT_POOL_INV_SRC       0x00000001
2936 +#define IPT_POOL_INV_DST       0x00000002
2937 +#define IPT_POOL_DEL_SRC       0x00000004
2938 +#define IPT_POOL_DEL_DST       0x00000008
2939 +#define IPT_POOL_INV_MOD_SRC   0x00000010
2940 +#define IPT_POOL_INV_MOD_DST   0x00000020
2941 +#define IPT_POOL_MOD_SRC_ACCEPT        0x00000040
2942 +#define IPT_POOL_MOD_DST_ACCEPT        0x00000080
2943 +#define IPT_POOL_MOD_SRC_DROP  0x00000100
2944 +#define IPT_POOL_MOD_DST_DROP  0x00000200
2945 +
2946 +/* match info */
2947 +struct ipt_pool_info
2948 +{
2949 +       ip_pool_t src;
2950 +       ip_pool_t dst;
2951 +       unsigned flags;
2952 +};
2953 +
2954 +#endif /*_IPT_POOL_H*/
2955 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_psd.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_psd.h
2956 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_psd.h     Thu Jan  1 00:00:00 1970
2957 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_psd.h Wed Sep 24 09:17:01 2003
2958 @@ -0,0 +1,40 @@
2959 +#ifndef _IPT_PSD_H
2960 +#define _IPT_PSD_H
2961 +
2962 +#include <linux/param.h>
2963 +#include <linux/types.h>
2964 +
2965 +/*
2966 + * High port numbers have a lower weight to reduce the frequency of false
2967 + * positives, such as from passive mode FTP transfers.
2968 + */
2969 +#define PORT_WEIGHT_PRIV               3
2970 +#define PORT_WEIGHT_HIGH               1
2971 +
2972 +/*
2973 + * Port scan detection thresholds: at least COUNT ports need to be scanned
2974 + * from the same source, with no longer than DELAY ticks between ports.
2975 + */
2976 +#define SCAN_MIN_COUNT                 7
2977 +#define SCAN_MAX_COUNT                 (SCAN_MIN_COUNT * PORT_WEIGHT_PRIV)
2978 +#define SCAN_WEIGHT_THRESHOLD          SCAN_MAX_COUNT
2979 +#define SCAN_DELAY_THRESHOLD           (HZ * 3)
2980 +
2981 +/*
2982 + * Keep track of up to LIST_SIZE source addresses, using a hash table of
2983 + * HASH_SIZE entries for faster lookups, but limiting hash collisions to
2984 + * HASH_MAX source addresses per the same hash value.
2985 + */
2986 +#define LIST_SIZE                      0x100
2987 +#define HASH_LOG                       9
2988 +#define HASH_SIZE                      (1 << HASH_LOG)
2989 +#define HASH_MAX                       0x10
2990 +
2991 +struct ipt_psd_info {
2992 +       unsigned int weight_threshold;
2993 +       unsigned int delay_threshold;
2994 +       unsigned short lo_ports_weight;
2995 +       unsigned short hi_ports_weight;
2996 +};
2997 +
2998 +#endif /*_IPT_PSD_H*/
2999 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_quota.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_quota.h
3000 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_quota.h   Thu Jan  1 00:00:00 1970
3001 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_quota.h       Wed Sep 24 09:17:03 2003
3002 @@ -0,0 +1,11 @@
3003 +#ifndef _IPT_QUOTA_H
3004 +#define _IPT_QUOTA_H
3005 +
3006 +/* print debug info in both kernel/netfilter module & iptable library */
3007 +//#define DEBUG_IPT_QUOTA
3008 +
3009 +struct ipt_quota_info {
3010 +        u_int64_t quota;
3011 +};
3012 +
3013 +#endif /*_IPT_QUOTA_H*/
3014 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_random.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_random.h
3015 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_random.h  Thu Jan  1 00:00:00 1970
3016 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_random.h      Wed Sep 24 09:17:05 2003
3017 @@ -0,0 +1,11 @@
3018 +#ifndef _IPT_RAND_H
3019 +#define _IPT_RAND_H
3020 +
3021 +#include <linux/param.h>
3022 +#include <linux/types.h>
3023 +
3024 +struct ipt_rand_info {
3025 +       u_int8_t average;
3026 +};
3027 +
3028 +#endif /*_IPT_RAND_H*/
3029 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_realm.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_realm.h
3030 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_realm.h   Thu Jan  1 00:00:00 1970
3031 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_realm.h       Wed Sep 24 09:17:09 2003
3032 @@ -0,0 +1,9 @@
3033 +#ifndef _IPT_REALM_H
3034 +#define _IPT_REALM_H
3035 +
3036 +struct ipt_realm_info {
3037 +       u_int32_t id;
3038 +       u_int32_t mask;
3039 +       u_int8_t invert;
3040 +};
3041 +#endif /*_IPT_REALM_H*/
3042 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_recent.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_recent.h
3043 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_recent.h  Thu Jan  1 00:00:00 1970
3044 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_recent.h      Wed Sep 24 09:16:17 2003
3045 @@ -0,0 +1,27 @@
3046 +#ifndef _IPT_RECENT_H
3047 +#define _IPT_RECENT_H
3048 +
3049 +#define RECENT_NAME    "ipt_recent"
3050 +#define RECENT_VER     "v0.3.1"
3051 +
3052 +#define IPT_RECENT_CHECK  1
3053 +#define IPT_RECENT_SET    2
3054 +#define IPT_RECENT_UPDATE 4
3055 +#define IPT_RECENT_REMOVE 8
3056 +#define IPT_RECENT_TTL   16
3057 +
3058 +#define IPT_RECENT_SOURCE 0
3059 +#define IPT_RECENT_DEST   1
3060 +
3061 +#define IPT_RECENT_NAME_LEN 200
3062 +
3063 +struct ipt_recent_info {
3064 +       u_int32_t   seconds;
3065 +       u_int32_t   hit_count;
3066 +       u_int8_t    check_set;
3067 +       u_int8_t    invert;
3068 +       char        name[IPT_RECENT_NAME_LEN];
3069 +       u_int8_t    side;
3070 +};
3071 +
3072 +#endif /*_IPT_RECENT_H*/
3073 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_rpc.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_rpc.h
3074 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_rpc.h     Thu Jan  1 00:00:00 1970
3075 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_rpc.h Wed Sep 24 09:18:01 2003
3076 @@ -0,0 +1,35 @@
3077 +/* RPC extension for IP netfilter matching, Version 2.2
3078 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
3079 + *     - original rpc tracking module
3080 + *     - "recent" connection handling for kernel 2.3+ netfilter
3081 + *
3082 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3083 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
3084 + *
3085 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
3086 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
3087 + *     - extended matching to support filtering on procedures
3088 + *
3089 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
3090 + *
3091 + *     This program is free software; you can redistribute it and/or
3092 + *     modify it under the terms of the GNU General Public License
3093 + *     as published by the Free Software Foundation; either version
3094 + *     2 of the License, or (at your option) any later version.
3095 + **
3096 + */
3097 +
3098 +#ifndef _IPT_RPC_H
3099 +#define _IPT_RPC_H
3100 +
3101 +struct ipt_rpc_data;
3102 +
3103 +struct ipt_rpc_info {
3104 +       int inverse;
3105 +       int strict;
3106 +       const char c_procs[1408];
3107 +       int i_procs;
3108 +       struct ipt_rpc_data *data;
3109 +};
3110 +
3111 +#endif /* _IPT_RPC_H */
3112 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_state.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_state.h
3113 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_state.h   Fri Apr 14 16:37:20 2000
3114 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_state.h       Wed Sep 24 09:18:12 2003
3115 @@ -3,6 +3,7 @@
3116  
3117  #define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
3118  #define IPT_STATE_INVALID (1 << 0)
3119 +#define IPT_STATE_UNTRACKED (1 << (IP_CT_IS_REPLY+1))
3120  
3121  struct ipt_state_info
3122  {
3123 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_string.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_string.h
3124 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_string.h  Thu Jan  1 00:00:00 1970
3125 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_string.h      Wed Sep 24 09:18:05 2003
3126 @@ -0,0 +1,21 @@
3127 +#ifndef _IPT_STRING_H
3128 +#define _IPT_STRING_H
3129 +
3130 +/* *** PERFORMANCE TWEAK ***
3131 + * Packet size and search string threshold,
3132 + * above which sublinear searches is used. */
3133 +#define IPT_STRING_HAYSTACK_THRESH     100
3134 +#define IPT_STRING_NEEDLE_THRESH       20
3135 +
3136 +#define BM_MAX_NLEN 256
3137 +#define BM_MAX_HLEN 1024
3138 +
3139 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
3140 +
3141 +struct ipt_string_info {
3142 +    char string[BM_MAX_NLEN];
3143 +    u_int16_t invert;
3144 +    u_int16_t len;
3145 +};
3146 +
3147 +#endif /* _IPT_STRING_H */
3148 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_time.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_time.h
3149 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_time.h    Thu Jan  1 00:00:00 1970
3150 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_time.h        Wed Sep 24 09:17:10 2003
3151 @@ -0,0 +1,13 @@
3152 +#ifndef __ipt_time_h_included__
3153 +#define __ipt_time_h_included__
3154 +
3155 +
3156 +struct ipt_time_info {
3157 +       u_int8_t  days_match;   /* 1 bit per day. -SMTWTFS                      */
3158 +       u_int16_t time_start;   /* 0 < time_start < 23*60+59 = 1439             */
3159 +       u_int16_t time_stop;    /* 0:0 < time_stat < 23:59                      */
3160 +       u_int8_t  kerneltime;   /* ignore skb time (and use kerneltime) or not. */
3161 +};
3162 +
3163 +
3164 +#endif /* __ipt_time_h_included__ */
3165 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_u32.h linux-2.4.20/include/linux/netfilter_ipv4/ipt_u32.h
3166 --- linux-2.4.20.org/include/linux/netfilter_ipv4/ipt_u32.h     Thu Jan  1 00:00:00 1970
3167 +++ linux-2.4.20/include/linux/netfilter_ipv4/ipt_u32.h Wed Sep 24 09:17:12 2003
3168 @@ -0,0 +1,40 @@
3169 +#ifndef _IPT_U32_H
3170 +#define _IPT_U32_H
3171 +#include <linux/netfilter_ipv4/ip_tables.h>
3172 +
3173 +enum ipt_u32_ops
3174 +{
3175 +       IPT_U32_AND,
3176 +       IPT_U32_LEFTSH,
3177 +       IPT_U32_RIGHTSH,
3178 +       IPT_U32_AT
3179 +};
3180 +
3181 +struct ipt_u32_location_element
3182 +{
3183 +       u_int32_t number;
3184 +       u_int8_t nextop;
3185 +};
3186 +struct ipt_u32_value_element
3187 +{
3188 +       u_int32_t min;
3189 +       u_int32_t max;
3190 +};
3191 +/* *** any way to allow for an arbitrary number of elements?
3192 +   for now I settle for a limit of 10 of each */
3193 +#define U32MAXSIZE 10
3194 +struct ipt_u32_test
3195 +{
3196 +       u_int8_t nnums;
3197 +       struct ipt_u32_location_element location[U32MAXSIZE+1];
3198 +       u_int8_t nvalues;
3199 +       struct ipt_u32_value_element value[U32MAXSIZE+1];
3200 +};
3201 +
3202 +struct ipt_u32
3203 +{
3204 +       u_int8_t ntests;
3205 +       struct ipt_u32_test tests[U32MAXSIZE+1];
3206 +};
3207 +
3208 +#endif /*_IPT_U32_H*/
3209 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/listhelp.h linux-2.4.20/include/linux/netfilter_ipv4/listhelp.h
3210 --- linux-2.4.20.org/include/linux/netfilter_ipv4/listhelp.h    Thu Jul 26 20:52:12 2001
3211 +++ linux-2.4.20/include/linux/netfilter_ipv4/listhelp.h        Wed Sep 24 09:16:17 2003
3212 @@ -39,6 +39,22 @@
3213         (type)__i;                              \
3214  })
3215  
3216 +/* Just like LIST_FIND but we search backwards */
3217 +#define LIST_FIND_B(head, cmpfn, type, args...)                \
3218 +({                                                     \
3219 +       const struct list_head *__i = (head);           \
3220 +                                                       \
3221 +       ASSERT_READ_LOCK(head);                         \
3222 +       do {                                            \
3223 +               __i = __i->prev;                        \
3224 +               if (__i == (head)) {                    \
3225 +                       __i = NULL;                     \
3226 +                       break;                          \
3227 +               }                                       \
3228 +       } while (!cmpfn((const type)__i , ## args));    \
3229 +       (type)__i;                                      \
3230 +})
3231 +
3232  static inline int
3233  __list_cmp_same(const void *p1, const void *p2) { return p1 == p2; }
3234  
3235 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv4/lockhelp.h linux-2.4.20/include/linux/netfilter_ipv4/lockhelp.h
3236 --- linux-2.4.20.org/include/linux/netfilter_ipv4/lockhelp.h    Mon Jan  1 18:37:41 2001
3237 +++ linux-2.4.20/include/linux/netfilter_ipv4/lockhelp.h        Wed Sep 24 09:16:17 2003
3238 @@ -42,22 +42,22 @@
3239         printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l);     \
3240  } while(0)
3241  
3242 -/* Write locked OK as well. */                                             \
3243 +/* Write locked OK as well. */
3244  #define MUST_BE_READ_LOCKED(l)                                             \
3245 -do { if (!((l)->read_locked_map & (1 << smp_processor_id()))               \
3246 -        && !((l)->write_locked_map & (1 << smp_processor_id())))           \
3247 +do { if (!((l)->read_locked_map & (1UL << smp_processor_id()))             \
3248 +        && !((l)->write_locked_map & (1UL << smp_processor_id())))         \
3249         printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \
3250  } while(0)
3251  
3252  #define MUST_BE_WRITE_LOCKED(l)                                                     \
3253 -do { if (!((l)->write_locked_map & (1 << smp_processor_id())))              \
3254 +do { if (!((l)->write_locked_map & (1UL << smp_processor_id())))            \
3255         printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \
3256  } while(0)
3257  
3258  #define MUST_BE_READ_WRITE_UNLOCKED(l)                                   \
3259 -do { if ((l)->read_locked_map & (1 << smp_processor_id()))               \
3260 +do { if ((l)->read_locked_map & (1UL << smp_processor_id()))             \
3261         printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l);   \
3262 - else if ((l)->write_locked_map & (1 << smp_processor_id()))             \
3263 + else if ((l)->write_locked_map & (1UL << smp_processor_id()))           \
3264          printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \
3265  } while(0)
3266  
3267 @@ -91,7 +91,7 @@
3268  
3269  #define READ_UNLOCK(lk)                                                        \
3270  do {                                                                   \
3271 -       if (!((lk)->read_locked_map & (1 << smp_processor_id())))       \
3272 +       if (!((lk)->read_locked_map & (1UL << smp_processor_id())))     \
3273                 printk("ASSERT: %s:%u %s not readlocked\n",             \
3274                        __FILE__, __LINE__, #lk);                        \
3275         clear_bit(smp_processor_id(), &(lk)->read_locked_map);          \
3276 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6_logging.h linux-2.4.20/include/linux/netfilter_ipv6/ip6_logging.h
3277 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6_logging.h Thu Jan  1 00:00:00 1970
3278 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6_logging.h     Wed Sep 24 09:16:23 2003
3279 @@ -0,0 +1,20 @@
3280 +/* IPv6 macros for the nternal logging interface. */
3281 +#ifndef __IP6_LOGGING_H
3282 +#define __IP6_LOGGING_H
3283 +
3284 +#ifdef __KERNEL__
3285 +#include <linux/socket.h>
3286 +#include <linux/netfilter_logging.h>
3287 +
3288 +#define nf_log_ip6_packet(pskb,hooknum,in,out,fmt,args...) \
3289 +       nf_log_packet(AF_INET6,pskb,hooknum,in,out,fmt,##args)
3290 +
3291 +#define nf_log_ip6(pfh,len,fmt,args...) \
3292 +       nf_log(AF_INET6,pfh,len,fmt,##args)
3293 +
3294 +#define nf_ip6_log_register(logging) nf_log_register(AF_INET6,logging)
3295 +#define nf_ip6_log_unregister(logging) nf_log_unregister(AF_INET6,logging)
3296 +       
3297 +#endif /*__KERNEL__*/
3298 +
3299 +#endif /*__IP6_LOGGING_H*/
3300 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6_tables.h linux-2.4.20/include/linux/netfilter_ipv6/ip6_tables.h
3301 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6_tables.h  Mon Feb 25 19:38:13 2002
3302 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6_tables.h      Wed Sep 24 09:16:14 2003
3303 @@ -449,6 +449,9 @@
3304                                   struct ip6t_table *table,
3305                                   void *userdata);
3306  
3307 +/* Check for an extension */
3308 +extern int ip6t_ext_hdr(u8 nexthdr);
3309 +
3310  #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
3311  
3312  #endif /*__KERNEL__*/
3313 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_HL.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_HL.h
3314 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_HL.h     Thu Jan  1 00:00:00 1970
3315 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_HL.h Wed Sep 24 09:16:28 2003
3316 @@ -0,0 +1,22 @@
3317 +/* Hop Limit modification module for ip6tables
3318 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3319 + * Based on HW's TTL module */
3320 +
3321 +#ifndef _IP6T_HL_H
3322 +#define _IP6T_HL_H
3323 +
3324 +enum {
3325 +       IP6T_HL_SET = 0,
3326 +       IP6T_HL_INC,
3327 +       IP6T_HL_DEC
3328 +};
3329 +
3330 +#define IP6T_HL_MAXMODE        IP6T_HL_DEC
3331 +
3332 +struct ip6t_HL_info {
3333 +       u_int8_t        mode;
3334 +       u_int8_t        hop_limit;
3335 +};
3336 +
3337 +
3338 +#endif
3339 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_IMQ.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_IMQ.h
3340 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_IMQ.h    Thu Jan  1 00:00:00 1970
3341 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_IMQ.h        Wed Sep 24 09:17:21 2003
3342 @@ -0,0 +1,8 @@
3343 +#ifndef _IP6T_IMQ_H
3344 +#define _IP6T_IMQ_H
3345 +
3346 +struct ip6t_imq_info {
3347 +       unsigned int todev;     /* target imq device */
3348 +};
3349 +
3350 +#endif /* _IP6T_IMQ_H */
3351 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_REJECT.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_REJECT.h
3352 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_REJECT.h Tue Jun 20 21:32:27 2000
3353 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_REJECT.h     Wed Sep 24 09:16:36 2003
3354 @@ -2,15 +2,17 @@
3355  #define _IP6T_REJECT_H
3356  
3357  enum ip6t_reject_with {
3358 -       IP6T_ICMP_NET_UNREACHABLE,
3359 -       IP6T_ICMP_HOST_UNREACHABLE,
3360 -       IP6T_ICMP_PROT_UNREACHABLE,
3361 -       IP6T_ICMP_PORT_UNREACHABLE,
3362 -       IP6T_ICMP_ECHOREPLY
3363 +       IP6T_ICMP6_NO_ROUTE,
3364 +       IP6T_ICMP6_ADM_PROHIBITED,
3365 +       IP6T_ICMP6_NOT_NEIGHBOUR,
3366 +       IP6T_ICMP6_ADDR_UNREACH,
3367 +       IP6T_ICMP6_PORT_UNREACH,
3368 +       IP6T_ICMP6_ECHOREPLY,
3369 +       IP6T_TCP_RESET
3370  };
3371  
3372  struct ip6t_reject_info {
3373         enum ip6t_reject_with with;      /* reject type */
3374  };
3375  
3376 -#endif /*_IPT_REJECT_H*/
3377 +#endif /*_IP6T_REJECT_H*/
3378 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ROUTE.h
3379 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ROUTE.h  Thu Jan  1 00:00:00 1970
3380 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ROUTE.h      Wed Sep 24 09:17:27 2003
3381 @@ -0,0 +1,22 @@
3382 +/* Header file for iptables ip6t_ROUTE target
3383 + *
3384 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
3385 + *
3386 + * This software is distributed under GNU GPL v2, 1991
3387 + */
3388 +#ifndef _IPT_ROUTE_H_target
3389 +#define _IPT_ROUTE_H_target
3390 +
3391 +#define IP6T_ROUTE_IFNAMSIZ 16
3392 +
3393 +struct ip6t_route_target_info {
3394 +       char      oif[IP6T_ROUTE_IFNAMSIZ];     /* Output Interface Name */
3395 +       char      iif[IP6T_ROUTE_IFNAMSIZ];     /* Input Interface Name  */
3396 +       u_int32_t gw[4];                        /* IPv6 address of gateway */
3397 +       u_int8_t  flags;
3398 +};
3399 +
3400 +/* Values for "flags" field */
3401 +#define IP6T_ROUTE_CONTINUE        0x01
3402 +
3403 +#endif /*_IP6T_ROUTE_H_target*/
3404 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ah.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ah.h
3405 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ah.h     Thu Jan  1 00:00:00 1970
3406 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ah.h Wed Sep 24 09:16:14 2003
3407 @@ -0,0 +1,30 @@
3408 +#ifndef _IP6T_AH_H
3409 +#define _IP6T_AH_H
3410 +
3411 +struct ip6t_ah
3412 +{
3413 +       u_int32_t spis[2];                      /* Security Parameter Index */
3414 +       u_int32_t hdrlen;                       /* Header Length */
3415 +       u_int8_t  hdrres;                       /* Test of the Reserved Filed */
3416 +       u_int8_t  invflags;                     /* Inverse flags */
3417 +};
3418 +
3419 +#define IP6T_AH_SPI 0x01
3420 +#define IP6T_AH_LEN 0x02
3421 +#define IP6T_AH_RES 0x04
3422 +
3423 +/* Values for "invflags" field in struct ip6t_ah. */
3424 +#define IP6T_AH_INV_SPI                0x01    /* Invert the sense of spi. */
3425 +#define IP6T_AH_INV_LEN                0x02    /* Invert the sense of length. */
3426 +#define IP6T_AH_INV_MASK       0x03    /* All possible flags. */
3427 +
3428 +#define MASK_HOPOPTS    128
3429 +#define MASK_DSTOPTS    64
3430 +#define MASK_ROUTING    32
3431 +#define MASK_FRAGMENT   16
3432 +#define MASK_AH         8
3433 +#define MASK_ESP        4
3434 +#define MASK_NONE       2
3435 +#define MASK_PROTO      1
3436 +
3437 +#endif /*_IP6T_AH_H*/
3438 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_condition.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_condition.h
3439 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_condition.h      Thu Jan  1 00:00:00 1970
3440 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_condition.h  Wed Sep 24 09:17:36 2003
3441 @@ -0,0 +1,11 @@
3442 +#ifndef __IP6T_CONDITION_MATCH__
3443 +#define __IP6T_CONDITION_MATCH__
3444 +
3445 +#define CONDITION6_NAME_LEN  32
3446 +
3447 +struct condition6_info {
3448 +       char name[CONDITION6_NAME_LEN];
3449 +       int  invert;
3450 +};
3451 +
3452 +#endif
3453 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_esp.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_esp.h
3454 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_esp.h    Thu Jan  1 00:00:00 1970
3455 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_esp.h        Wed Sep 24 09:16:14 2003
3456 @@ -0,0 +1,23 @@
3457 +#ifndef _IP6T_ESP_H
3458 +#define _IP6T_ESP_H
3459 +
3460 +struct ip6t_esp
3461 +{
3462 +       u_int32_t spis[2];                      /* Security Parameter Index */
3463 +       u_int8_t  invflags;                     /* Inverse flags */
3464 +};
3465 +
3466 +#define MASK_HOPOPTS    128
3467 +#define MASK_DSTOPTS    64
3468 +#define MASK_ROUTING    32
3469 +#define MASK_FRAGMENT   16
3470 +#define MASK_AH         8
3471 +#define MASK_ESP        4
3472 +#define MASK_NONE       2
3473 +#define MASK_PROTO      1
3474 +
3475 +/* Values for "invflags" field in struct ip6t_esp. */
3476 +#define IP6T_ESP_INV_SPI               0x01    /* Invert the sense of spi. */
3477 +#define IP6T_ESP_INV_MASK      0x01    /* All possible flags. */
3478 +
3479 +#endif /*_IP6T_ESP_H*/
3480 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_frag.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_frag.h
3481 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_frag.h   Thu Jan  1 00:00:00 1970
3482 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_frag.h       Wed Sep 24 09:16:14 2003
3483 @@ -0,0 +1,33 @@
3484 +#ifndef _IP6T_FRAG_H
3485 +#define _IP6T_FRAG_H
3486 +
3487 +struct ip6t_frag
3488 +{
3489 +       u_int32_t ids[2];                       /* Security Parameter Index */
3490 +       u_int32_t hdrlen;                       /* Header Length */
3491 +       u_int8_t  flags;                        /*  */
3492 +       u_int8_t  invflags;                     /* Inverse flags */
3493 +};
3494 +
3495 +#define IP6T_FRAG_IDS          0x01
3496 +#define IP6T_FRAG_LEN          0x02
3497 +#define IP6T_FRAG_RES          0x04
3498 +#define IP6T_FRAG_FST          0x08
3499 +#define IP6T_FRAG_MF           0x10
3500 +#define IP6T_FRAG_NMF                  0x20
3501 +
3502 +/* Values for "invflags" field in struct ip6t_frag. */
3503 +#define IP6T_FRAG_INV_IDS      0x01    /* Invert the sense of ids. */
3504 +#define IP6T_FRAG_INV_LEN      0x02    /* Invert the sense of length. */
3505 +#define IP6T_FRAG_INV_MASK     0x03    /* All possible flags. */
3506 +
3507 +#define MASK_HOPOPTS    128
3508 +#define MASK_DSTOPTS    64
3509 +#define MASK_ROUTING    32
3510 +#define MASK_FRAGMENT   16
3511 +#define MASK_AH         8
3512 +#define MASK_ESP        4
3513 +#define MASK_NONE       2
3514 +#define MASK_PROTO      1
3515 +
3516 +#endif /*_IP6T_FRAG_H*/
3517 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_fuzzy.h
3518 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_fuzzy.h  Thu Jan  1 00:00:00 1970
3519 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_fuzzy.h      Wed Sep 24 09:16:45 2003
3520 @@ -0,0 +1,21 @@
3521 +#ifndef _IP6T_FUZZY_H
3522 +#define _IP6T_FUZZY_H
3523 +
3524 +#include <linux/param.h>
3525 +#include <linux/types.h>
3526 +
3527 +#define MAXFUZZYRATE 10000000
3528 +#define MINFUZZYRATE 3
3529 +
3530 +struct ip6t_fuzzy_info {
3531 +       u_int32_t minimum_rate;
3532 +       u_int32_t maximum_rate;
3533 +       u_int32_t packets_total;
3534 +       u_int32_t bytes_total;
3535 +       u_int32_t previous_time;
3536 +       u_int32_t present_time;
3537 +       u_int32_t mean_rate;
3538 +       u_int8_t acceptance_rate;
3539 +};
3540 +
3541 +#endif /*_IP6T_FUZZY_H*/
3542 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_hl.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_hl.h
3543 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_hl.h     Thu Jan  1 00:00:00 1970
3544 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_hl.h Wed Sep 24 09:16:14 2003
3545 @@ -0,0 +1,22 @@
3546 +/* ip6tables module for matching the Hop Limit value
3547 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3548 + * Based on HW's ttl module */
3549 +
3550 +#ifndef _IP6T_HL_H
3551 +#define _IP6T_HL_H
3552 +
3553 +enum {
3554 +       IP6T_HL_EQ = 0,         /* equals */
3555 +       IP6T_HL_NE,             /* not equals */
3556 +       IP6T_HL_LT,             /* less than */
3557 +       IP6T_HL_GT,             /* greater than */
3558 +};
3559 +
3560 +
3561 +struct ip6t_hl_info {
3562 +       u_int8_t        mode;
3563 +       u_int8_t        hop_limit;
3564 +};
3565 +
3566 +
3567 +#endif
3568 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ipv6header.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ipv6header.h
3569 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_ipv6header.h     Thu Jan  1 00:00:00 1970
3570 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_ipv6header.h Wed Sep 24 09:16:14 2003
3571 @@ -0,0 +1,27 @@
3572 +/* ipv6header match - matches IPv6 packets based
3573 +on whether they contain certain headers */
3574 +
3575 +/* Original idea: Brad Chapman 
3576 + * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
3577 +
3578 +
3579 +#ifndef __IPV6HEADER_H
3580 +#define __IPV6HEADER_H
3581 +
3582 +struct ip6t_ipv6header_info
3583 +{
3584 +       u_int8_t matchflags;
3585 +       u_int8_t invflags;
3586 +       u_int8_t modeflag;
3587 +};
3588 +
3589 +#define MASK_HOPOPTS    128
3590 +#define MASK_DSTOPTS    64
3591 +#define MASK_ROUTING    32
3592 +#define MASK_FRAGMENT   16
3593 +#define MASK_AH         8
3594 +#define MASK_ESP        4
3595 +#define MASK_NONE       2
3596 +#define MASK_PROTO      1
3597 +
3598 +#endif /* __IPV6HEADER_H */
3599 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_nth.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_nth.h
3600 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_nth.h    Thu Jan  1 00:00:00 1970
3601 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_nth.h        Wed Sep 24 09:16:55 2003
3602 @@ -0,0 +1,19 @@
3603 +#ifndef _IP6T_NTH_H
3604 +#define _IP6T_NTH_H
3605 +
3606 +#include <linux/param.h>
3607 +#include <linux/types.h>
3608 +
3609 +#ifndef IP6T_NTH_NUM_COUNTERS
3610 +#define IP6T_NTH_NUM_COUNTERS 16
3611 +#endif
3612 +
3613 +struct ip6t_nth_info {
3614 +       u_int8_t every;
3615 +       u_int8_t not;
3616 +       u_int8_t startat;
3617 +       u_int8_t counter;
3618 +       u_int8_t packet;
3619 +};
3620 +
3621 +#endif /*_IP6T_NTH_H*/
3622 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_opts.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_opts.h
3623 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_opts.h   Thu Jan  1 00:00:00 1970
3624 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_opts.h       Wed Sep 24 09:16:14 2003
3625 @@ -0,0 +1,32 @@
3626 +#ifndef _IP6T_OPTS_H
3627 +#define _IP6T_OPTS_H
3628 +
3629 +#define IP6T_OPTS_OPTSNR 16
3630 +
3631 +struct ip6t_opts
3632 +{
3633 +       u_int32_t hdrlen;                       /* Header Length */
3634 +       u_int8_t flags;                         /*  */
3635 +       u_int8_t invflags;                      /* Inverse flags */
3636 +       u_int16_t opts[IP6T_OPTS_OPTSNR];       /* opts */
3637 +       u_int8_t optsnr;                        /* Nr of OPts */
3638 +};
3639 +
3640 +#define IP6T_OPTS_LEN          0x01
3641 +#define IP6T_OPTS_OPTS                 0x02
3642 +#define IP6T_OPTS_NSTRICT      0x04
3643 +
3644 +/* Values for "invflags" field in struct ip6t_rt. */
3645 +#define IP6T_OPTS_INV_LEN      0x01    /* Invert the sense of length. */
3646 +#define IP6T_OPTS_INV_MASK     0x01    /* All possible flags. */
3647 +
3648 +#define MASK_HOPOPTS    128
3649 +#define MASK_DSTOPTS    64
3650 +#define MASK_ROUTING    32
3651 +#define MASK_FRAGMENT   16
3652 +#define MASK_AH         8
3653 +#define MASK_ESP        4
3654 +#define MASK_NONE       2
3655 +#define MASK_PROTO      1
3656 +
3657 +#endif /*_IP6T_OPTS_H*/
3658 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_owner.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_owner.h
3659 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_owner.h  Tue Jun 20 21:32:27 2000
3660 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_owner.h      Wed Sep 24 09:17:52 2003
3661 @@ -6,12 +6,14 @@
3662  #define IP6T_OWNER_GID 0x02
3663  #define IP6T_OWNER_PID 0x04
3664  #define IP6T_OWNER_SID 0x08
3665 +#define IP6T_OWNER_COMM 0x10
3666  
3667  struct ip6t_owner_info {
3668      uid_t uid;
3669      gid_t gid;
3670      pid_t pid;
3671      pid_t sid;
3672 +    char comm[16];
3673      u_int8_t match, invert;    /* flags */
3674  };
3675  
3676 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_random.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_random.h
3677 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_random.h Thu Jan  1 00:00:00 1970
3678 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_random.h     Wed Sep 24 09:17:07 2003
3679 @@ -0,0 +1,11 @@
3680 +#ifndef _IP6T_RAND_H
3681 +#define _IP6T_RAND_H
3682 +
3683 +#include <linux/param.h>
3684 +#include <linux/types.h>
3685 +
3686 +struct ip6t_rand_info {
3687 +       u_int8_t average;
3688 +};
3689 +
3690 +#endif /*_IP6T_RAND_H*/
3691 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_rt.h linux-2.4.20/include/linux/netfilter_ipv6/ip6t_rt.h
3692 --- linux-2.4.20.org/include/linux/netfilter_ipv6/ip6t_rt.h     Thu Jan  1 00:00:00 1970
3693 +++ linux-2.4.20/include/linux/netfilter_ipv6/ip6t_rt.h Wed Sep 24 09:16:14 2003
3694 @@ -0,0 +1,42 @@
3695 +#ifndef _IP6T_RT_H
3696 +#define _IP6T_RT_H
3697 +
3698 +/*#include <linux/in6.h>*/
3699 +
3700 +#define IP6T_RT_HOPS 16
3701 +
3702 +struct ip6t_rt
3703 +{
3704 +       u_int32_t rt_type;                      /* Routing Type */
3705 +       u_int32_t segsleft[2];                  /* Segments Left */
3706 +       u_int32_t hdrlen;                       /* Header Length */
3707 +       u_int8_t  flags;                        /*  */
3708 +       u_int8_t  invflags;                     /* Inverse flags */
3709 +       struct in6_addr addrs[IP6T_RT_HOPS];    /* Hops */
3710 +       u_int8_t addrnr;                        /* Nr of Addresses */
3711 +};
3712 +
3713 +#define IP6T_RT_TYP            0x01
3714 +#define IP6T_RT_SGS            0x02
3715 +#define IP6T_RT_LEN            0x04
3716 +#define IP6T_RT_RES            0x08
3717 +#define IP6T_RT_FST_MASK       0x30
3718 +#define IP6T_RT_FST            0x10
3719 +#define IP6T_RT_FST_NSTRICT    0x20
3720 +
3721 +/* Values for "invflags" field in struct ip6t_rt. */
3722 +#define IP6T_RT_INV_TYP                0x01    /* Invert the sense of type. */
3723 +#define IP6T_RT_INV_SGS                0x02    /* Invert the sense of Segments. */
3724 +#define IP6T_RT_INV_LEN                0x04    /* Invert the sense of length. */
3725 +#define IP6T_RT_INV_MASK       0x07    /* All possible flags. */
3726 +
3727 +#define MASK_HOPOPTS    128
3728 +#define MASK_DSTOPTS    64
3729 +#define MASK_ROUTING    32
3730 +#define MASK_FRAGMENT   16
3731 +#define MASK_AH         8
3732 +#define MASK_ESP        4
3733 +#define MASK_NONE       2
3734 +#define MASK_PROTO      1
3735 +
3736 +#endif /*_IP6T_RT_H*/
3737 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/netfilter_logging.h linux-2.4.20/include/linux/netfilter_logging.h
3738 --- linux-2.4.20.org/include/linux/netfilter_logging.h  Thu Jan  1 00:00:00 1970
3739 +++ linux-2.4.20/include/linux/netfilter_logging.h      Wed Sep 24 09:16:23 2003
3740 @@ -0,0 +1,33 @@
3741 +/* Internal logging interface, which relies on the real 
3742 +   LOG target modules */
3743 +#ifndef __LINUX_NETFILTER_LOGGING_H
3744 +#define __LINUX_NETFILTER_LOGGING_H
3745 +
3746 +#ifdef __KERNEL__
3747 +#include <asm/atomic.h>
3748 +
3749 +struct nf_logging_t {
3750 +       void (*nf_log_packet)(struct sk_buff **pskb,
3751 +                             unsigned int hooknum,
3752 +                             const struct net_device *in,
3753 +                             const struct net_device *out,
3754 +                             const char *prefix);
3755 +       void (*nf_log)(char *pfh, size_t len,
3756 +                      const char *prefix);
3757 +};
3758 +
3759 +extern void nf_log_register(int pf, const struct nf_logging_t *logging);
3760 +extern void nf_log_unregister(int pf, const struct nf_logging_t *logging);
3761 +
3762 +extern void nf_log_packet(int pf,
3763 +                         struct sk_buff **pskb,
3764 +                         unsigned int hooknum,
3765 +                         const struct net_device *in,
3766 +                         const struct net_device *out,
3767 +                         const char *fmt, ...);
3768 +extern void nf_log(int pf,
3769 +                  char *pfh, size_t len,
3770 +                  const char *fmt, ...);
3771 +#endif /*__KERNEL__*/
3772 +
3773 +#endif /*__LINUX_NETFILTER_LOGGING_H*/
3774 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/nfnetlink.h linux-2.4.20/include/linux/nfnetlink.h
3775 --- linux-2.4.20.org/include/linux/nfnetlink.h  Thu Jan  1 00:00:00 1970
3776 +++ linux-2.4.20/include/linux/nfnetlink.h      Wed Sep 24 09:17:51 2003
3777 @@ -0,0 +1,158 @@
3778 +#ifndef _NFNETLINK_H
3779 +#define _NFNETLINK_H
3780 +#include <linux/types.h>
3781 +
3782 +/* Generic structure for encapsulation optional netfilter information.
3783 + * It is reminiscent of sockaddr, but with sa_family replaced
3784 + * with attribute type. 
3785 + * ! This should someday be put somewhere generic as now rtnetlink and
3786 + * ! nfnetlink use the same attributes methods. - J. Schulist.
3787 + */
3788 +
3789 +struct nfattr
3790 +{
3791 +       unsigned short  nfa_len;
3792 +       unsigned short  nfa_type;
3793 +};
3794 +
3795 +#define NFA_ALIGNTO     4
3796 +#define NFA_ALIGN(len) (((len) + NFA_ALIGNTO - 1) & ~(NFA_ALIGNTO - 1))
3797 +#define NFA_OK(nfa,len)        ((len) > 0 && (nfa)->nfa_len >= sizeof(struct nfattr) \
3798 +       && (nfa)->nfa_len <= (len))
3799 +#define NFA_NEXT(nfa,attrlen)  ((attrlen) -= NFA_ALIGN((nfa)->nfa_len), \
3800 +       (struct nfattr *)(((char *)(nfa)) + NFA_ALIGN((nfa)->nfa_len)))
3801 +#define NFA_LENGTH(len)        (NFA_ALIGN(sizeof(struct nfattr)) + (len))
3802 +#define NFA_SPACE(len) NFA_ALIGN(NFA_LENGTH(len))
3803 +#define NFA_DATA(nfa)   ((void *)(((char *)(nfa)) + NFA_LENGTH(0)))
3804 +#define NFA_PAYLOAD(nfa) ((int)((nfa)->nfa_len) - NFA_LENGTH(0))
3805 +
3806 +/* General form of address family dependent message.
3807 + */
3808 +struct nfgenmsg {
3809 +       unsigned char nfgen_family;
3810 +};
3811 +
3812 +#if 0
3813 +struct iptgenmsg {
3814 +       unsigned char   iptgen_family;
3815 +       char            iptgen_table[IPT_TABLE_MAXNAMELEN];
3816 +};
3817 +
3818 +struct iptmsg {
3819 +       unsigned char   iptm_family;
3820 +       char            iptm_table[IPT_TABLE_MAXNAMELEN];
3821 +       char            iptm_chain[IPT_FUNCTION_MAXNAMELEN];
3822 +       unsigned int    iptm_entry_num;
3823 +};
3824 +
3825 +enum iptattr_type_t
3826 +{
3827 +       IPTA_UNSPEC,    /* [none] I don't know (unspecified). */
3828 +       IPTA_IP,        /* [ipt_ip] */
3829 +       IPTA_NFCACHE,   /* [u_int] */
3830 +       IPTA_COUNTERS,  /* [ipt_counters] */
3831 +       IPTA_MATCH,     /* [ipt_info] */
3832 +       IPTA_TARGET,    /* [ipt_info] */
3833 +       IPTA_MAX = IPTA_TARGET
3834 +};
3835 +
3836 +struct ipta_info {
3837 +       u_int16_t       size;
3838 +       char            name[IPT_FUNCTION_MAXNAMELEN];
3839 +       unsigned char   data[0];
3840 +};
3841 +
3842 +#define NFM_IPTA(n)    ((struct nfattr *)(((char *)(n)) \
3843 +       + NLMSG_ALIGN(sizeof(struct iptmsg))))
3844 +
3845 +#endif
3846 +
3847 +#define NFM_NFA(n)      ((struct nfattr *)(((char *)(n)) \
3848 +        + NLMSG_ALIGN(sizeof(struct nfgenmsg))))
3849 +#define NFM_PAYLOAD(n)  NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
3850 +
3851 +
3852 +#ifndef NETLINK_NETFILTER
3853 +#define NETLINK_NETFILTER      6
3854 +#endif
3855 +
3856 +/* netfilter netlink message types are split in two pieces:
3857 + * 8 bit subsystem, 8bit operation.
3858 + */
3859 +
3860 +#define NFNL_SUBSYS_ID(x)      ((x & 0xff00) >> 8)
3861 +#define NFNL_MSG_TYPE(x)       (x & 0x00ff)
3862 +
3863 +enum nfnl_subsys_id {
3864 +       NFNL_SUBSYS_NONE = 0,
3865 +       NFNL_SUBSYS_CTNETLINK,
3866 +       NFNL_SUBSYS_CTNETLINK_EXP,
3867 +       NFNL_SUBSYS_IPTNETLINK,
3868 +       NFNL_SUBSYS_QUEUE,
3869 +       NFNL_SUBSYS_ULOG,
3870 +       NFNL_SUBSYS_COUNT,
3871 +};
3872 +
3873 +#ifdef __KERNEL__
3874 +
3875 +#include <linux/capability.h>
3876 +
3877 +struct nfnl_callback
3878 +{
3879 +       kernel_cap_t cap_required; /* capabilities required for this msg */
3880 +       int (*call)(struct sock *nl, struct sk_buff *skb, 
3881 +               struct nlmsghdr *nlh, int *errp);
3882 +};
3883 +
3884 +struct nfnetlink_subsystem
3885 +{
3886 +       /* Internal use. */
3887 +       struct list_head list;
3888 +       
3889 +       const char *name;
3890 +       __u8 subsys_id;         /* nfnetlink subsystem ID */
3891 +       __u8 cb_count;          /* number of callbacks */
3892 +       u_int32_t attr_count;   /* number of nfattr's */
3893 +       struct nfnl_callback cb[0]; /* callback for individual types */
3894 +};
3895 +
3896 +extern void __nfa_fill(struct sk_buff *skb, int attrtype,
3897 +        int attrlen, const void *data);
3898 +#define NFA_PUT(skb, attrtype, attrlen, data) \
3899 +({ if (skb_tailroom(skb) < (int)NFA_SPACE(attrlen)) goto nfattr_failure; \
3900 +   __nfa_fill(skb, attrtype, attrlen, data); })
3901 +
3902 +extern struct semaphore nfnl_sem;
3903 +#define nfnl_exlock()          do { } while(0)
3904 +#define nfnl_exunlock()                do { } while(0)
3905 +#define nfnl_exlock_nowait()   (0)
3906 +
3907 +#define nfnl_shlock()          down(&nfnl_sem)
3908 +#define nfnl_shlock_nowait()   down_trylock(&nfnl_sem)
3909 +
3910 +#ifndef CONFIG_NF_NETLINK
3911 +#define nfnl_shunlock()                up(&nfnl_sem)
3912 +#else
3913 +#define nfnl_shunlock()                do { up(&nfnl_sem); \
3914 +                                       if(nfnl && nfnl->receive_queue.qlen) \
3915 +                                               nfnl->data_ready(nfnl, 0); \
3916 +                               } while(0)
3917 +#endif
3918 +
3919 +extern void nfnl_lock(void);
3920 +extern void nfnl_unlock(void);
3921 +
3922 +extern struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count);
3923 +extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n);
3924 +extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n);
3925 +
3926 +extern int nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
3927 +                                     struct nlmsghdr *nlh, 
3928 +                                     struct nfattr *cda[]);
3929 +extern int nfattr_parse(struct nfattr *tb[], int maxattr, 
3930 +                       struct nfattr *nfa, int len);
3931 +extern int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, 
3932 +                         int echo);
3933 +
3934 +#endif /* __KERNEL__ */
3935 +#endif /* _NFNETLINK_H */
3936 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/nfnetlink_conntrack.h linux-2.4.20/include/linux/nfnetlink_conntrack.h
3937 --- linux-2.4.20.org/include/linux/nfnetlink_conntrack.h        Thu Jan  1 00:00:00 1970
3938 +++ linux-2.4.20/include/linux/nfnetlink_conntrack.h    Wed Sep 24 09:17:51 2003
3939 @@ -0,0 +1,84 @@
3940 +#ifndef _NFNETLINK_CONNTRACK_H
3941 +#define _NFNETLINK_CONNTRACK_H
3942 +#include <linux/nfnetlink.h>
3943 +#include <linux/netfilter_ipv4/ip_conntrack.h>
3944 +//#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
3945 +
3946 +/* CTNETLINK for ip_conntrack */
3947 +
3948 +enum cntl_msg_types {
3949 +       CTNL_MSG_NEWCONNTRACK,
3950 +       CTNL_MSG_GETCONNTRACK,
3951 +       CTNL_MSG_DELCONNTRACK,
3952 +
3953 +       CTNL_MSG_NEWEXPECT,
3954 +       CTNL_MSG_GETEXPECT,
3955 +       CTNL_MSG_DELEXPECT,
3956 +       CTNL_MSG_CONFIRMEXPECT,
3957 +
3958 +       CTNL_MSG_COUNT,
3959 +};
3960 +
3961 +/* ctnetlink attribute types.
3962 + */
3963 +enum ctattr_type_t
3964 +{
3965 +       CTA_UNSPEC,     /* [none] I don't know (unspecified). */
3966 +       CTA_ORIG,       /* [ip_conntrack_tuple] Original tuple. */
3967 +       CTA_RPLY,       /* [ip_conntrack_tuple] Reply tuple. */
3968 +       CTA_IIF,        /* [char] Input interface name (ie eth0). */
3969 +       CTA_OIF,        /* [char] Output interface name (ie eth1). */
3970 +       CTA_STATUS,     /* [unsigned long] Status of connection. */
3971 +       CTA_INFO,       /* [unsigned long] Information (ctinfo). */
3972 +       CTA_PROTOINFO,  /* [cta_proto] Protocol specific ct information. */
3973 +       CTA_HELPINFO,   /* [cta_help] Helper specific information. */
3974 +       CTA_NATINFO,    /* [cta_nat] Any NAT transformations. */
3975 +       CTA_TIMEOUT,    /* [unsigne long] timer */
3976 +
3977 +       CTA_EXP_TIMEOUT,/* [fixme] timer */
3978 +       CTA_EXP_TUPLE,  /* [ip_conntrack_tuple] Expected tuple */
3979 +       CTA_EXP_MASK,   /* [ip_conntrack_tuple] Mask for EXP_TUPLE */
3980 +       CTA_EXP_SEQNO,  /* [u_int32_t] sequence number */
3981 +       CTA_EXP_PROTO,  /* [cta_exp_proto] */
3982 +       CTA_EXP_HELP,   /* [cta_exp_help] */
3983 +
3984 +        CTA_MAX = CTA_EXP_HELP
3985 +};
3986 +
3987 +/* Attribute specific data structures.
3988 + */
3989 +
3990 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3991 +#include <linux/netfilter_ipv4/ip_nat.h>
3992 +struct cta_nat {
3993 +       unsigned int num_manips;
3994 +       struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
3995 +};
3996 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
3997 +
3998 +struct cta_proto {
3999 +       unsigned char num_proto;        /* Protocol number IPPROTO_X */
4000 +       union ip_conntrack_proto proto;
4001 +};
4002 +
4003 +struct cta_help {
4004 +       struct ip_conntrack_tuple tuple;
4005 +       struct ip_conntrack_tuple mask;
4006 +       char name[31];                  /* name of conntrack helper */
4007 +       union ip_conntrack_help help;
4008 +};
4009 +
4010 +/* ctnetlink multicast groups: reports any change of ctinfo,
4011 + * ctstatus, or protocol state change.
4012 + */
4013 +#define NFGRP_IPV4_CT_TCP      0x01
4014 +#define NFGRP_IPV4_CT_UDP      0x02
4015 +#define NFGRP_IPV4_CT_ICMP     0x04
4016 +#define NFGRP_IPV4_CT_OTHER    0x08
4017 +
4018 +#define NFGRP_IPV6_CT_TCP       0x10
4019 +#define NFGRP_IPV6_CT_UDP       0x20
4020 +#define NFGRP_IPV6_CT_ICMP      0x40
4021 +#define NFGRP_IPV6_CT_OTHER    0x80
4022 +
4023 +#endif /* _NFNETLINK_CONNTRACK_H */
4024 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/linux/sysctl.h linux-2.4.20/include/linux/sysctl.h
4025 --- linux-2.4.20.org/include/linux/sysctl.h     Wed Sep 24 08:52:38 2003
4026 +++ linux-2.4.20/include/linux/sysctl.h Wed Sep 24 09:16:22 2003
4027 @@ -235,6 +235,7 @@
4028         NET_IPV4_NEIGH=17,
4029         NET_IPV4_ROUTE=18,
4030         NET_IPV4_FIB_HASH=19,
4031 +       NET_IPV4_NETFILTER=20,
4032  
4033         NET_IPV4_TCP_TIMESTAMPS=33,
4034         NET_IPV4_TCP_WINDOW_SCALING=34,
4035 @@ -343,6 +344,24 @@
4036         NET_IPV4_CONF_MEDIUM_ID=14,
4037  };
4038  
4039 +/* /proc/sys/net/ipv4/netfilter */
4040 +enum
4041 +{
4042 +       NET_IPV4_NF_CONNTRACK_MAX=1,
4043 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT=2,
4044 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV=3,
4045 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED=4,
4046 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT=5,
4047 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT=6,
4048 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK=7,
4049 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT=8,
4050 +       NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE=9,
4051 +       NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT=10,
4052 +       NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM=11,
4053 +       NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT=12,
4054 +       NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT=13,
4055 +};
4056
4057  /* /proc/sys/net/ipv6 */
4058  enum {
4059         NET_IPV6_CONF=16,
4060 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/net/ip6_route.h linux-2.4.20/include/net/ip6_route.h
4061 --- linux-2.4.20.org/include/net/ip6_route.h    Mon Dec 11 21:30:48 2000
4062 +++ linux-2.4.20/include/net/ip6_route.h        Wed Sep 24 09:16:14 2003
4063 @@ -31,6 +31,8 @@
4064  extern struct dst_entry *      ip6_route_output(struct sock *sk,
4065                                                  struct flowi *fl);
4066  
4067 +extern int                     ip6_route_me_harder(struct sk_buff *skb);
4068 +
4069  extern void                    ip6_route_init(void);
4070  extern void                    ip6_route_cleanup(void);
4071  
4072 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/net/tcp.h linux-2.4.20/include/net/tcp.h
4073 --- linux-2.4.20.org/include/net/tcp.h  Thu Nov 28 23:53:15 2002
4074 +++ linux-2.4.20/include/net/tcp.h      Wed Sep 24 09:17:52 2003
4075 @@ -140,6 +140,7 @@
4076  extern void tcp_bucket_unlock(struct sock *sk);
4077  extern int tcp_port_rover;
4078  extern struct sock *tcp_v4_lookup_listener(u32 addr, unsigned short hnum, int dif);
4079 +extern struct sock *tcp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 hnum, int dif);
4080  
4081  /* These are AF independent. */
4082  static __inline__ int tcp_bhashfn(__u16 lport)
4083 diff -Nur --exclude '*.orig' linux-2.4.20.org/include/net/udp.h linux-2.4.20/include/net/udp.h
4084 --- linux-2.4.20.org/include/net/udp.h  Thu Nov 22 19:47:15 2001
4085 +++ linux-2.4.20/include/net/udp.h      Wed Sep 24 09:17:52 2003
4086 @@ -69,6 +69,8 @@
4087  extern int     udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
4088  extern int     udp_disconnect(struct sock *sk, int flags);
4089  
4090 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
4091 +
4092  extern struct udp_mib udp_statistics[NR_CPUS*2];
4093  #define UDP_INC_STATS(field)           SNMP_INC_STATS(udp_statistics, field)
4094  #define UDP_INC_STATS_BH(field)                SNMP_INC_STATS_BH(udp_statistics, field)
4095 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/core/netfilter.c linux-2.4.20/net/core/netfilter.c
4096 --- linux-2.4.20.org/net/core/netfilter.c       Sat Aug  3 00:39:46 2002
4097 +++ linux-2.4.20/net/core/netfilter.c   Wed Sep 24 09:17:50 2003
4098 @@ -8,9 +8,12 @@
4099   *
4100   * February 2000: Modified by James Morris to have 1 queue per protocol.
4101   * 15-Mar-2000:   Added NF_REPEAT --RR.
4102 + * 08-May-2003:          Internal logging interface added by Jozsef Kadlecsik.
4103   */
4104  #include <linux/config.h>
4105 +#include <linux/kernel.h>
4106  #include <linux/netfilter.h>
4107 +#include <linux/netfilter_logging.h>
4108  #include <net/protocol.h>
4109  #include <linux/init.h>
4110  #include <linux/skbuff.h>
4111 @@ -57,6 +60,10 @@
4112         void *data;
4113  } queue_handler[NPROTO];
4114  
4115 +/**
4116 + * nf_register_hook - Register with a netfilter hook
4117 + * @reg: Hook operations to be registered
4118 + */
4119  int nf_register_hook(struct nf_hook_ops *reg)
4120  {
4121         struct list_head *i;
4122 @@ -73,6 +80,10 @@
4123         return 0;
4124  }
4125  
4126 +/**
4127 + * nf_unregister_hook - Unregister from a netfilter hook
4128 + * @reg: hook operations to be unregistered
4129 + */
4130  void nf_unregister_hook(struct nf_hook_ops *reg)
4131  {
4132         br_write_lock_bh(BR_NETPROTO_LOCK);
4133 @@ -373,6 +384,18 @@
4134         return NF_ACCEPT;
4135  }
4136  
4137 +/**
4138 + * nf_register_queue_handler - Registere a queue handler with netfilter
4139 + * @pf: protocol family
4140 + * @outfn: function called by core to enqueue a packet
4141 + * @data: opaque parameter, passed through
4142 + *
4143 + * This function registers a queue handler with netfilter.  There can only
4144 + * be one queue handler for every protocol family.
4145 + *
4146 + * A queue handler _must_ reinject every packet via nf_reinject, no
4147 + * matter what.
4148 + */
4149  int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
4150  {      
4151         int ret;
4152 @@ -390,7 +413,12 @@
4153         return ret;
4154  }
4155  
4156 -/* The caller must flush their queue before this */
4157 +/**
4158 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
4159 + * @pf: protocol family
4160 + *
4161 + * The caller must flush their queue before unregistering
4162 + */
4163  int nf_unregister_queue_handler(int pf)
4164  {
4165         br_write_lock_bh(BR_NETPROTO_LOCK);
4166 @@ -502,6 +530,15 @@
4167         return ret;
4168  }
4169  
4170 +/**
4171 + * nf_reinject - Reinject a packet from a queue handler
4172 + * @skb: the packet to be reinjected
4173 + * @info: info which was passed to the outfn() of the queue handler
4174 + * @verdict: verdict (NF_ACCEPT, ...) for this packet
4175 + *
4176 + * This is the function called by a queue handler to reinject a
4177 + * packet.
4178 + */
4179  void nf_reinject(struct sk_buff *skb, struct nf_info *info,
4180                  unsigned int verdict)
4181  {
4182 @@ -563,67 +600,134 @@
4183  {
4184         struct iphdr *iph = (*pskb)->nh.iph;
4185         struct rtable *rt;
4186 -       struct rt_key key = { dst:iph->daddr,
4187 -                             src:iph->saddr,
4188 -                             oif:(*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
4189 -                             tos:RT_TOS(iph->tos)|RTO_CONN,
4190 -#ifdef CONFIG_IP_ROUTE_FWMARK
4191 -                             fwmark:(*pskb)->nfmark
4192 -#endif
4193 -                           };
4194 -       struct net_device *dev_src = NULL;
4195 -       int err;
4196 -
4197 -       /* accomodate ip_route_output_slow(), which expects the key src to be
4198 -          0 or a local address; however some non-standard hacks like
4199 -          ipt_REJECT.c:send_reset() can cause packets with foreign
4200 -           saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
4201 -       if(key.src && !(dev_src = ip_dev_find(key.src)))
4202 -               key.src = 0;
4203 -
4204 -       if ((err=ip_route_output_key(&rt, &key)) != 0) {
4205 -               printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
4206 -                       NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
4207 -                       (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0,
4208 -                       RT_TOS(iph->tos)|RTO_CONN,
4209 +       struct rt_key key = {};
4210 +       struct dst_entry *odst;
4211 +       unsigned int hh_len;
4212 +
4213 +       /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
4214 +        * packets with foreign saddr to be appear on the NF_IP_LOCAL_OUT hook.
4215 +        */
4216 +       if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
4217 +               key.dst = iph->daddr;
4218 +               key.src = iph->saddr;
4219 +               key.oif = (*pskb)->sk ? (*pskb)->sk->bound_dev_if : 0;
4220 +               key.tos = RT_TOS(iph->tos);
4221  #ifdef CONFIG_IP_ROUTE_FWMARK
4222 -                       (*pskb)->nfmark,
4223 -#else
4224 -                       0UL,
4225 +               key.fwmark = (*pskb)->nfmark;
4226  #endif
4227 -                       err);
4228 -               goto out;
4229 -       }
4230 +               if (ip_route_output_key(&rt, &key) != 0)
4231 +                       return -1;
4232  
4233 -       /* Drop old route. */
4234 -       dst_release((*pskb)->dst);
4235 -
4236 -       (*pskb)->dst = &rt->u.dst;
4237 +               /* Drop old route. */
4238 +               dst_release((*pskb)->dst);
4239 +               (*pskb)->dst = &rt->u.dst;
4240 +       } else {
4241 +               /* non-local src, find valid iif to satisfy
4242 +                * rp-filter when calling ip_route_input. */
4243 +               key.dst = iph->saddr;
4244 +               if (ip_route_output_key(&rt, &key) != 0)
4245 +                       return -1;
4246 +
4247 +               odst = (*pskb)->dst;
4248 +               if (ip_route_input(*pskb, iph->daddr, iph->saddr,
4249 +                                  RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
4250 +                       dst_release(&rt->u.dst);
4251 +                       return -1;
4252 +               }
4253 +               dst_release(&rt->u.dst);
4254 +               dst_release(odst);
4255 +       }
4256 +       
4257 +       if ((*pskb)->dst->error)
4258 +               return -1;
4259  
4260         /* Change in oif may mean change in hh_len. */
4261 -       if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
4262 +       hh_len = (*pskb)->dst->dev->hard_header_len;
4263 +       if (skb_headroom(*pskb) < hh_len) {
4264                 struct sk_buff *nskb;
4265  
4266 -               nskb = skb_realloc_headroom(*pskb,
4267 -                                           (*pskb)->dst->dev->hard_header_len);
4268 -               if (!nskb) {
4269 -                       err = -ENOMEM;
4270 -                       goto out;
4271 -               }
4272 +               nskb = skb_realloc_headroom(*pskb, hh_len);
4273 +               if (!nskb)
4274 +                       return -1;
4275                 if ((*pskb)->sk)
4276                         skb_set_owner_w(nskb, (*pskb)->sk);
4277                 kfree_skb(*pskb);
4278                 *pskb = nskb;
4279         }
4280  
4281 -out:
4282 -       if (dev_src)
4283 -               dev_put(dev_src);
4284 -
4285 -       return err;
4286 +       return 0;
4287  }
4288  #endif /*CONFIG_INET*/
4289  
4290 +/* Internal logging interface, which relies on the real 
4291 +   LOG target modules */
4292 +
4293 +#define NF_LOG_PREFIXLEN               128
4294 +
4295 +static struct nf_logging_t nf_logging[NPROTO] = {};
4296 +static int reported = 0;
4297 +
4298 +void nf_log_register(int pf, const struct nf_logging_t *logging)
4299 +{
4300 +       br_write_lock_bh(BR_NETPROTO_LOCK);
4301 +       if (!nf_logging[pf].nf_log_packet) {
4302 +               nf_logging[pf].nf_log_packet = logging->nf_log_packet;
4303 +               nf_logging[pf].nf_log = logging->nf_log;
4304 +       }
4305 +       br_write_unlock_bh(BR_NETPROTO_LOCK);
4306 +}              
4307 +
4308 +void nf_log_unregister(int pf, const struct nf_logging_t *logging)
4309 +{
4310 +       br_write_lock_bh(BR_NETPROTO_LOCK);
4311 +       if (nf_logging[pf].nf_log_packet == logging->nf_log_packet) {
4312 +               nf_logging[pf].nf_log_packet = NULL;
4313 +               nf_logging[pf].nf_log = NULL;
4314 +       }
4315 +       br_write_unlock_bh(BR_NETPROTO_LOCK);
4316 +}              
4317 +
4318 +void nf_log_packet(int pf,
4319 +                  struct sk_buff **pskb,
4320 +                  unsigned int hooknum,
4321 +                  const struct net_device *in,
4322 +                  const struct net_device *out,
4323 +                  const char *fmt, ...)
4324 +{
4325 +       va_list args;
4326 +       char prefix[NF_LOG_PREFIXLEN];
4327 +       
4328 +       if (nf_logging[pf].nf_log_packet) {
4329 +               va_start(args, fmt);
4330 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
4331 +               va_end(args);
4332 +               nf_logging[pf].nf_log_packet(pskb, hooknum, in, out, prefix);
4333 +       } else if (!reported) {
4334 +               printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
4335 +                      "no backend logging module loaded in!\n");
4336 +               reported++;
4337 +       }
4338 +}
4339 +
4340 +void nf_log(int pf,
4341 +           char *pfh, size_t len,
4342 +           const char *fmt, ...)
4343 +{
4344 +       va_list args;
4345 +       char prefix[NF_LOG_PREFIXLEN];
4346 +       
4347 +       if (nf_logging[pf].nf_log) {
4348 +               va_start(args, fmt);
4349 +               vsnprintf(prefix, sizeof(prefix), fmt, args);
4350 +               va_end(args);
4351 +               nf_logging[pf].nf_log(pfh, len, prefix);
4352 +       } else if (!reported) {
4353 +               printk(KERN_WARNING "nf_log: can\'t log yet, "
4354 +                      "no backend logging module loaded in!\n");
4355 +               reported++;
4356 +       }
4357 +}
4358 +
4359  /* This does not belong here, but ipt_REJECT needs it if connection
4360     tracking in use: without this, connection may not be in hash table,
4361     and hence manufactured ICMP or RST packets will not be associated
4362 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/Config.in linux-2.4.20/net/ipv4/netfilter/Config.in
4363 --- linux-2.4.20.org/net/ipv4/netfilter/Config.in       Wed Sep 24 08:52:39 2003
4364 +++ linux-2.4.20/net/ipv4/netfilter/Config.in   Wed Sep 24 09:18:12 2003
4365 @@ -4,10 +4,29 @@
4366  mainmenu_option next_comment
4367  comment '  IP: Netfilter Configuration'
4368  
4369 +tristate 'Netfilter netlink interface' CONFIG_IP_NF_NETLINK
4370 +
4371  tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP_NF_CONNTRACK
4372  if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
4373 +  if [ "$CONFIG_IP_NF_CONNTRACK" = "y" ]; then
4374 +    dep_tristate '  Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_NETLINK
4375 +  else
4376 +    dep_tristate '  Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_CONNTRACK
4377 +  fi
4378    dep_tristate '  FTP protocol support' CONFIG_IP_NF_FTP $CONFIG_IP_NF_CONNTRACK
4379 +  dep_tristate '  talk protocol support' CONFIG_IP_NF_TALK $CONFIG_IP_NF_CONNTRACK
4380 +  dep_tristate '  RSH protocol support' CONFIG_IP_NF_RSH $CONFIG_IP_NF_CONNTRACK
4381 +  dep_tristate '  H.323 (netmeeting) support' CONFIG_IP_NF_H323 $CONFIG_IP_NF_CONNTRACK
4382 +  dep_tristate '  Eggdrop bot support' CONFIG_IP_NF_EGG $CONFIG_IP_NF_CONNTRACK
4383 +  bool '  Connection mark tracking support' CONFIG_IP_NF_CONNTRACK_MARK
4384 +  dep_tristate '  Amanda protocol support' CONFIG_IP_NF_AMANDA $CONFIG_IP_NF_CONNTRACK
4385 +  dep_tristate '  TFTP protocol support' CONFIG_IP_NF_TFTP $CONFIG_IP_NF_CONNTRACK
4386    dep_tristate '  IRC protocol support' CONFIG_IP_NF_IRC $CONFIG_IP_NF_CONNTRACK
4387 +  dep_tristate '  Quake III protocol support' CONFIG_IP_NF_QUAKE3 $CONFIG_IP_NF_CONNTRACK
4388 +  dep_tristate '  GRE protocol support' CONFIG_IP_NF_CT_PROTO_GRE $CONFIG_IP_NF_CONNTRACK
4389 +  dep_tristate '   PPTP protocol support' CONFIG_IP_NF_PPTP $CONFIG_IP_NF_CT_PROTO_GRE
4390 +  dep_tristate '  MMS protocol support' CONFIG_IP_NF_MMS $CONFIG_IP_NF_CONNTRACK
4391 +  dep_tristate '  CuSeeMe protocol support' CONFIG_IP_NF_CUSEEME $CONFIG_IP_NF_CONNTRACK
4392  fi
4393  
4394  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4395 @@ -15,39 +34,85 @@
4396  fi
4397  tristate 'IP tables support (required for filtering/masq/NAT)' CONFIG_IP_NF_IPTABLES
4398  if [ "$CONFIG_IP_NF_IPTABLES" != "n" ]; then
4399 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4400 +    tristate 'raw table support (required for NOTRACK/TRACE)' CONFIG_IP_NF_RAW $CONFIG_IP_NF_IPTABLES
4401 +  fi
4402  # The simple matches.
4403 +  if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
4404 +    dep_tristate '  RPC match support' CONFIG_IP_NF_MATCH_RPC $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES
4405 +  fi
4406    dep_tristate '  limit match support' CONFIG_IP_NF_MATCH_LIMIT $CONFIG_IP_NF_IPTABLES
4407 +  dep_tristate '  quota match support' CONFIG_IP_NF_MATCH_QUOTA $CONFIG_IP_NF_IPTABLES
4408 +
4409 +  dep_tristate '  IP address pool support' CONFIG_IP_NF_POOL $CONFIG_IP_NF_IPTABLES
4410 +  if [ "$CONFIG_IP_NF_POOL" = "y" -o "$CONFIG_IP_NF_POOL" = "m" ]; then
4411 +    bool '    enable statistics on pool usage' CONFIG_IP_POOL_STATISTICS n
4412 +  fi
4413 +
4414 +  dep_tristate '  IP range match support' CONFIG_IP_NF_MATCH_IPRANGE $CONFIG_IP_NF_IPTABLES
4415    dep_tristate '  MAC address match support' CONFIG_IP_NF_MATCH_MAC $CONFIG_IP_NF_IPTABLES
4416    dep_tristate '  Packet type match support' CONFIG_IP_NF_MATCH_PKTTYPE $CONFIG_IP_NF_IPTABLES
4417    dep_tristate '  netfilter MARK match support' CONFIG_IP_NF_MATCH_MARK $CONFIG_IP_NF_IPTABLES
4418    dep_tristate '  Multiple port match support' CONFIG_IP_NF_MATCH_MULTIPORT $CONFIG_IP_NF_IPTABLES
4419 +  dep_tristate '  Multiple port with ranges match support' CONFIG_IP_NF_MATCH_MPORT $CONFIG_IP_NF_IPTABLES
4420    dep_tristate '  TOS match support' CONFIG_IP_NF_MATCH_TOS $CONFIG_IP_NF_IPTABLES
4421 +  dep_tristate '  condition match support' CONFIG_IP_NF_MATCH_CONDITION $CONFIG_IP_NF_IPTABLES
4422 +  dep_tristate '  TIME match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_TIME $CONFIG_IP_NF_IPTABLES
4423 +  dep_tristate '  random match support' CONFIG_IP_NF_MATCH_RANDOM $CONFIG_IP_NF_IPTABLES
4424 +  dep_tristate '  psd match support' CONFIG_IP_NF_MATCH_PSD $CONFIG_IP_NF_IPTABLES
4425 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4426 +    dep_tristate '  OSF match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OSF $CONFIG_IP_NF_IPTABLES
4427 +  fi
4428 +  dep_tristate '  Nth match support' CONFIG_IP_NF_MATCH_NTH $CONFIG_IP_NF_IPTABLES
4429 +  dep_tristate '  IPV4OPTIONS match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_IPV4OPTIONS $CONFIG_IP_NF_IPTABLES
4430 +  dep_tristate '  fuzzy match support' CONFIG_IP_NF_MATCH_FUZZY $CONFIG_IP_NF_IPTABLES
4431 +  dep_tristate '  recent match support' CONFIG_IP_NF_MATCH_RECENT $CONFIG_IP_NF_IPTABLES
4432    dep_tristate '  ECN match support' CONFIG_IP_NF_MATCH_ECN $CONFIG_IP_NF_IPTABLES
4433   
4434    dep_tristate '  DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES
4435   
4436    dep_tristate '  AH/ESP match support' CONFIG_IP_NF_MATCH_AH_ESP $CONFIG_IP_NF_IPTABLES
4437    dep_tristate '  LENGTH match support' CONFIG_IP_NF_MATCH_LENGTH $CONFIG_IP_NF_IPTABLES
4438 +  dep_tristate '  U32 match support' CONFIG_IP_NF_MATCH_U32 $CONFIG_IP_NF_U32
4439    dep_tristate '  TTL match support' CONFIG_IP_NF_MATCH_TTL $CONFIG_IP_NF_IPTABLES
4440 +  dep_tristate '  address type match support' CONFIG_IP_NF_MATCH_ADDRTYPE $CONFIG_IP_NF_IPTABLES
4441    dep_tristate '  tcpmss match support' CONFIG_IP_NF_MATCH_TCPMSS $CONFIG_IP_NF_IPTABLES
4442 +  dep_tristate '  realm match support' CONFIG_IP_NF_MATCH_REALM $CONFIG_IP_NF_IPTABLES
4443    dep_tristate '  stealth match support' CONFIG_IP_NF_MATCH_STEALTH $CONFIG_IP_NF_IPTABLES
4444    if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
4445      dep_tristate '  Helper match support' CONFIG_IP_NF_MATCH_HELPER $CONFIG_IP_NF_IPTABLES
4446    fi
4447    if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
4448      dep_tristate '  Connection state match support' CONFIG_IP_NF_MATCH_STATE $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES 
4449 +    if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
4450 +      dep_tristate '  Connection mark match support' CONFIG_IP_NF_MATCH_CONNMARK $CONFIG_IP_NF_IPTABLES
4451 +    fi
4452 +    dep_tristate '  Connections/IP limit match support' CONFIG_IP_NF_MATCH_CONNLIMIT $CONFIG_IP_NF_IPTABLES
4453      dep_tristate '  Connection tracking match support' CONFIG_IP_NF_MATCH_CONNTRACK $CONFIG_IP_NF_CONNTRACK $CONFIG_IP_NF_IPTABLES 
4454    fi
4455    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4456      dep_tristate '  Unclean match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_UNCLEAN $CONFIG_IP_NF_IPTABLES
4457 +    dep_tristate '  String match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_STRING $CONFIG_IP_NF_IPTABLES
4458      dep_tristate '  Owner match support (EXPERIMENTAL)' CONFIG_IP_NF_MATCH_OWNER $CONFIG_IP_NF_IPTABLES
4459    fi
4460  # The targets
4461 +  if [ "$CONFIG_IP_NF_RAW" != "n" ]; then
4462 +    if [ "$CONFIG_IP_NF_CONNTRACK" != "n" ]; then
4463 +      dep_tristate '  NOTRACK target support' CONFIG_IP_NF_TARGET_NOTRACK $CONFIG_IP_NF_RAW
4464 +    fi
4465 +    dep_tristate '  TRACE target support' CONFIG_IP_NF_TARGET_TRACE $CONFIG_IP_NF_RAW
4466 +    if [ "$CONFIG_IP_NF_TARGET_TRACE" != "n" ]; then
4467 +      define_bool CONFIG_IP_NF_TARGET_TRACE_NEEDED y
4468 +    fi
4469 +  fi
4470    dep_tristate '  Packet filtering' CONFIG_IP_NF_FILTER $CONFIG_IP_NF_IPTABLES 
4471    if [ "$CONFIG_IP_NF_FILTER" != "n" ]; then
4472      dep_tristate '    REJECT target support' CONFIG_IP_NF_TARGET_REJECT $CONFIG_IP_NF_FILTER
4473 +dep_tristate '    NETLINK target support' CONFIG_IP_NF_TARGET_NETLINK $CONFIG_IP_NF_FILTER
4474 +    dep_tristate '    IPV4OPTSSTRIP target support' CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP $CONFIG_IP_NF_FILTER
4475      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4476        dep_tristate '    MIRROR target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_MIRROR $CONFIG_IP_NF_FILTER
4477 +      dep_tristate '    TARPIT target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_TARPIT $CONFIG_IP_NF_FILTER
4478      fi
4479    fi
4480  
4481 @@ -57,6 +122,45 @@
4482        define_bool CONFIG_IP_NF_NAT_NEEDED y
4483        dep_tristate '    MASQUERADE target support' CONFIG_IP_NF_TARGET_MASQUERADE $CONFIG_IP_NF_NAT
4484        dep_tristate '    REDIRECT target support' CONFIG_IP_NF_TARGET_REDIRECT $CONFIG_IP_NF_NAT
4485 +      # If they want talk, set to $CONFIG_IP_NF_NAT (m or y), 
4486 +      # or $CONFIG_IP_NF_TALK (m or y), whichever is weaker.  Argh.
4487 +      if [ "$CONFIG_IP_NF_TALK" = "m" ]; then
4488 +       define_tristate CONFIG_IP_NF_NAT_TALK m
4489 +      else
4490 +        if [ "$CONFIG_IP_NF_TALK" = "y" ]; then
4491 +          define_tristate CONFIG_IP_NF_NAT_TALK $CONFIG_IP_NF_NAT
4492 +        fi
4493 +      fi
4494 +      if [ "$CONFIG_IP_NF_H323" = "m" ]; then
4495 +       define_tristate CONFIG_IP_NF_NAT_H323 m
4496 +      else
4497 +        if [ "$CONFIG_IP_NF_H323" = "y" ]; then
4498 +          define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
4499 +        fi
4500 +      fi
4501 +      dep_tristate '    SAME target support' CONFIG_IP_NF_TARGET_SAME $CONFIG_IP_NF_NAT
4502 +      dep_tristate '    NETMAP target support' CONFIG_IP_NF_TARGET_NETMAP $CONFIG_IP_NF_NAT
4503 +      if [ "$CONFIG_IP_NF_AMANDA" = "m" ]; then
4504 +        define_tristate CONFIG_IP_NF_NAT_AMANDA m
4505 +      else
4506 +        if [ "$CONFIG_IP_NF_AMANDA" = "y" ]; then
4507 +          define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
4508 +        fi
4509 +      fi
4510 +      if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then
4511 +        define_tristate CONFIG_IP_NF_NAT_PPTP m
4512 +      else
4513 +        if [ "$CONFIG_IP_NF_PPTP" = "y" ]; then
4514 +          define_tristate CONFIG_IP_NF_NAT_PPTP $CONFIG_IP_NF_NAT
4515 +        fi
4516 +      fi
4517 +      if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "m" ]; then
4518 +        define_tristate CONFIG_IP_NF_NAT_PROTO_GRE m
4519 +      else
4520 +        if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "y" ]; then
4521 +         define_tristate CONFIG_IP_NF_NAT_PROTO_GRE $CONFIG_IP_NF_NAT
4522 +       fi
4523 +      fi
4524        bool '    NAT of local connections (READ HELP)' CONFIG_IP_NF_NAT_LOCAL
4525        if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
4526          dep_tristate '    Basic SNMP-ALG support (EXPERIMENTAL)' CONFIG_IP_NF_NAT_SNMP_BASIC $CONFIG_IP_NF_NAT
4527 @@ -68,6 +172,27 @@
4528            define_tristate CONFIG_IP_NF_NAT_IRC $CONFIG_IP_NF_NAT
4529          fi
4530        fi
4531 +      if [ "$CONFIG_IP_NF_QUAKE3" = "m" ]; then
4532 +        define_tristate CONFIG_IP_NF_NAT_QUAKE3 m
4533 +      else
4534 +        if [ "$CONFIG_IP_NF_QUAKE3" = "y" ]; then
4535 +         define_tristate CONFIG_IP_NF_NAT_QUAKE3 $CONFIG_IP_NF_NAT
4536 +        fi
4537 +      fi
4538 +      if [ "$CONFIG_IP_NF_MMS" = "m" ]; then
4539 +        define_tristate CONFIG_IP_NF_NAT_MMS m
4540 +      else
4541 +        if [ "$CONFIG_IP_NF_MMS" = "y" ]; then
4542 +          define_tristate CONFIG_IP_NF_NAT_MMS $CONFIG_IP_NF_NAT
4543 +        fi
4544 +      fi
4545 +      if [ "$CONFIG_IP_NF_CUSEEME" = "m" ]; then
4546 +        define_tristate CONFIG_IP_NF_NAT_CUSEEME m
4547 +      else
4548 +        if [ "$CONFIG_IP_NF_CUSEEME" = "y" ]; then
4549 +         define_tristate CONFIG_IP_NF_NAT_CUSEEME $CONFIG_IP_NF_NAT
4550 +        fi
4551 +      fi
4552        # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), 
4553        # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.  Argh.
4554        if [ "$CONFIG_IP_NF_FTP" = "m" ]; then
4555 @@ -77,6 +202,13 @@
4556            define_tristate CONFIG_IP_NF_NAT_FTP $CONFIG_IP_NF_NAT
4557          fi
4558        fi
4559 +      if [ "$CONFIG_IP_NF_TFTP" = "m" ]; then
4560 +       define_tristate CONFIG_IP_NF_NAT_TFTP m
4561 +      else
4562 +        if [ "$CONFIG_IP_NF_TFTP" = "y" ]; then
4563 +          define_tristate CONFIG_IP_NF_NAT_TFTP $CONFIG_IP_NF_NAT
4564 +        fi
4565 +      fi
4566      fi
4567    fi
4568  
4569 @@ -88,8 +220,19 @@
4570      dep_tristate '    DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
4571   
4572      dep_tristate '    MARK target support' CONFIG_IP_NF_TARGET_MARK $CONFIG_IP_NF_MANGLE
4573 +    dep_tristate '    ROUTE target support' CONFIG_IP_NF_TARGET_ROUTE $CONFIG_IP_NF_MANGLE
4574
4575 +    dep_tristate '    IPMARK target support' CONFIG_IP_NF_TARGET_IPMARK $CONFIG_IP_NF_MANGLE
4576 +    dep_tristate '    IMQ target support' CONFIG_IP_NF_TARGET_IMQ $CONFIG_IP_NF_MANGLE
4577 +    dep_tristate '    CLASSIFY target support (EXPERIMENTAL)' CONFIG_IP_NF_TARGET_CLASSIFY $CONFIG_IP_NF_FILTER
4578    fi
4579    dep_tristate '  LOG target support' CONFIG_IP_NF_TARGET_LOG $CONFIG_IP_NF_IPTABLES
4580 +  dep_tristate '  XOR target support' CONFIG_IP_NF_TARGET_XOR $CONFIG_IP_NF_IPTABLES
4581 +  dep_tristate '  TCPLAG target support' CONFIG_IP_NF_TARGET_TCPLAG $CONFIG_IP_NF_IPTABLES
4582 +  if [ "$CONFIG_IP_NF_CONNTRACK_MARK" != "n" ]; then
4583 +    dep_tristate '  CONNMARK target support' CONFIG_IP_NF_TARGET_CONNMARK $CONFIG_IP_NF_IPTABLES
4584 +  fi
4585 +  dep_tristate '  TTL target support' CONFIG_IP_NF_TARGET_TTL $CONFIG_IP_NF_IPTABLES
4586    dep_tristate '  ULOG target support' CONFIG_IP_NF_TARGET_ULOG $CONFIG_IP_NF_IPTABLES
4587    dep_tristate '  TCPMSS target support' CONFIG_IP_NF_TARGET_TCPMSS $CONFIG_IP_NF_IPTABLES
4588  fi
4589 @@ -98,6 +241,9 @@
4590  if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then
4591    dep_tristate '  ARP packet filtering' CONFIG_IP_NF_ARPFILTER $CONFIG_IP_NF_ARPTABLES 
4592  fi
4593 +if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then
4594 +  dep_tristate '  ARP payload mangling' CONFIG_IP_NF_ARP_MANGLE $CONFIG_IP_NF_ARPTABLES
4595 +fi
4596  
4597  # Backwards compatibility modules: only if you don't build in the others.
4598  if [ "$CONFIG_IP_NF_CONNTRACK" != "y" ]; then
4599 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/Makefile linux-2.4.20/net/ipv4/netfilter/Makefile
4600 --- linux-2.4.20.org/net/ipv4/netfilter/Makefile        Wed Sep 24 08:52:39 2003
4601 +++ linux-2.4.20/net/ipv4/netfilter/Makefile    Wed Sep 24 09:18:13 2003
4602 @@ -28,23 +28,85 @@
4603  ipfwadm-objs           := $(ip_nf_compat-objs) ipfwadm_core.o
4604  ipchains-objs          := $(ip_nf_compat-objs) ipchains_core.o
4605  
4606 +# netfilter netlink interface
4607 +obj-$(CONFIG_IP_NF_NETLINK) += nfnetlink.o
4608 +ifdef CONFIG_IP_NF_NETLINK
4609 +       export-objs += nfnetlink.o
4610 +endif
4611 +
4612 +# nfnetlink modules
4613 +obj-$(CONFIG_IP_NF_NETLINK_CONNTRACK) += nfnetlink_conntrack.o
4614 +
4615  # connection tracking
4616  obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
4617  
4618 +# talk protocol support
4619 +obj-$(CONFIG_IP_NF_TALK) += ip_conntrack_talk.o
4620 +ifdef CONFIG_IP_NF_TALK
4621 +       export-objs += ip_conntrack_talk.o
4622 +endif
4623 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
4624 +
4625
4626 +# H.323 support
4627 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
4628 +ifdef CONFIG_IP_NF_H323
4629 +       export-objs += ip_conntrack_h323.o
4630 +endif
4631 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
4632 +
4633 +
4634 +# connection tracking protocol helpers
4635 +obj-$(CONFIG_IP_NF_CT_PROTO_GRE) += ip_conntrack_proto_gre.o
4636 +ifdef CONFIG_IP_NF_CT_PROTO_GRE
4637 +       export-objs += ip_conntrack_proto_gre.o
4638 +endif
4639 +
4640 +# NAT protocol helpers
4641 +obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
4642 +
4643  # connection tracking helpers
4644 +obj-$(CONFIG_IP_NF_QUAKE3) += ip_conntrack_quake3.o
4645 +ifdef CONFIG_IP_NF_NAT_QUAKE3
4646 +       export-objs += ip_conntrack_quake3.o
4647 +endif
4648 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
4649 +ifdef CONFIG_IP_NF_NAT_PPTP
4650 +       export-objs += ip_conntrack_pptp.o
4651 +endif
4652 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
4653 +ifdef CONFIG_IP_NF_MMS
4654 +       export-objs += ip_conntrack_mms.o
4655 +endif
4656 +obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
4657 +ifdef CONFIG_IP_NF_AMANDA
4658 +       export-objs += ip_conntrack_amanda.o
4659 +endif
4660 +
4661 +obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
4662  obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
4663 -ifdef CONFIG_IP_NF_NAT_FTP
4664 +obj-$(CONFIG_IP_NF_RSH) += ip_conntrack_rsh.o
4665 +
4666 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
4667 +
4668 +ifdef CONFIG_IP_NF_FTP
4669         export-objs += ip_conntrack_ftp.o
4670  endif
4671  
4672  obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
4673 -ifdef CONFIG_IP_NF_NAT_IRC
4674 +ifdef CONFIG_IP_NF_IRC
4675         export-objs += ip_conntrack_irc.o
4676  endif
4677  
4678  # NAT helpers 
4679 +obj-$(CONFIG_IP_NF_NAT_PPTP) += ip_nat_pptp.o
4680 +obj-$(CONFIG_IP_NF_NAT_CUSEEME) += ip_nat_cuseeme.o
4681 +obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
4682 +obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
4683  obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
4684  obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
4685 +obj-$(CONFIG_IP_NF_NAT_QUAKE3) += ip_nat_quake3.o
4686 +obj-$(CONFIG_IP_NF_NAT_MMS) += ip_nat_mms.o
4687  
4688  # generic IP tables 
4689  obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
4690 @@ -53,46 +115,103 @@
4691  obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
4692  obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
4693  obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
4694 +obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
4695  
4696  # matches
4697 +obj-$(CONFIG_IP_NF_MATCH_RPC) += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o ipt_rpc.o
4698 +export-objs += ip_conntrack_rpc_tcp.o ip_conntrack_rpc_udp.o
4699 +
4700  obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o
4701  obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o
4702 +obj-$(CONFIG_IP_NF_MATCH_QUOTA) += ipt_quota.o
4703 +obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o
4704  obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o
4705 +obj-$(CONFIG_IP_NF_POOL) += ipt_pool.o ipt_POOL.o ip_pool.o
4706  obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o
4707  
4708  obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
4709  obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
4710 +
4711 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
4712 +
4713  obj-$(CONFIG_IP_NF_MATCH_OWNER) += ipt_owner.o
4714  obj-$(CONFIG_IP_NF_MATCH_TOS) += ipt_tos.o
4715 +obj-$(CONFIG_IP_NF_MATCH_CONDITION) += ipt_condition.o
4716 +
4717 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
4718 +
4719 +
4720 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
4721 +
4722 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
4723 +
4724 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
4725 +
4726 +
4727 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
4728 +
4729 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
4730 +
4731 +
4732 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
4733 +
4734 +obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
4735 +
4736  obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
4737  obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_dscp.o
4738  obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_ah.o ipt_esp.o
4739  
4740  obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
4741  
4742 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
4743 +
4744 +
4745  obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
4746  obj-$(CONFIG_IP_NF_MATCH_STATE) += ipt_state.o
4747 +obj-$(CONFIG_IP_NF_MATCH_CONNMARK) += ipt_connmark.o
4748 +obj-$(CONFIG_IP_NF_MATCH_CONNLIMIT) += ipt_connlimit.o
4749  obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o
4750  obj-$(CONFIG_IP_NF_MATCH_UNCLEAN) += ipt_unclean.o
4751 +obj-$(CONFIG_IP_NF_MATCH_STRING) += ipt_string.o
4752  obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o
4753 +obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
4754 +obj-$(CONFIG_IP_NF_MATCH_REALM) += ipt_realm.o
4755  obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
4756  
4757  # targets
4758  obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
4759  obj-$(CONFIG_IP_NF_TARGET_MIRROR) += ipt_MIRROR.o
4760 +obj-$(CONFIG_IP_NF_TARGET_TARPIT) += ipt_TARPIT.o
4761 +obj-$(CONFIG_IP_NF_TARGET_CLASSIFY) += ipt_CLASSIFY.o
4762  obj-$(CONFIG_IP_NF_TARGET_TOS) += ipt_TOS.o
4763  obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
4764  obj-$(CONFIG_IP_NF_TARGET_DSCP) += ipt_DSCP.o
4765  obj-$(CONFIG_IP_NF_TARGET_MARK) += ipt_MARK.o
4766 +obj-$(CONFIG_IP_NF_TARGET_IPMARK) += ipt_IPMARK.o
4767 +obj-$(CONFIG_IP_NF_TARGET_IMQ) += ipt_IMQ.o
4768  obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
4769  obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o
4770 +obj-$(CONFIG_IP_NF_TARGET_ROUTE) += ipt_ROUTE.o
4771 +obj-$(CONFIG_IP_NF_TARGET_SAME) += ipt_SAME.o
4772 +obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o
4773  obj-$(CONFIG_IP_NF_NAT_SNMP_BASIC) += ip_nat_snmp_basic.o
4774  obj-$(CONFIG_IP_NF_TARGET_LOG) += ipt_LOG.o
4775 +obj-$(CONFIG_IP_NF_TARGET_XOR) += ipt_XOR.o
4776 +obj-$(CONFIG_IP_NF_TARGET_TCPLAG) += ipt_TCPLAG.o
4777 +obj-$(CONFIG_IP_NF_TARGET_CONNMARK) += ipt_CONNMARK.o
4778 +obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o
4779 +
4780 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
4781 +
4782 +obj-$(CONFIG_IP_NF_TARGET_IPV4OPTSSTRIP) += ipt_IPV4OPTSSTRIP.o
4783  obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o
4784  obj-$(CONFIG_IP_NF_TARGET_TCPMSS) += ipt_TCPMSS.o
4785 +obj-$(CONFIG_IP_NF_TARGET_TRACE) += ipt_TRACE.o
4786 +obj-$(CONFIG_IP_NF_TARGET_NOTRACK) += ipt_NOTRACK.o
4787  
4788  # generic ARP tables
4789  obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
4790 +obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
4791  
4792  # just filtering instance of ARP tables for now
4793  obj-$(CONFIG_IP_NF_ARPFILTER) += arptable_filter.o
4794 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/arp_tables.c linux-2.4.20/net/ipv4/netfilter/arp_tables.c
4795 --- linux-2.4.20.org/net/ipv4/netfilter/arp_tables.c    Sat Aug  3 00:39:46 2002
4796 +++ linux-2.4.20/net/ipv4/netfilter/arp_tables.c        Wed Sep 24 09:16:17 2003
4797 @@ -136,6 +136,7 @@
4798                 dprintf("ARP hardware address length mismatch.\n");
4799                 dprintf("ar_hln: %02x info->arhln: %02x info->arhln_mask: %02x\n",
4800                         arphdr->ar_hln, arpinfo->arhln, arpinfo->arhln_mask);
4801 +               return 0;
4802         }
4803  
4804         src_devaddr = arpptr;
4805 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/arpt_mangle.c linux-2.4.20/net/ipv4/netfilter/arpt_mangle.c
4806 --- linux-2.4.20.org/net/ipv4/netfilter/arpt_mangle.c   Thu Jan  1 00:00:00 1970
4807 +++ linux-2.4.20/net/ipv4/netfilter/arpt_mangle.c       Wed Sep 24 09:16:17 2003
4808 @@ -0,0 +1,101 @@
4809 +/* module that allows mangling of the arp payload */
4810 +#include <linux/module.h>
4811 +#include <linux/netfilter_arp/arpt_mangle.h>
4812 +#include <net/sock.h>
4813 +
4814 +static unsigned int
4815 +target(struct sk_buff **pskb, unsigned int hooknum, const struct net_device *in,
4816 +   const struct net_device *out, const void *targinfo, void *userinfo)
4817 +{
4818 +       const struct arpt_mangle *mangle = targinfo;
4819 +       struct arphdr *arp;
4820 +       unsigned char *arpptr;
4821 +       int pln, hln;
4822 +
4823 +       if (skb_shared(*pskb) || skb_cloned(*pskb)) {
4824 +               struct sk_buff *nskb;
4825 +
4826 +               nskb = skb_copy(*pskb, GFP_ATOMIC);
4827 +               if (!nskb)
4828 +                       return NF_DROP;
4829 +               if ((*pskb)->sk)
4830 +                       skb_set_owner_w(nskb, (*pskb)->sk);
4831 +               kfree_skb(*pskb);
4832 +               *pskb = nskb;
4833 +       }
4834 +
4835 +       arp = (*pskb)->nh.arph;
4836 +       arpptr = (*pskb)->nh.raw + sizeof(*arp);
4837 +       pln = arp->ar_pln;
4838 +       hln = arp->ar_hln;
4839 +       /* We assume that hln was checked in the match */
4840 +       if (mangle->flags & ARPT_MANGLE_SDEV) {
4841 +               if (ARPT_DEV_ADDR_LEN_MAX < hln ||
4842 +                  (arpptr + hln > (**pskb).tail))
4843 +                       return NF_DROP;
4844 +               memcpy(arpptr, mangle->src_devaddr, hln);
4845 +       }
4846 +       arpptr += hln;
4847 +       if (mangle->flags & ARPT_MANGLE_SIP) {
4848 +               if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
4849 +                  (arpptr + pln > (**pskb).tail))
4850 +                       return NF_DROP;
4851 +               memcpy(arpptr, &mangle->u_s.src_ip, pln);
4852 +       }
4853 +       arpptr += pln;
4854 +       if (mangle->flags & ARPT_MANGLE_TDEV) {
4855 +               if (ARPT_DEV_ADDR_LEN_MAX < hln ||
4856 +                  (arpptr + hln > (**pskb).tail))
4857 +                       return NF_DROP;
4858 +               memcpy(arpptr, mangle->tgt_devaddr, hln);
4859 +       }
4860 +       arpptr += hln;
4861 +       if (mangle->flags & ARPT_MANGLE_TIP) {
4862 +               if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
4863 +                  (arpptr + pln > (**pskb).tail))
4864 +                       return NF_DROP;
4865 +               memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
4866 +       }
4867 +       return mangle->target;
4868 +}
4869 +
4870 +static int
4871 +checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo,
4872 +   unsigned int targinfosize, unsigned int hook_mask)
4873 +{
4874 +       const struct arpt_mangle *mangle = targinfo;
4875 +
4876 +       if (mangle->flags & ~ARPT_MANGLE_MASK ||
4877 +           !(mangle->flags & ARPT_MANGLE_MASK))
4878 +               return 0;
4879 +
4880 +       if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
4881 +          mangle->target != ARPT_CONTINUE)
4882 +               return 0;
4883 +       return 1;
4884 +}
4885 +
4886 +static struct arpt_target arpt_mangle_reg
4887 += {
4888 +        .name          = "mangle",
4889 +        .target                = target,
4890 +        .checkentry    = checkentry,
4891 +        .me            = THIS_MODULE,
4892 +};
4893 +
4894 +static int __init init(void)
4895 +{
4896 +       if (arpt_register_target(&arpt_mangle_reg))
4897 +               return -EINVAL;
4898 +
4899 +       return 0;
4900 +}
4901 +
4902 +static void __exit fini(void)
4903 +{
4904 +       arpt_unregister_target(&arpt_mangle_reg);
4905 +}
4906 +
4907 +module_init(init);
4908 +module_exit(fini);
4909 +MODULE_LICENSE("GPL");
4910 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_amanda.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_amanda.c
4911 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_amanda.c   Thu Jan  1 00:00:00 1970
4912 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_amanda.c       Wed Sep 24 09:16:24 2003
4913 @@ -0,0 +1,234 @@
4914 +/* Amanda extension for IP connection tracking, Version 0.2
4915 + * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
4916 + * based on HW's ip_conntrack_irc.c as well as other modules
4917 + *
4918 + *      This program is free software; you can redistribute it and/or
4919 + *      modify it under the terms of the GNU General Public License
4920 + *      as published by the Free Software Foundation; either version
4921 + *      2 of the License, or (at your option) any later version.
4922 + *
4923 + *     Module load syntax:
4924 + *     insmod ip_conntrack_amanda.o [master_timeout=n]
4925 + *     
4926 + *     Where master_timeout is the timeout (in seconds) of the master
4927 + *     connection (port 10080).  This defaults to 5 minutes but if
4928 + *     your clients take longer than 5 minutes to do their work
4929 + *     before getting back to the Amanda server, you can increase
4930 + *     this value.
4931 + *
4932 + */
4933 +
4934 +#include <linux/module.h>
4935 +#include <linux/netfilter.h>
4936 +#include <linux/ip.h>
4937 +#include <net/checksum.h>
4938 +#include <net/udp.h>
4939 +
4940 +#include <linux/netfilter_ipv4/lockhelp.h>
4941 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
4942 +#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
4943 +
4944 +static unsigned int master_timeout = 300;
4945 +
4946 +MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
4947 +MODULE_DESCRIPTION("Amanda connection tracking module");
4948 +MODULE_LICENSE("GPL");
4949 +MODULE_PARM(master_timeout, "i");
4950 +MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
4951 +
4952 +DECLARE_LOCK(ip_amanda_lock);
4953 +struct module *ip_conntrack_amanda = THIS_MODULE;
4954 +
4955 +#define MAXMATCHLEN    6
4956 +struct conn conns[NUM_MSGS] = {
4957 +       {"DATA ", 5},
4958 +       {"MESG ", 5},
4959 +       {"INDEX ", 6},
4960 +};
4961 +
4962 +#if 0
4963 +#define DEBUGP printk
4964 +#else
4965 +#define DEBUGP(format, args...)
4966 +#endif
4967 +
4968 +
4969 +/* FIXME: This should be in userspace.  Later. */
4970 +static int help(const struct iphdr *iph, size_t len,
4971 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
4972 +{
4973 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
4974 +       u_int32_t udplen = len - iph->ihl * 4;
4975 +       u_int32_t datalen = udplen - sizeof(struct udphdr);
4976 +       char *data = (char *)udph + sizeof(struct udphdr);
4977 +       char *datap = data;
4978 +       char *data_limit = (char *) data + datalen;
4979 +       int dir = CTINFO2DIR(ctinfo);
4980 +       struct ip_ct_amanda *info =
4981 +                               (struct ip_ct_amanda *)&ct->help.ct_ftp_info;
4982 +
4983 +       /* Can't track connections formed before we registered */
4984 +       if (!info)
4985 +               return NF_ACCEPT;
4986 +
4987 +       /* increase the UDP timeout of the master connection as replies from
4988 +        * Amanda clients to the server can be quite delayed */
4989 +       ip_ct_refresh(ct, master_timeout * HZ);
4990 +
4991 +       /* If packet is coming from Amanda server */
4992 +       if (dir == IP_CT_DIR_ORIGINAL)
4993 +               return NF_ACCEPT;
4994 +
4995 +       /* Not whole UDP header? */
4996 +       if (udplen < sizeof(struct udphdr)) {
4997 +               printk("ip_conntrack_amanda_help: udplen = %u\n",
4998 +                      (unsigned)udplen);
4999 +               return NF_ACCEPT;
5000 +       }
5001 +
5002 +       /* Checksum invalid?  Ignore. */
5003 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
5004 +                             csum_partial((char *)udph, udplen, 0))) {
5005 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u "
5006 +                      "%u.%u.%u.%u\n",
5007 +                      udph, udplen, NIPQUAD(iph->saddr),
5008 +                      NIPQUAD(iph->daddr));
5009 +               return NF_ACCEPT;
5010 +       }
5011 +       
5012 +       /* Search for the CONNECT string */
5013 +       while (data < data_limit) {
5014 +               if (!memcmp(data, "CONNECT ", 8)) {
5015 +                       break;
5016 +               }
5017 +               data++;
5018 +       }
5019 +       if (memcmp(data, "CONNECT ", 8))
5020 +               return NF_ACCEPT;
5021 +
5022 +       DEBUGP("ip_conntrack_amanda_help: CONNECT found in connection "
5023 +                  "%u.%u.%u.%u:%u %u.%u.%u.%u:%u\n",
5024 +                  NIPQUAD(iph->saddr), htons(udph->source),
5025 +                  NIPQUAD(iph->daddr), htons(udph->dest));
5026 +       data += 8;
5027 +       while (*data != 0x0a && data < data_limit) {
5028 +
5029 +               int i;
5030 +
5031 +               for (i = 0; i < NUM_MSGS; i++) {
5032 +                       if (!memcmp(data, conns[i].match,
5033 +                                  conns[i].matchlen)) {
5034 +
5035 +                               char *portchr;
5036 +                               struct ip_conntrack_expect expect;
5037 +                               struct ip_ct_amanda_expect
5038 +                                   *exp_amanda_info =
5039 +                                       &expect.help.exp_amanda_info;
5040 +
5041 +                               memset(&expect, 0, sizeof(expect));
5042 +
5043 +                               data += conns[i].matchlen;
5044 +                               /* this is not really tcp, but let's steal an
5045 +                                * idea from a tcp stream helper :-)
5046 +                                */
5047 +                               // XXX expect.seq = data - datap;
5048 +                               exp_amanda_info->offset = data - datap;
5049 +// XXX DEBUGP("expect.seq = %p - %p = %d\n", data, datap, expect.seq);
5050 +DEBUGP("exp_amanda_info->offset = %p - %p = %d\n", data, datap, exp_amanda_info->offset);
5051 +                               portchr = data;
5052 +                               exp_amanda_info->port =
5053 +                                   simple_strtoul(data, &data, 10);
5054 +                               exp_amanda_info->len = data - portchr;
5055 +
5056 +                               /* eat whitespace */
5057 +                               while (*data == ' ')
5058 +                                       data++;
5059 +                               DEBUGP ("ip_conntrack_amanda_help: "
5060 +                                       "CONNECT %s request with port "
5061 +                                       "%u found\n", conns[i].match,
5062 +                                       exp_amanda_info->port);
5063 +
5064 +                               LOCK_BH(&ip_amanda_lock);
5065 +
5066 +                               expect.tuple = ((struct ip_conntrack_tuple)
5067 +                                               { { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
5068 +                                                 { 0 } },
5069 +                                               { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
5070 +                                                 { htons(exp_amanda_info->port) },
5071 +                                         IPPROTO_TCP }});
5072 +                               expect.mask = ((struct ip_conntrack_tuple)
5073 +                                                          { { 0, { 0 } },
5074 +                                                                { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5075 +
5076 +                               expect.expectfn = NULL;
5077 +
5078 +                               DEBUGP ("ip_conntrack_amanda_help: "
5079 +                                       "expect_related: %u.%u.%u.%u:%u - "
5080 +                                       "%u.%u.%u.%u:%u\n",
5081 +                                       NIPQUAD(expect.tuple.src.ip),
5082 +                                       ntohs(expect.tuple.src.u.tcp.port),
5083 +                                       NIPQUAD(expect.tuple.dst.ip),
5084 +                                       ntohs(expect.tuple.dst.u.tcp.port));
5085 +                               if (ip_conntrack_expect_related(ct, &expect) ==
5086 +                                   -EEXIST) {
5087 +                                       ;
5088 +                                       /* this must be a packet being resent */
5089 +                                       /* XXX - how do I get the
5090 +                                        *       ip_conntrack_expect that
5091 +                                        *       already exists so that I can
5092 +                                        *       update the .seq so that the
5093 +                                        *       nat module rewrites the port
5094 +                                        *       numbers?
5095 +                                        *       Perhaps I should use the
5096 +                                        *       exp_amanda_info instead of
5097 +                                        *       .seq.
5098 +                                        */
5099 +                               }
5100 +                               UNLOCK_BH(&ip_amanda_lock);
5101 +                       } /* if memcmp(conns) */
5102 +               } /* for .. NUM_MSGS */
5103 +               data++;
5104 +       } /* while (*data != 0x0a && data < data_limit) */
5105 +
5106 +       return NF_ACCEPT;
5107 +}
5108 +
5109 +static struct ip_conntrack_helper amanda_helper;
5110 +
5111 +static void fini(void)
5112 +{
5113 +       DEBUGP("ip_ct_amanda: unregistering helper for port 10080\n");
5114 +       ip_conntrack_helper_unregister(&amanda_helper);
5115 +}
5116 +
5117 +static int __init init(void)
5118 +{
5119 +       int ret;
5120 +
5121 +       amanda_helper.tuple.src.u.udp.port = htons(10080);
5122 +       amanda_helper.tuple.dst.protonum = IPPROTO_UDP;
5123 +       amanda_helper.mask.src.u.udp.port = 0xFFFF;
5124 +       amanda_helper.mask.dst.protonum = 0xFFFF;
5125 +       amanda_helper.max_expected = NUM_MSGS;
5126 +       amanda_helper.timeout = 180;
5127 +       amanda_helper.flags = IP_CT_HELPER_F_REUSE_EXPECT;
5128 +       amanda_helper.me = ip_conntrack_amanda;
5129 +       amanda_helper.help = help;
5130 +       amanda_helper.name = "amanda";
5131 +
5132 +       DEBUGP("ip_ct_amanda: registering helper for port 10080\n");
5133 +
5134 +       ret = ip_conntrack_helper_register(&amanda_helper);
5135 +
5136 +       if (ret) {
5137 +               printk("ip_ct_amanda: ERROR registering helper\n");
5138 +               fini();
5139 +               return -EBUSY;
5140 +       }
5141 +       return 0;
5142 +}
5143 +
5144 +EXPORT_SYMBOL(ip_amanda_lock);
5145 +
5146 +module_init(init);
5147 +module_exit(fini);
5148 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_core.c
5149 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_core.c     Thu Nov 28 23:53:15 2002
5150 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_core.c Wed Sep 24 09:18:16 2003
5151 @@ -4,6 +4,7 @@
5152  
5153  /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
5154   * Public Licence. 
5155 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
5156   *
5157   * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
5158   *     - new API and handling of conntrack/nat helpers
5159 @@ -11,11 +12,10 @@
5160   * 16 Jul 2002: Harald Welte <laforge@gnumonks.org>
5161   *     - add usage/reference counts to ip_conntrack_expect
5162   *     - export ip_conntrack[_expect]_{find_get,put} functions
5163 + * 05 Aug 2002: Harald Welte <laforge@gnumonks.org>
5164 + *     - added DocBook-style comments for public API
5165   * */
5166  
5167 -#ifdef MODULE
5168 -#define __NO_VERSION__
5169 -#endif
5170  #include <linux/version.h>
5171  #include <linux/config.h>
5172  #include <linux/types.h>
5173 @@ -31,6 +31,8 @@
5174  #include <linux/stddef.h>
5175  #include <linux/sysctl.h>
5176  #include <linux/slab.h>
5177 +#include <linux/random.h>
5178 +#include <linux/jhash.h>
5179  /* For ERR_PTR().  Yeah, I know... --RR */
5180  #include <linux/fs.h>
5181  
5182 @@ -61,10 +63,11 @@
5183  LIST_HEAD(protocol_list);
5184  static LIST_HEAD(helpers);
5185  unsigned int ip_conntrack_htable_size = 0;
5186 -static int ip_conntrack_max = 0;
5187 +int ip_conntrack_max = 0;
5188  static atomic_t ip_conntrack_count = ATOMIC_INIT(0);
5189  struct list_head *ip_conntrack_hash;
5190  static kmem_cache_t *ip_conntrack_cachep;
5191 +struct ip_conntrack ip_conntrack_untracked;
5192  
5193  extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
5194  
5195 @@ -87,6 +90,10 @@
5196         return p;
5197  }
5198  
5199 +/**
5200 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
5201 + * @protocol: protocol number
5202 + */
5203  struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
5204  {
5205         struct ip_conntrack_protocol *p;
5206 @@ -107,20 +114,19 @@
5207         nf_conntrack_put(&ct->infos[0]);
5208  }
5209  
5210 -static inline u_int32_t
5211 +static int ip_conntrack_hash_rnd_initted;
5212 +static unsigned int ip_conntrack_hash_rnd;
5213 +
5214 +static u_int32_t
5215  hash_conntrack(const struct ip_conntrack_tuple *tuple)
5216  {
5217  #if 0
5218         dump_tuple(tuple);
5219  #endif
5220 -       /* ntohl because more differences in low bits. */
5221 -       /* To ensure that halves of the same connection don't hash
5222 -          clash, we add the source per-proto again. */
5223 -       return (ntohl(tuple->src.ip + tuple->dst.ip
5224 -                    + tuple->src.u.all + tuple->dst.u.all
5225 -                    + tuple->dst.protonum)
5226 -               + ntohs(tuple->src.u.all))
5227 -               % ip_conntrack_htable_size;
5228 +       return (jhash_3words(tuple->src.ip,
5229 +                            (tuple->dst.ip ^ tuple->dst.protonum),
5230 +                            (tuple->src.u.all | (tuple->dst.u.all << 16)),
5231 +                            ip_conntrack_hash_rnd) % ip_conntrack_htable_size);
5232  }
5233  
5234  inline int
5235 @@ -144,12 +150,22 @@
5236         tuple->dst.ip = iph->daddr;
5237         tuple->dst.protonum = iph->protocol;
5238  
5239 +       tuple->src.u.all = tuple->dst.u.all = 0;
5240 +
5241         ret = protocol->pkt_to_tuple((u_int32_t *)iph + iph->ihl,
5242                                      len - 4*iph->ihl,
5243                                      tuple);
5244         return ret;
5245  }
5246  
5247 +int
5248 +ip_conntrack_get_tuple(const struct iphdr *iph, size_t len,
5249 +                      struct ip_conntrack_tuple *tuple,
5250 +                      struct ip_conntrack_protocol *protocol)
5251 +{
5252 +       return get_tuple(iph, len, tuple, protocol);
5253 +}
5254 +
5255  static int
5256  invert_tuple(struct ip_conntrack_tuple *inverse,
5257              const struct ip_conntrack_tuple *orig,
5258 @@ -159,6 +175,8 @@
5259         inverse->dst.ip = orig->src.ip;
5260         inverse->dst.protonum = orig->dst.protonum;
5261  
5262 +       inverse->src.u.all = inverse->dst.u.all = 0;
5263 +
5264         return protocol->invert_tuple(inverse, orig);
5265  }
5266  
5267 @@ -176,8 +194,8 @@
5268  static void
5269  destroy_expect(struct ip_conntrack_expect *exp)
5270  {
5271 -       DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(exp->use));
5272 -       IP_NF_ASSERT(atomic_read(exp->use));
5273 +       DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(&exp->use));
5274 +       IP_NF_ASSERT(atomic_read(&exp->use));
5275         IP_NF_ASSERT(!timer_pending(&exp->timeout));
5276  
5277         kfree(exp);
5278 @@ -259,16 +277,14 @@
5279  }
5280  
5281  /* delete all unconfirmed expectations for this conntrack */
5282 -static void remove_expectations(struct ip_conntrack *ct)
5283 +static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
5284  {
5285         struct list_head *exp_entry, *next;
5286         struct ip_conntrack_expect *exp;
5287  
5288         DEBUGP("remove_expectations(%p)\n", ct);
5289  
5290 -       for (exp_entry = ct->sibling_list.next;
5291 -            exp_entry != &ct->sibling_list; exp_entry = next) {
5292 -               next = exp_entry->next;
5293 +       list_for_each_safe(exp_entry, next, &ct->sibling_list) {
5294                 exp = list_entry(exp_entry, struct ip_conntrack_expect,
5295                                  expected_list);
5296  
5297 @@ -276,6 +292,11 @@
5298                  * the un-established ones only */
5299                 if (exp->sibling) {
5300                         DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
5301 +                       if (drop_refcount) {
5302 +                               /* Indicate that this expectations parent is dead */
5303 +                               ip_conntrack_put(exp->expectant);
5304 +                               exp->expectant = NULL;
5305 +                       }
5306                         continue;
5307                 }
5308  
5309 @@ -290,20 +311,18 @@
5310  static void
5311  clean_from_lists(struct ip_conntrack *ct)
5312  {
5313 +       unsigned int ho, hr;
5314 +       
5315         DEBUGP("clean_from_lists(%p)\n", ct);
5316         MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
5317 -       /* Remove from both hash lists: must not NULL out next ptrs,
5318 -           otherwise we'll look unconfirmed.  Fortunately, LIST_DELETE
5319 -           doesn't do this. --RR */
5320 -       LIST_DELETE(&ip_conntrack_hash
5321 -                   [hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)],
5322 -                   &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
5323 -       LIST_DELETE(&ip_conntrack_hash
5324 -                   [hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple)],
5325 -                   &ct->tuplehash[IP_CT_DIR_REPLY]);
5326 +
5327 +       ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
5328 +       hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
5329 +       LIST_DELETE(&ip_conntrack_hash[ho], &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
5330 +       LIST_DELETE(&ip_conntrack_hash[hr], &ct->tuplehash[IP_CT_DIR_REPLY]);
5331  
5332         /* Destroy all un-established, pending expectations */
5333 -       remove_expectations(ct);
5334 +       remove_expectations(ct, 1);
5335  }
5336  
5337  static void
5338 @@ -316,9 +335,6 @@
5339         IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
5340         IP_NF_ASSERT(!timer_pending(&ct->timeout));
5341  
5342 -       if (ct->master && master_ct(ct))
5343 -               ip_conntrack_put(master_ct(ct));
5344 -
5345         /* To make sure we don't get any weird locking issues here:
5346          * destroy_conntrack() MUST NOT be called with a write lock
5347          * to ip_conntrack_lock!!! -HW */
5348 @@ -330,11 +346,17 @@
5349                 ip_conntrack_destroyed(ct);
5350  
5351         WRITE_LOCK(&ip_conntrack_lock);
5352 +       /* Delete us from our own list to prevent corruption later */
5353 +       list_del(&ct->sibling_list);
5354 +
5355         /* Delete our master expectation */
5356         if (ct->master) {
5357 -               /* can't call __unexpect_related here,
5358 -                * since it would screw up expect_list */
5359 -               list_del(&ct->master->expected_list);
5360 +               if (ct->master->expectant) {
5361 +                       /* can't call __unexpect_related here,
5362 +                        * since it would screw up expect_list */
5363 +                       list_del(&ct->master->expected_list);
5364 +                       ip_conntrack_put(ct->master->expectant);
5365 +               }
5366                 kfree(ct->master);
5367         }
5368         WRITE_UNLOCK(&ip_conntrack_lock);
5369 @@ -344,7 +366,7 @@
5370         atomic_dec(&ip_conntrack_count);
5371  }
5372  
5373 -static void death_by_timeout(unsigned long ul_conntrack)
5374 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
5375  {
5376         struct ip_conntrack *ct = (void *)ul_conntrack;
5377  
5378 @@ -369,16 +391,24 @@
5379                     const struct ip_conntrack *ignored_conntrack)
5380  {
5381         struct ip_conntrack_tuple_hash *h;
5382 +       unsigned int hash = hash_conntrack(tuple);
5383  
5384         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
5385 -       h = LIST_FIND(&ip_conntrack_hash[hash_conntrack(tuple)],
5386 +       h = LIST_FIND(&ip_conntrack_hash[hash],
5387                       conntrack_tuple_cmp,
5388                       struct ip_conntrack_tuple_hash *,
5389                       tuple, ignored_conntrack);
5390         return h;
5391  }
5392  
5393 -/* Find a connection corresponding to a tuple. */
5394 +/**
5395 + * ip_conntrack_find_get - find conntrack according to tuple
5396 + * @tuple: conntrack tuple for which we search conntrack
5397 + * @ignored_conntrack: ignore this conntrack during search
5398 + *
5399 + * This function increments the reference count of the found
5400 + * conntrack (if any).
5401 + */
5402  struct ip_conntrack_tuple_hash *
5403  ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
5404                       const struct ip_conntrack *ignored_conntrack)
5405 @@ -406,7 +436,14 @@
5406         return ct;
5407  }
5408  
5409 -/* Return conntrack and conntrack_info given skb->nfct->master */
5410 +/**
5411 + * ip_conntrack_get - Return conntrack and conntrack_info for given skb
5412 + * @skb: skb for which we want to find conntrack and conntrack_info
5413 + * @ctinfo: pointer to ctinfo, used as return value
5414 + *
5415 + * This function resolves the respective conntrack and conntrack_info
5416 + * structures for the connection this packet (skb) is part of.
5417 + */
5418  struct ip_conntrack *
5419  ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
5420  {
5421 @@ -467,6 +504,7 @@
5422                 ct->timeout.expires += jiffies;
5423                 add_timer(&ct->timeout);
5424                 atomic_inc(&ct->ct_general.use);
5425 +               set_bit(IPS_CONFIRMED_BIT, &ct->status);
5426                 WRITE_UNLOCK(&ip_conntrack_lock);
5427                 return NF_ACCEPT;
5428         }
5429 @@ -475,8 +513,14 @@
5430         return NF_DROP;
5431  }
5432  
5433 -/* Returns true if a connection correspondings to the tuple (required
5434 -   for NAT). */
5435 +/**
5436 + * ip_conntrack_tuple_taken - Find out if tuple is already in use
5437 + * @tuple: tuple to be used for this test
5438 + * @ignored_conntrack: conntrack which is excluded from result
5439 + *
5440 + * This function is called by the NAT code in order to find out if
5441 + * a particular tuple is already in use by some connection.
5442 + */
5443  int
5444  ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
5445                          const struct ip_conntrack *ignored_conntrack)
5446 @@ -585,7 +629,7 @@
5447     connection.  Too bad: we're in trouble anyway. */
5448  static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
5449  {
5450 -       return !(i->ctrack->status & IPS_ASSURED);
5451 +       return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
5452  }
5453  
5454  static int early_drop(struct list_head *chain)
5455 @@ -595,7 +639,7 @@
5456         int dropped = 0;
5457  
5458         READ_LOCK(&ip_conntrack_lock);
5459 -       h = LIST_FIND(chain, unreplied, struct ip_conntrack_tuple_hash *);
5460 +       h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *);
5461         if (h)
5462                 atomic_inc(&h->ctrack->ct_general.use);
5463         READ_UNLOCK(&ip_conntrack_lock);
5464 @@ -604,7 +648,7 @@
5465                 return dropped;
5466  
5467         if (del_timer(&h->ctrack->timeout)) {
5468 -               death_by_timeout((unsigned long)h->ctrack);
5469 +               ip_ct_death_by_timeout((unsigned long)h->ctrack);
5470                 dropped = 1;
5471         }
5472         ip_conntrack_put(h->ctrack);
5473 @@ -616,7 +660,13 @@
5474  {
5475         return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
5476  }
5477 -
5478 +/**
5479 + * ip_ct_find_helper - Find application helper according to tuple
5480 + * @tuple: tuple for which helper needs to be found
5481 + *
5482 + * This function is used to determine if any registered conntrack helper
5483 + * is to be used for the given tuple.
5484 + */
5485  struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
5486  {
5487         return LIST_FIND(&helpers, helper_cmp,
5488 @@ -633,11 +683,16 @@
5489  {
5490         struct ip_conntrack *conntrack;
5491         struct ip_conntrack_tuple repl_tuple;
5492 -       size_t hash, repl_hash;
5493 +       size_t hash;
5494         struct ip_conntrack_expect *expected;
5495         int i;
5496         static unsigned int drop_next = 0;
5497  
5498 +       if (!ip_conntrack_hash_rnd_initted) {
5499 +               get_random_bytes(&ip_conntrack_hash_rnd, 4);
5500 +               ip_conntrack_hash_rnd_initted = 1;
5501 +       }
5502 +
5503         hash = hash_conntrack(tuple);
5504  
5505         if (ip_conntrack_max &&
5506 @@ -661,7 +716,6 @@
5507                 DEBUGP("Can't invert tuple.\n");
5508                 return NULL;
5509         }
5510 -       repl_hash = hash_conntrack(&repl_tuple);
5511  
5512         conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
5513         if (!conntrack) {
5514 @@ -686,13 +740,10 @@
5515         /* Don't set timer yet: wait for confirmation */
5516         init_timer(&conntrack->timeout);
5517         conntrack->timeout.data = (unsigned long)conntrack;
5518 -       conntrack->timeout.function = death_by_timeout;
5519 +       conntrack->timeout.function = ip_ct_death_by_timeout;
5520  
5521         INIT_LIST_HEAD(&conntrack->sibling_list);
5522  
5523 -       /* Mark clearly that it's not in the hash table. */
5524 -       conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list.next = NULL;
5525 -
5526         WRITE_LOCK(&ip_conntrack_lock);
5527         /* Need finding and deleting of expected ONLY if we win race */
5528         READ_LOCK(&ip_conntrack_expect_tuple_lock);
5529 @@ -700,6 +751,14 @@
5530                              struct ip_conntrack_expect *, tuple);
5531         READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
5532  
5533 +       /* If master is not in hash table yet (ie. packet hasn't left
5534 +          this machine yet), how can other end know about expected?
5535 +          Hence these are not the droids you are looking for (if
5536 +          master ct never got confirmed, we'd hold a reference to it
5537 +          and weird things would happen to future packets). */
5538 +       if (expected && !is_confirmed(expected->expectant))
5539 +               expected = NULL;
5540 +
5541         /* Look up the conntrack helper for master connections only */
5542         if (!expected)
5543                 conntrack->helper = ip_ct_find_helper(&repl_tuple);
5544 @@ -710,19 +769,17 @@
5545             && ! del_timer(&expected->timeout))
5546                 expected = NULL;
5547  
5548 -       /* If master is not in hash table yet (ie. packet hasn't left
5549 -          this machine yet), how can other end know about expected?
5550 -          Hence these are not the droids you are looking for (if
5551 -          master ct never got confirmed, we'd hold a reference to it
5552 -          and weird things would happen to future packets). */
5553 -       if (expected && is_confirmed(expected->expectant)) {
5554 +       if (expected) {
5555                 DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
5556                         conntrack, expected);
5557                 /* Welcome, Mr. Bond.  We've been expecting you... */
5558                 IP_NF_ASSERT(master_ct(conntrack));
5559 -               conntrack->status = IPS_EXPECTED;
5560 +               __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
5561                 conntrack->master = expected;
5562                 expected->sibling = conntrack;
5563 +#if CONFIG_IP_NF_CONNTRACK_MARK
5564 +               conntrack->mark = expected->expectant->mark;
5565 +#endif
5566                 LIST_DELETE(&ip_conntrack_expect_list, expected);
5567                 expected->expectant->expecting--;
5568                 nf_conntrack_get(&master_ct(conntrack)->infos[0]);
5569 @@ -768,11 +825,11 @@
5570                 *set_reply = 1;
5571         } else {
5572                 /* Once we've had two way comms, always ESTABLISHED. */
5573 -               if (h->ctrack->status & IPS_SEEN_REPLY) {
5574 +               if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
5575                         DEBUGP("ip_conntrack_in: normal packet for %p\n",
5576                                h->ctrack);
5577                         *ctinfo = IP_CT_ESTABLISHED;
5578 -               } else if (h->ctrack->status & IPS_EXPECTED) {
5579 +               } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
5580                         DEBUGP("ip_conntrack_in: related packet for %p\n",
5581                                h->ctrack);
5582                         *ctinfo = IP_CT_RELATED;
5583 @@ -907,6 +964,14 @@
5584         return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
5585  }
5586  
5587 +/**
5588 + * ip_conntrack_unexpect_related - Unexpect a related connection
5589 + * @expect: expecattin to be removed
5590 + *
5591 + * This function removes an existing expectation, that has not yet been
5592 + * confirmed (i.e. expectation was issued, but expected connection didn't
5593 + * arrive yet)
5594 + */
5595  inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
5596  {
5597         WRITE_LOCK(&ip_conntrack_lock);
5598 @@ -924,7 +989,20 @@
5599         WRITE_UNLOCK(&ip_conntrack_lock);
5600  }
5601  
5602 -/* Add a related connection. */
5603 +/**
5604 + * ip_conntrack_expect_related - Expect a related connection
5605 + * @related_to: master conntrack
5606 + * @expect: expectation with all values filled in
5607 + *
5608 + * This function is called by conntrack application helpers who
5609 + * have detected that the control (master) connection is just about
5610 + * to negotiate a related slave connection. 
5611 + *
5612 + * Note: This function allocates it's own struct ip_conntrack_expect,
5613 + * copying the values from the 'expect' parameter.  Thus, 'expect' can
5614 + * be allocated on the stack and does not need to be valid after this
5615 + * function returns.
5616 + */
5617  int ip_conntrack_expect_related(struct ip_conntrack *related_to,
5618                                 struct ip_conntrack_expect *expect)
5619  {
5620 @@ -936,8 +1014,8 @@
5621          * so there is no need to use the tuple lock too */
5622  
5623         DEBUGP("ip_conntrack_expect_related %p\n", related_to);
5624 -       DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
5625 -       DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
5626 +       DEBUGP("tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
5627 +       DEBUGP("mask:  "); DUMP_TUPLE_RAW(&expect->mask);
5628  
5629         old = LIST_FIND(&ip_conntrack_expect_list, resent_expect,
5630                         struct ip_conntrack_expect *, &expect->tuple, 
5631 @@ -966,23 +1044,28 @@
5632                    related_to->expecting >= related_to->helper->max_expected) {
5633                 struct list_head *cur_item;
5634                 /* old == NULL */
5635 -               if (net_ratelimit())
5636 -                       printk(KERN_WARNING 
5637 -                              "ip_conntrack: max number of expected "
5638 -                              "connections %i of %s reached for "
5639 -                              "%u.%u.%u.%u->%u.%u.%u.%u%s\n",
5640 -                              related_to->helper->max_expected, 
5641 -                              related_to->helper->name,
5642 -                              NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5643 -                              NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
5644 -                              related_to->helper->flags & IP_CT_HELPER_F_REUSE_EXPECT ?
5645 -                              ", reusing" : "");
5646                 if (!(related_to->helper->flags & 
5647                       IP_CT_HELPER_F_REUSE_EXPECT)) {
5648                         WRITE_UNLOCK(&ip_conntrack_lock);
5649 +                       if (net_ratelimit())
5650 +                               printk(KERN_WARNING
5651 +                                      "ip_conntrack: max number of expected "
5652 +                                      "connections %i of %s reached for "
5653 +                                      "%u.%u.%u.%u->%u.%u.%u.%u\n",
5654 +                                      related_to->helper->max_expected,
5655 +                                      related_to->helper->name,
5656 +                                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5657 +                                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
5658                         return -EPERM;
5659                 }
5660 -
5661 +               DEBUGP("ip_conntrack: max number of expected "
5662 +                      "connections %i of %s reached for "
5663 +                      "%u.%u.%u.%u->%u.%u.%u.%u, reusing\n",
5664 +                      related_to->helper->max_expected,
5665 +                      related_to->helper->name,
5666 +                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
5667 +                      NIPQUAD(related_to->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip));
5668
5669                 /* choose the the oldest expectation to evict */
5670                 list_for_each(cur_item, &related_to->sibling_list) { 
5671                         struct ip_conntrack_expect *cur;
5672 @@ -1023,18 +1106,11 @@
5673                 return -ENOMEM;
5674         }
5675         
5676 -       /* Zero out the new structure, then fill out it with the data */
5677         DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
5678 -       memset(new, 0, sizeof(*expect));
5679 -       INIT_LIST_HEAD(&new->list);
5680 -       INIT_LIST_HEAD(&new->expected_list);
5681         memcpy(new, expect, sizeof(*expect));
5682         new->expectant = related_to;
5683         new->sibling = NULL;
5684 -       /* increase usage count. This sucks. The memset above overwrites
5685 -        * old usage count [if still present] and we increase to one.  Only
5686 -        * works because everything is done under ip_conntrack_lock() */
5687 -       atomic_inc(&new->use);
5688 +       atomic_set(&new->use, 1);
5689         
5690         /* add to expected list for this connection */  
5691         list_add(&new->expected_list, &related_to->sibling_list);
5692 @@ -1056,7 +1132,15 @@
5693         return ret;
5694  }
5695  
5696 -/* Change tuple in an existing expectation */
5697 +/**
5698 + * ip_conntrack_change_expect - Change tuple in existing expectation
5699 + * @expect: expectation which is to be changed
5700 + * @newtuple: new tuple for expect
5701 + *
5702 + * This function is mostly called by NAT application helpers, who want to
5703 + * change an expectation issued by their respective conntrack application
5704 + * helper counterpart.
5705 + */
5706  int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
5707                                struct ip_conntrack_tuple *newtuple)
5708  {
5709 @@ -1064,15 +1148,14 @@
5710  
5711         MUST_BE_READ_LOCKED(&ip_conntrack_lock);
5712         WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
5713 -
5714         DEBUGP("change_expect:\n");
5715 -       DEBUGP("exp tuple: "); DUMP_TUPLE(&expect->tuple);
5716 -       DEBUGP("exp mask:  "); DUMP_TUPLE(&expect->mask);
5717 -       DEBUGP("newtuple:  "); DUMP_TUPLE(newtuple);
5718 +       DEBUGP("exp tuple: "); DUMP_TUPLE_RAW(&expect->tuple);
5719 +       DEBUGP("exp mask:  "); DUMP_TUPLE_RAW(&expect->mask);
5720 +       DEBUGP("newtuple:  "); DUMP_TUPLE_RAW(newtuple);
5721         if (expect->ct_tuple.dst.protonum == 0) {
5722                 /* Never seen before */
5723                 DEBUGP("change expect: never seen before\n");
5724 -               if (!ip_ct_tuple_equal(&expect->tuple, newtuple) 
5725 +               if (!ip_ct_tuple_mask_cmp(&expect->tuple, newtuple, &expect->mask)
5726                     && LIST_FIND(&ip_conntrack_expect_list, expect_clash,
5727                                  struct ip_conntrack_expect *, newtuple, &expect->mask)) {
5728                         /* Force NAT to find an unused tuple */
5729 @@ -1097,8 +1180,15 @@
5730         return ret;
5731  }
5732  
5733 -/* Alter reply tuple (maybe alter helper).  If it's already taken,
5734 -   return 0 and don't do alteration. */
5735 +/**
5736 + * ip_conntrack_alter_reply - Alter reply tuple of conntrack
5737 + * @conntrack: conntrack whose reply tuple we want to alter
5738 + * @newreply: designated reply tuple for this conntrack
5739 + *
5740 + * This function alters the reply tuple of a conntrack to the given
5741 + * newreply tuple.  If this newreply tuple is already taken, return 0
5742 + * and don't do alteration
5743 + */
5744  int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
5745                              const struct ip_conntrack_tuple *newreply)
5746  {
5747 @@ -1123,6 +1213,13 @@
5748         return 1;
5749  }
5750  
5751 +/**
5752 + * ip_conntrack_helper_register - Register a conntrack application helper
5753 + * @me: structure describing the helper
5754 + *
5755 + * This function is called by conntrack application helpers to register
5756 + * themselves with the conntrack core.
5757 + */
5758  int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
5759  {
5760         MOD_INC_USE_COUNT;
5761 @@ -1139,13 +1236,20 @@
5762  {
5763         if (i->ctrack->helper == me) {
5764                 /* Get rid of any expected. */
5765 -               remove_expectations(i->ctrack);
5766 +               remove_expectations(i->ctrack, 0);
5767                 /* And *then* set helper to NULL */
5768                 i->ctrack->helper = NULL;
5769         }
5770         return 0;
5771  }
5772  
5773 +/**
5774 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
5775 + * @me: structure describing the helper
5776 + *
5777 + * This function is called by conntrack application helpers to unregister
5778 + * themselvers from the conntrack core.
5779 + */
5780  void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
5781  {
5782         unsigned int i;
5783 @@ -1167,7 +1271,14 @@
5784         MOD_DEC_USE_COUNT;
5785  }
5786  
5787 -/* Refresh conntrack for this many jiffies. */
5788 +/**
5789 + * ip_ct_refresh - Refresh conntrack timer for given conntrack
5790 + * @ct: conntrack which we want to refresh
5791 + * @extra_jiffies: number of jiffies to add
5792 + *
5793 + * This function is called by protocol helpers and application helpers in
5794 + * order to change the expiration timer of a conntrack entry.
5795 + */
5796  void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
5797  {
5798         IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
5799 @@ -1177,8 +1288,10 @@
5800         if (!is_confirmed(ct))
5801                 ct->timeout.expires = extra_jiffies;
5802         else {
5803 -               /* Need del_timer for race avoidance (may already be dying). */
5804 -               if (del_timer(&ct->timeout)) {
5805 +               /* Don't update timer for each packet, only if it's been >HZ
5806 +                * ticks since last update.
5807 +                * Need del_timer for race avoidance (may already be dying). */
5808 +               if (abs(jiffies + extra_jiffies - ct->timeout.expires) >= HZ && del_timer(&ct->timeout)) {
5809                         ct->timeout.expires = jiffies + extra_jiffies;
5810                         add_timer(&ct->timeout);
5811                 }
5812 @@ -1186,7 +1299,16 @@
5813         WRITE_UNLOCK(&ip_conntrack_lock);
5814  }
5815  
5816 -/* Returns new sk_buff, or NULL */
5817 +
5818 +/**
5819 + * ip_ct_gather_frags - Gather fragments of a particular skb
5820 + * @skb: pointer to sk_buff of fragmented IP packet
5821 + *
5822 + * This code is just a wrapper around the defragmentation code in the core IPv4
5823 + * stack.  It also takes care of nonlinear skb's.
5824 + *
5825 + * Returns new sk_buff, or NULL
5826 + */
5827  struct sk_buff *
5828  ip_ct_gather_frags(struct sk_buff *skb)
5829  {
5830 @@ -1274,6 +1396,16 @@
5831         return h;
5832  }
5833  
5834 +/**
5835 + * ip_ct_selective_cleanup - Selectively delete a set of conntrack entries
5836 + * @kill: callback function selecting which entries to delete
5837 + * @data: opaque data pointer, becomes 2nd argument for kill function
5838 + *
5839 + * This function can be used to selectively delete elements of the conntrack
5840 + * hashtable.  The function iterates over the list of conntrack entries and
5841 + * calls the 'kill' function for every entry.  If the return value is true,
5842 + * the connection is deleted (death_by_timeout).
5843 + */
5844  void
5845  ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
5846                         void *data)
5847 @@ -1284,7 +1416,7 @@
5848         while ((h = get_next_corpse(kill, data)) != NULL) {
5849                 /* Time to push up daises... */
5850                 if (del_timer(&h->ctrack->timeout))
5851 -                       death_by_timeout((unsigned long)h->ctrack);
5852 +                       ip_ct_death_by_timeout((unsigned long)h->ctrack);
5853                 /* ... else the timer will get him soon. */
5854  
5855                 ip_conntrack_put(h->ctrack);
5856 @@ -1299,9 +1431,14 @@
5857  getorigdst(struct sock *sk, int optval, void *user, int *len)
5858  {
5859         struct ip_conntrack_tuple_hash *h;
5860 -       struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { sk->sport } },
5861 -                                           { sk->daddr, { sk->dport },
5862 -                                             IPPROTO_TCP } };
5863 +       struct ip_conntrack_tuple tuple;
5864 +
5865 +       IP_CT_TUPLE_BLANK(&tuple);
5866 +       tuple.src.ip = sk->rcv_saddr;
5867 +       tuple.src.u.tcp.port = sk->sport;
5868 +       tuple.dst.ip = sk->daddr;
5869 +       tuple.dst.u.tcp.port = sk->dport;
5870 +       tuple.dst.protonum = IPPROTO_TCP;
5871  
5872         /* We only do TCP at the moment: is there a better way? */
5873         if (strcmp(sk->prot->name, "TCP") != 0) {
5874 @@ -1345,29 +1482,6 @@
5875      SO_ORIGINAL_DST, SO_ORIGINAL_DST+1, &getorigdst,
5876      0, NULL };
5877  
5878 -#define NET_IP_CONNTRACK_MAX 2089
5879 -#define NET_IP_CONNTRACK_MAX_NAME "ip_conntrack_max"
5880 -
5881 -#ifdef CONFIG_SYSCTL
5882 -static struct ctl_table_header *ip_conntrack_sysctl_header;
5883 -
5884 -static ctl_table ip_conntrack_table[] = {
5885 -       { NET_IP_CONNTRACK_MAX, NET_IP_CONNTRACK_MAX_NAME, &ip_conntrack_max,
5886 -         sizeof(ip_conntrack_max), 0644,  NULL, proc_dointvec },
5887 -       { 0 }
5888 -};
5889 -
5890 -static ctl_table ip_conntrack_dir_table[] = {
5891 -       {NET_IPV4, "ipv4", NULL, 0, 0555, ip_conntrack_table, 0, 0, 0, 0, 0},
5892 -       { 0 }
5893 -};
5894 -
5895 -static ctl_table ip_conntrack_root_table[] = {
5896 -       {CTL_NET, "net", NULL, 0, 0555, ip_conntrack_dir_table, 0, 0, 0, 0, 0},
5897 -       { 0 }
5898 -};
5899 -#endif /*CONFIG_SYSCTL*/
5900 -
5901  static int kill_all(const struct ip_conntrack *i, void *data)
5902  {
5903         return 1;
5904 @@ -1377,9 +1491,6 @@
5905     supposed to kill the mall. */
5906  void ip_conntrack_cleanup(void)
5907  {
5908 -#ifdef CONFIG_SYSCTL
5909 -       unregister_sysctl_table(ip_conntrack_sysctl_header);
5910 -#endif
5911         ip_ct_attach = NULL;
5912         /* This makes sure all current packets have passed through
5913             netfilter framework.  Roll on, two-stage module
5914 @@ -1423,7 +1534,7 @@
5915         ip_conntrack_max = 8 * ip_conntrack_htable_size;
5916  
5917         printk("ip_conntrack version %s (%u buckets, %d max)"
5918 -              " - %d bytes per conntrack\n", IP_CONNTRACK_VERSION,
5919 +              " - %Zd bytes per conntrack\n", IP_CONNTRACK_VERSION,
5920                ip_conntrack_htable_size, ip_conntrack_max,
5921                sizeof(struct ip_conntrack));
5922  
5923 @@ -1458,23 +1569,19 @@
5924         for (i = 0; i < ip_conntrack_htable_size; i++)
5925                 INIT_LIST_HEAD(&ip_conntrack_hash[i]);
5926  
5927 -/* This is fucking braindead.  There is NO WAY of doing this without
5928 -   the CONFIG_SYSCTL unless you don't want to detect errors.
5929 -   Grrr... --RR */
5930 -#ifdef CONFIG_SYSCTL
5931 -       ip_conntrack_sysctl_header
5932 -               = register_sysctl_table(ip_conntrack_root_table, 0);
5933 -       if (ip_conntrack_sysctl_header == NULL) {
5934 -               goto err_free_ct_cachep;
5935 -       }
5936 -#endif /*CONFIG_SYSCTL*/
5937 -
5938         /* For use by ipt_REJECT */
5939         ip_ct_attach = ip_conntrack_attach;
5940 +       
5941 +       /* Set up fake conntrack:
5942 +           - to never be deleted, not in any hashes */
5943 +       atomic_set(&ip_conntrack_untracked.ct_general.use, 1);
5944 +       /*  - and look it like as a confirmed connection */
5945 +       set_bit(IPS_CONFIRMED_BIT, &ip_conntrack_untracked.status);
5946 +       /*  - and prepare the ctinfo field for NAT. */
5947 +       ip_conntrack_untracked.infos[IP_CT_NEW].master = &ip_conntrack_untracked.ct_general;
5948 +       
5949         return ret;
5950  
5951 -err_free_ct_cachep:
5952 -       kmem_cache_destroy(ip_conntrack_cachep);
5953  err_free_hash:
5954         vfree(ip_conntrack_hash);
5955  err_unreg_sockopt:
5956 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_egg.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_egg.c
5957 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_egg.c      Thu Jan  1 00:00:00 1970
5958 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_egg.c  Wed Sep 24 09:17:40 2003
5959 @@ -0,0 +1,237 @@
5960 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
5961 + * based on ip_conntrack_irc.c 
5962 + *
5963 + *      This module only supports the share userfile-send command,
5964 + *      used by eggdrops to share it's userfile.
5965 + *
5966 + *      There are no support for NAT at the moment.
5967 + *
5968 + *      This program is free software; you can redistribute it and/or
5969 + *      modify it under the terms of the GNU General Public License
5970 + *      as published by the Free Software Foundation; either version
5971 + *      2 of the License, or (at your option) any later version.
5972 + *
5973 + *     Module load syntax:
5974 + *     
5975 + *     please give the ports of all Eggdrops You have running
5976 + *      on your system, the default port is 3333.
5977 + *
5978 + *      2001-04-19: Security update. IP addresses are now compared
5979 + *                  to prevent unauthorized "related" access.
5980 + *
5981 + *      2002-03-25: Harald Welte <laforge@gnumonks.org>:
5982 + *                 Port to netfilter 'newnat' API.
5983 + */
5984 +
5985 +#include <linux/module.h>
5986 +#include <linux/netfilter.h>
5987 +#include <linux/ip.h>
5988 +#include <net/checksum.h>
5989 +#include <net/tcp.h>
5990 +
5991 +#include <linux/netfilter_ipv4/lockhelp.h>
5992 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5993 +
5994 +#define MAX_PORTS 8
5995 +static int ports[MAX_PORTS];
5996 +static int ports_c = 0;
5997 +static unsigned int egg_timeout = 300;
5998 +
5999 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
6000 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
6001 +MODULE_LICENSE("GPL");
6002 +#ifdef MODULE_PARM
6003 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6004 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
6005 +#endif
6006 +
6007 +DECLARE_LOCK(ip_egg_lock);
6008 +struct module *ip_conntrack_egg = THIS_MODULE;
6009 +
6010 +#if 0
6011 +#define DEBUGP printk
6012 +#else
6013 +#define DEBUGP(format, args...)
6014 +#endif
6015 +
6016 +int parse_command(char *data, char *data_end, u_int32_t * ip, u_int16_t * port)
6017 +/* tries to get the ip_addr and port out of a eggdrop command
6018 +   return value: -1 on failure, 0 on success 
6019 +   data                pointer to first byte of DCC command data
6020 +   data_end    pointer to last byte of dcc command data
6021 +   ip          returns parsed ip of dcc command
6022 +   port                returns parsed port of dcc command */
6023 +{
6024 +       if (data > data_end)
6025 +               return -1;
6026 +       
6027 +       *ip = simple_strtoul(data, &data, 10);
6028 +
6029 +       /* skip blanks between ip and port */
6030 +       while (*data == ' ' && data < data_end)
6031 +               data++;
6032 +
6033 +       *port = simple_strtoul(data, &data, 10);
6034 +       return 0;
6035 +}
6036 +
6037 +
6038 +static int help(const struct iphdr *iph, size_t len,
6039 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
6040 +{
6041 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
6042 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
6043 +       char *data = (char *) tcph + tcph->doff * 4;
6044 +       char *data_limit;
6045 +       u_int32_t tcplen = len - iph->ihl * 4;
6046 +       u_int32_t datalen = tcplen - tcph->doff * 4;
6047 +       int dir = CTINFO2DIR(ctinfo);
6048 +       int bytes_scanned = 0;
6049 +       struct ip_conntrack_expect exp;
6050 +
6051 +       u_int32_t egg_ip;
6052 +       u_int16_t egg_port;
6053 +
6054 +       DEBUGP("entered\n");
6055 +
6056 +       /* If packet is coming from IRC server */
6057 +       if (dir != IP_CT_DIR_REPLY)
6058 +               return NF_ACCEPT;
6059 +
6060 +       /* Until there's been traffic both ways, don't look in packets. */
6061 +       if (ctinfo != IP_CT_ESTABLISHED
6062 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6063 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
6064 +               return NF_ACCEPT;
6065 +       }
6066 +
6067 +       /* Not whole TCP header? */
6068 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6069 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
6070 +               return NF_ACCEPT;
6071 +       }
6072 +
6073 +       /* Checksum invalid?  Ignore. */
6074 +       /* FIXME: Source route IP option packets --RR */
6075 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6076 +                        csum_partial((char *) tcph, tcplen, 0))) {
6077 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u -> %u.%u.%u.%u\n",
6078 +                       tcph, tcplen, NIPQUAD(iph->saddr),
6079 +                       NIPQUAD(iph->daddr));
6080 +               return NF_ACCEPT;
6081 +       }
6082 +
6083 +       data_limit = (char *) data + datalen;
6084 +       while (datalen > 5 && bytes_scanned < 128) {
6085 +               if (memcmp(data, "s us ", 5)) {
6086 +                       data++;
6087 +                       datalen--;
6088 +                       bytes_scanned++;
6089 +                       continue;
6090 +               }
6091 +
6092 +               data += 5;
6093 +
6094 +               DEBUGP("Userfile-share found in connection "
6095 +                       "%u.%u.%u.%u -> %u.%u.%u.%u\n",
6096 +                       NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6097 +
6098 +               if (parse_command((char *) data, data_limit, &egg_ip,
6099 +                                 &egg_port)) {
6100 +                       DEBUGP("no data in userfile-share pkt\n");
6101 +                       return NF_ACCEPT;
6102 +               }
6103 +
6104 +               memset(&exp, 0, sizeof(exp));
6105 +
6106 +               if (ct->tuplehash[dir].tuple.src.ip != htonl(egg_ip)) {
6107 +                       if (net_ratelimit())
6108 +                               printk("Forged Eggdrop command from "
6109 +                                      "%u.%u.%u.%u: %u.%u.%u.%u:%u\n",
6110 +                                      NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
6111 +                                      HIPQUAD(egg_ip), egg_port);
6112 +                       return NF_ACCEPT;
6113 +               }
6114 +
6115 +               exp.tuple.src.ip = iph->daddr;
6116 +               exp.tuple.src.u.tcp.port = 0;
6117 +               exp.tuple.dst.ip = htonl(egg_ip);
6118 +               exp.tuple.dst.u.tcp.port = htons(egg_port);
6119 +               exp.tuple.dst.protonum = IPPROTO_TCP;
6120 +
6121 +               exp.mask.dst.u.tcp.port = 0xffff;
6122 +               exp.mask.dst.protonum = 0xffff;
6123 +
6124 +               DEBUGP("expect_related %u.%u.%u.%u:%u - %u.%u.%u.%u:%u\n",
6125 +                       NIPQUAD(t.src.ip), ntohs(t.src.u.tcp.port),
6126 +                       NIPQUAD(t.dst.ip), ntohs(t.dst.u.tcp.port));
6127 +
6128 +               ip_conntrack_expect_related(ct, &exp);
6129 +               break;
6130 +       }
6131 +       return NF_ACCEPT;
6132 +}
6133 +
6134 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
6135 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
6136 +
6137 +static void deregister_helpers(void) {
6138 +       int i;
6139 +       
6140 +       for (i = 0; i < ports_c; i++) {
6141 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
6142 +               ip_conntrack_helper_unregister(&egg_helpers[i]);
6143 +       }
6144 +}
6145 +
6146 +static int __init init(void)
6147 +{
6148 +       int i, ret;
6149 +       char *tmpname;
6150 +
6151 +       /* If no port given, default to standard eggdrop port */
6152 +       if (ports[0] == 0)
6153 +               ports[0] = 3333;
6154 +
6155 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6156 +               memset(&egg_helpers[i], 0,
6157 +                      sizeof(struct ip_conntrack_helper));
6158 +               egg_helpers[i].tuple.src.u.tcp.port = htons(ports[i]);
6159 +               egg_helpers[i].tuple.dst.protonum = IPPROTO_TCP;
6160 +               egg_helpers[i].mask.src.u.tcp.port = 0xFFFF;
6161 +               egg_helpers[i].mask.dst.protonum = 0xFFFF;
6162 +               egg_helpers[i].max_expected = 1;
6163 +               egg_helpers[i].timeout = egg_timeout;
6164 +               egg_helpers[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6165 +               egg_helpers[i].me = THIS_MODULE;
6166 +               egg_helpers[i].help = help;
6167 +
6168 +               tmpname = &egg_names[i][0];
6169 +               if (ports[i] == 3333)
6170 +                       sprintf(tmpname, "eggdrop");
6171 +               else
6172 +                       sprintf(tmpname, "eggdrop-%d", ports[i]);
6173 +               egg_helpers[i].name = tmpname;
6174 +
6175 +               DEBUGP("port #%d: %d\n", i, ports[i]);
6176 +
6177 +               ret = ip_conntrack_helper_register(&egg_helpers[i]);
6178 +
6179 +               if (ret) {
6180 +                       printk("ip_conntrack_egg: ERROR registering helper "
6181 +                               "for port %d\n", ports[i]);
6182 +                       deregister_helpers();
6183 +                       return 1;
6184 +               }
6185 +               ports_c++;
6186 +       }
6187 +       return 0;
6188 +}
6189 +
6190 +static void __exit fini(void)
6191 +{
6192 +       deregister_helpers();
6193 +}
6194 +
6195 +module_init(init);
6196 +module_exit(fini);
6197 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_ftp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_ftp.c
6198 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_ftp.c      Thu Nov 28 23:53:15 2002
6199 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_ftp.c  Wed Sep 24 09:16:17 2003
6200 @@ -32,7 +32,7 @@
6201  
6202  static int try_rfc959(const char *, size_t, u_int32_t [], char);
6203  static int try_eprt(const char *, size_t, u_int32_t [], char);
6204 -static int try_espv_response(const char *, size_t, u_int32_t [], char);
6205 +static int try_epsv_response(const char *, size_t, u_int32_t [], char);
6206  
6207  static struct ftp_search {
6208         enum ip_conntrack_dir dir;
6209 @@ -65,7 +65,7 @@
6210                 IP_CT_DIR_REPLY,
6211                 "229 ", sizeof("229 ") - 1, '(', ')',
6212                 IP_CT_FTP_EPSV,
6213 -               try_espv_response,
6214 +               try_epsv_response,
6215         },
6216  };
6217  
6218 @@ -157,7 +157,7 @@
6219  }
6220  
6221  /* Returns 0, or length of numbers: |||6446| */
6222 -static int try_espv_response(const char *data, size_t dlen, u_int32_t array[6],
6223 +static int try_epsv_response(const char *data, size_t dlen, u_int32_t array[6],
6224                              char term)
6225  {
6226         char delim;
6227 @@ -200,9 +200,9 @@
6228  
6229                 DEBUGP("ftp: string mismatch\n");
6230                 for (i = 0; i < plen; i++) {
6231 -                       DEBUGFTP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
6232 -                                i, data[i], data[i],
6233 -                                pattern[i], pattern[i]);
6234 +                       DEBUGP("ftp:char %u `%c'(%u) vs `%c'(%u)\n",
6235 +                               i, data[i], data[i],
6236 +                               pattern[i], pattern[i]);
6237                 }
6238  #endif
6239                 return 0;
6240 @@ -366,11 +366,11 @@
6241                     { 0 } },
6242                   { htonl((array[0] << 24) | (array[1] << 16)
6243                           | (array[2] << 8) | array[3]),
6244 -                   { htons(array[4] << 8 | array[5]) },
6245 +                   { .tcp = { htons(array[4] << 8 | array[5]) } },
6246                     IPPROTO_TCP }});
6247         exp->mask = ((struct ip_conntrack_tuple)
6248                 { { 0xFFFFFFFF, { 0 } },
6249 -                 { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6250 +                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6251  
6252         exp->expectfn = NULL;
6253  
6254 @@ -405,7 +405,6 @@
6255                 ports[0] = FTP_PORT;
6256  
6257         for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6258 -               memset(&ftp[i], 0, sizeof(struct ip_conntrack_helper));
6259                 ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
6260                 ftp[i].tuple.dst.protonum = IPPROTO_TCP;
6261                 ftp[i].mask.src.u.tcp.port = 0xFFFF;
6262 @@ -436,9 +435,7 @@
6263         return 0;
6264  }
6265  
6266 -#ifdef CONFIG_IP_NF_NAT_NEEDED
6267  EXPORT_SYMBOL(ip_ftp_lock);
6268 -#endif
6269  
6270  MODULE_LICENSE("GPL");
6271  module_init(init);
6272 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_h323.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_h323.c
6273 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_h323.c     Thu Jan  1 00:00:00 1970
6274 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_h323.c Wed Sep 24 09:17:43 2003
6275 @@ -0,0 +1,308 @@
6276 +/* 
6277 + * H.323 'brute force' extension for H.323 connection tracking. 
6278 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
6279 + *
6280 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
6281 + * (http://www.coritel.it/projects/sofia/nat/)
6282 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
6283 + * the unregistered helpers to the conntrack entries.
6284 + */
6285 +
6286 +
6287 +#include <linux/module.h>
6288 +#include <linux/netfilter.h>
6289 +#include <linux/ip.h>
6290 +#include <net/checksum.h>
6291 +#include <net/tcp.h>
6292 +
6293 +#include <linux/netfilter_ipv4/lockhelp.h>
6294 +#include <linux/netfilter_ipv4/ip_conntrack.h>
6295 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
6296 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6297 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
6298 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
6299 +
6300 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6301 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6302 +MODULE_LICENSE("GPL");
6303 +
6304 +DECLARE_LOCK(ip_h323_lock);
6305 +struct module *ip_conntrack_h323 = THIS_MODULE;
6306 +
6307 +#if 0
6308 +#define DEBUGP printk
6309 +#else
6310 +#define DEBUGP(format, args...)
6311 +#endif
6312 +
6313 +/* FIXME: This should be in userspace.  Later. */
6314 +static int h245_help(const struct iphdr *iph, size_t len,
6315 +                    struct ip_conntrack *ct,
6316 +                    enum ip_conntrack_info ctinfo)
6317 +{
6318 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
6319 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
6320 +       unsigned char *data_limit;
6321 +       u_int32_t tcplen = len - iph->ihl * 4;
6322 +       u_int32_t datalen = tcplen - tcph->doff * 4;
6323 +       int dir = CTINFO2DIR(ctinfo);
6324 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6325 +       struct ip_conntrack_expect expect, *exp = &expect;
6326 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
6327 +       u_int16_t data_port;
6328 +       u_int32_t data_ip;
6329 +       unsigned int i;
6330 +
6331 +       DEBUGP("ct_h245_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6332 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
6333 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
6334 +
6335 +       /* Can't track connections formed before we registered */
6336 +       if (!info)
6337 +               return NF_ACCEPT;
6338 +               
6339 +       /* Until there's been traffic both ways, don't look in packets. */
6340 +       if (ctinfo != IP_CT_ESTABLISHED
6341 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6342 +               DEBUGP("ct_h245_help: Conntrackinfo = %u\n", ctinfo);
6343 +               return NF_ACCEPT;
6344 +       }
6345 +
6346 +       /* Not whole TCP header or too short packet? */
6347 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
6348 +               DEBUGP("ct_h245_help: tcplen = %u\n", (unsigned)tcplen);
6349 +               return NF_ACCEPT;
6350 +       }
6351 +
6352 +       /* Checksum invalid?  Ignore. */
6353 +       /* FIXME: Source route IP option packets --RR */
6354 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6355 +                             csum_partial((char *)tcph, tcplen, 0))) {
6356 +               DEBUGP("ct_h245_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6357 +                      tcph, tcplen, NIPQUAD(iph->saddr),
6358 +                      NIPQUAD(iph->daddr));
6359 +               return NF_ACCEPT;
6360 +       }
6361 +
6362 +       data_limit = (unsigned char *) data + datalen;
6363 +       /* bytes: 0123   45
6364 +                 ipadrr port */
6365 +       for (i = 0; data < (data_limit - 5); data++, i++) {
6366 +               data_ip = *((u_int32_t *)data);
6367 +               if (data_ip == iph->saddr) {
6368 +                       data_port = *((u_int16_t *)(data + 4));
6369 +                       memset(&expect, 0, sizeof(expect));
6370 +                       /* update the H.225 info */
6371 +                       DEBUGP("ct_h245_help: new RTCP/RTP requested %u.%u.%u.%u:->%u.%u.%u.%u:%u\n",
6372 +                               NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
6373 +                               NIPQUAD(iph->saddr), ntohs(data_port));
6374 +                       LOCK_BH(&ip_h323_lock);
6375 +                       info->is_h225 = H225_PORT + 1;
6376 +                       exp_info->port = data_port;
6377 +                       exp_info->dir = dir;
6378 +                       exp_info->offset = i;
6379 +
6380 +                       exp->seq = ntohl(tcph->seq) + i;
6381 +                   
6382 +                       exp->tuple = ((struct ip_conntrack_tuple)
6383 +                               { { ct->tuplehash[!dir].tuple.src.ip,
6384 +                                   { 0 } },
6385 +                                 { data_ip,
6386 +                                   { .tcp = { data_port } },
6387 +                                   IPPROTO_UDP }});
6388 +                       exp->mask = ((struct ip_conntrack_tuple)
6389 +                               { { 0xFFFFFFFF, { 0 } },
6390 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6391 +       
6392 +                       exp->expectfn = NULL;
6393 +                       
6394 +                       /* Ignore failure; should only happen with NAT */
6395 +                       ip_conntrack_expect_related(ct, exp);
6396 +
6397 +                       UNLOCK_BH(&ip_h323_lock);
6398 +               }
6399 +       }
6400 +
6401 +       return NF_ACCEPT;
6402 +
6403 +}
6404 +
6405 +/* H.245 helper is not registered! */
6406 +static struct ip_conntrack_helper h245 = 
6407 +       { { NULL, NULL },
6408 +          "H.245",                             /* name */
6409 +          IP_CT_HELPER_F_REUSE_EXPECT,         /* flags */
6410 +          NULL,                                        /* module */
6411 +          8,                                   /* max_ expected */
6412 +          240,                                 /* timeout */
6413 +          { { 0, { 0 } },                      /* tuple */
6414 +            { 0, { 0 }, IPPROTO_TCP } },
6415 +          { { 0, { 0xFFFF } },                 /* mask */
6416 +            { 0, { 0 }, 0xFFFF } },
6417 +          h245_help                            /* helper */
6418 +       };
6419 +
6420 +static int h225_expect(struct ip_conntrack *ct)
6421 +{
6422 +       WRITE_LOCK(&ip_conntrack_lock);
6423 +       ct->helper = &h245;
6424 +       DEBUGP("h225_expect: helper for %p added\n", ct);
6425 +       WRITE_UNLOCK(&ip_conntrack_lock);
6426 +       
6427 +       return NF_ACCEPT;       /* unused */
6428 +}
6429 +
6430 +/* FIXME: This should be in userspace.  Later. */
6431 +static int h225_help(const struct iphdr *iph, size_t len,
6432 +                    struct ip_conntrack *ct,
6433 +                    enum ip_conntrack_info ctinfo)
6434 +{
6435 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
6436 +       unsigned char *data = (unsigned char *) tcph + tcph->doff * 4;
6437 +       unsigned char *data_limit;
6438 +       u_int32_t tcplen = len - iph->ihl * 4;
6439 +       u_int32_t datalen = tcplen - tcph->doff * 4;
6440 +       int dir = CTINFO2DIR(ctinfo);
6441 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info;
6442 +       struct ip_conntrack_expect expect, *exp = &expect;
6443 +       struct ip_ct_h225_expect *exp_info = &exp->help.exp_h225_info;
6444 +       u_int16_t data_port;
6445 +       u_int32_t data_ip;
6446 +       unsigned int i;
6447 +       
6448 +       DEBUGP("ct_h225_help: help entered %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
6449 +               NIPQUAD(iph->saddr), ntohs(tcph->source),
6450 +               NIPQUAD(iph->daddr), ntohs(tcph->dest));
6451 +
6452 +       /* Can't track connections formed before we registered */
6453 +       if (!info)
6454 +               return NF_ACCEPT;
6455 +
6456 +       /* Until there's been traffic both ways, don't look in packets. */
6457 +       if (ctinfo != IP_CT_ESTABLISHED
6458 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
6459 +               DEBUGP("ct_h225_help: Conntrackinfo = %u\n", ctinfo);
6460 +               return NF_ACCEPT;
6461 +       }
6462 +
6463 +       /* Not whole TCP header or too short packet? */
6464 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4 + 5) {
6465 +               DEBUGP("ct_h225_help: tcplen = %u\n", (unsigned)tcplen);
6466 +               return NF_ACCEPT;
6467 +       }
6468 +
6469 +       /* Checksum invalid?  Ignore. */
6470 +       /* FIXME: Source route IP option packets --RR */
6471 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6472 +                             csum_partial((char *)tcph, tcplen, 0))) {
6473 +               DEBUGP("ct_h225_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6474 +                      tcph, tcplen, NIPQUAD(iph->saddr),
6475 +                      NIPQUAD(iph->daddr));
6476 +               return NF_ACCEPT;
6477 +       }
6478 +       
6479 +       data_limit = (unsigned char *) data + datalen;
6480 +       /* bytes: 0123   45
6481 +                 ipadrr port */
6482 +       for (i = 0; data < (data_limit - 5); data++, i++) {
6483 +               data_ip = *((u_int32_t *)data);
6484 +               if (data_ip == iph->saddr) {
6485 +                       data_port = *((u_int16_t *)(data + 4));
6486 +                       if (data_port == tcph->source) {
6487 +                               /* Signal address */
6488 +                               DEBUGP("ct_h225_help: sourceCallSignalAddress from %u.%u.%u.%u\n",
6489 +                                       NIPQUAD(iph->saddr));
6490 +                               /* Update the H.225 info so that NAT can mangle the address/port
6491 +                                  even when we have no expected connection! */
6492 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6493 +                               LOCK_BH(&ip_h323_lock);
6494 +                               info->dir = dir;
6495 +                               info->seq[IP_CT_DIR_ORIGINAL] = ntohl(tcph->seq) + i;
6496 +                               info->offset[IP_CT_DIR_ORIGINAL] = i;
6497 +                               UNLOCK_BH(&ip_h323_lock);
6498 +#endif
6499 +                       } else {
6500 +                               memset(&expect, 0, sizeof(expect));
6501 +
6502 +                               /* update the H.225 info */
6503 +                               LOCK_BH(&ip_h323_lock);
6504 +                               info->is_h225 = H225_PORT;
6505 +                               exp_info->port = data_port;
6506 +                               exp_info->dir = dir;
6507 +                               exp_info->offset = i;
6508 +
6509 +                               exp->seq = ntohl(tcph->seq) + i;
6510 +
6511 +                               exp->tuple = ((struct ip_conntrack_tuple)
6512 +                                       { { ct->tuplehash[!dir].tuple.src.ip,
6513 +                                           { 0 } },
6514 +                                         { data_ip,
6515 +                                           { .tcp = { data_port } },
6516 +                                           IPPROTO_TCP }});
6517 +                               exp->mask = ((struct ip_conntrack_tuple)
6518 +                                       { { 0xFFFFFFFF, { 0 } },
6519 +                                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6520 +       
6521 +                               exp->expectfn = h225_expect;
6522 +                               
6523 +                               /* Ignore failure */
6524 +                               ip_conntrack_expect_related(ct, exp);
6525 +
6526 +                               DEBUGP("ct_h225_help: new H.245 requested %u.%u.%u.%u->%u.%u.%u.%u:%u\n",
6527 +                                       NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
6528 +                                       NIPQUAD(iph->saddr), ntohs(data_port));
6529 +
6530 +                               UNLOCK_BH(&ip_h323_lock);
6531 +                       }  
6532 +#ifdef CONFIG_IP_NF_NAT_NEEDED
6533 +               } else if (data_ip == iph->daddr) {
6534 +                       data_port = *((u_int16_t *)(data + 4));
6535 +                       if (data_port == tcph->dest) {
6536 +                               /* Signal address */
6537 +                               DEBUGP("ct_h225_help: destCallSignalAddress %u.%u.%u.%u\n",
6538 +                                       NIPQUAD(iph->daddr));
6539 +                               /* Update the H.225 info so that NAT can mangle the address/port
6540 +                                  even when we have no expected connection! */
6541 +                               LOCK_BH(&ip_h323_lock);
6542 +                               info->dir = dir;
6543 +                               info->seq[IP_CT_DIR_REPLY] = ntohl(tcph->seq) + i;
6544 +                               info->offset[IP_CT_DIR_REPLY] = i;
6545 +                               UNLOCK_BH(&ip_h323_lock);
6546 +                       }
6547 +#endif
6548 +               }
6549 +       }
6550 +
6551 +       return NF_ACCEPT;
6552 +
6553 +}
6554 +
6555 +static struct ip_conntrack_helper h225 = 
6556 +       { { NULL, NULL },
6557 +         "H.225",                                      /* name */
6558 +         IP_CT_HELPER_F_REUSE_EXPECT,                  /* flags */
6559 +         THIS_MODULE,                                  /* module */
6560 +         2,                                            /* max_expected */
6561 +         240,                                          /* timeout */
6562 +         { { 0, { __constant_htons(H225_PORT) } },     /* tuple */
6563 +           { 0, { 0 }, IPPROTO_TCP } },
6564 +         { { 0, { 0xFFFF } },                          /* mask */
6565 +           { 0, { 0 }, 0xFFFF } },
6566 +         h225_help                                     /* helper */
6567 +       };
6568 +
6569 +static int __init init(void)
6570 +{
6571 +       return ip_conntrack_helper_register(&h225);
6572 +}
6573 +
6574 +static void __exit fini(void)
6575 +{
6576 +       /* Unregister H.225 helper */   
6577 +       ip_conntrack_helper_unregister(&h225);
6578 +}
6579 +
6580 +EXPORT_SYMBOL(ip_h323_lock);
6581 +
6582 +module_init(init);
6583 +module_exit(fini);
6584 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_irc.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_irc.c
6585 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_irc.c      Thu Nov 28 23:53:15 2002
6586 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_irc.c  Wed Sep 24 09:16:26 2003
6587 @@ -59,7 +59,7 @@
6588         {"TSEND ", 6},
6589         {"SCHAT ", 6}
6590  };
6591 -#define MAXMATCHLEN    6
6592 +#define MINMATCHLEN    5
6593  
6594  DECLARE_LOCK(ip_irc_lock);
6595  struct module *ip_conntrack_irc = THIS_MODULE;
6596 @@ -92,9 +92,11 @@
6597         *ip = simple_strtoul(data, &data, 10);
6598  
6599         /* skip blanks between ip and port */
6600 -       while (*data == ' ')
6601 +       while (*data == ' ') {
6602 +               if (data >= data_end) 
6603 +                       return -1;
6604                 data++;
6605 -
6606 +       }
6607  
6608         *port = simple_strtoul(data, &data, 10);
6609         *ad_end_p = data;
6610 @@ -153,13 +155,17 @@
6611         }
6612  
6613         data_limit = (char *) data + datalen;
6614 -       while (data < (data_limit - (22 + MAXMATCHLEN))) {
6615 +
6616 +       /* strlen("\1DCC SEND t AAAAAAAA P\1\n")=24
6617 +        *         5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */
6618 +       while (data < (data_limit - (19 + MINMATCHLEN))) {
6619                 if (memcmp(data, "\1DCC ", 5)) {
6620                         data++;
6621                         continue;
6622                 }
6623  
6624                 data += 5;
6625 +               /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
6626  
6627                 DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
6628                         NIPQUAD(iph->saddr), ntohs(tcph->source),
6629 @@ -174,6 +180,9 @@
6630  
6631                         DEBUGP("DCC %s detected\n", dccprotos[i].match);
6632                         data += dccprotos[i].matchlen;
6633 +                       /* we have at least
6634 +                        * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid
6635 +                        * data left (== 14/13 bytes) */
6636                         if (parse_dcc((char *) data, data_limit, &dcc_ip,
6637                                        &dcc_port, &addr_beg_p, &addr_end_p)) {
6638                                 /* unable to parse */
6639 @@ -183,7 +192,10 @@
6640                         DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n",
6641                                 HIPQUAD(dcc_ip), dcc_port);
6642  
6643 -                       if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)) {
6644 +                       /* dcc_ip can be the internal OR external (NAT'ed) IP
6645 +                        * Tiago Sousa <mirage@kaotik.org> */
6646 +                       if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)
6647 +                           && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != htonl(dcc_ip)) {
6648                                 if (net_ratelimit())
6649                                         printk(KERN_WARNING
6650                                                 "Forged DCC command from "
6651 @@ -209,11 +221,11 @@
6652  
6653                         exp->tuple = ((struct ip_conntrack_tuple)
6654                                 { { 0, { 0 } },
6655 -                                 { htonl(dcc_ip), { htons(dcc_port) },
6656 +                                 { ct->tuplehash[dir].tuple.src.ip, { .tcp = { htons(dcc_port) } },
6657                                     IPPROTO_TCP }});
6658                         exp->mask = ((struct ip_conntrack_tuple)
6659                                 { { 0, { 0 } },
6660 -                                 { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6661 +                                 { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6662  
6663                         exp->expectfn = NULL;
6664  
6665 @@ -259,8 +271,6 @@
6666  
6667         for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6668                 hlpr = &irc_helpers[i];
6669 -               memset(hlpr, 0,
6670 -                      sizeof(struct ip_conntrack_helper));
6671                 hlpr->tuple.src.u.tcp.port = htons(ports[i]);
6672                 hlpr->tuple.dst.protonum = IPPROTO_TCP;
6673                 hlpr->mask.src.u.tcp.port = 0xFFFF;
6674 @@ -305,9 +315,7 @@
6675         }
6676  }
6677  
6678 -#ifdef CONFIG_IP_NF_NAT_NEEDED
6679  EXPORT_SYMBOL(ip_irc_lock);
6680 -#endif
6681  
6682  module_init(init);
6683  module_exit(fini);
6684 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_mms.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_mms.c
6685 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_mms.c      Thu Jan  1 00:00:00 1970
6686 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_mms.c  Wed Sep 24 09:17:48 2003
6687 @@ -0,0 +1,308 @@
6688 +/* MMS extension for IP connection tracking
6689 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
6690 + * based on ip_conntrack_ftp.c and ip_conntrack_irc.c
6691 + *
6692 + * ip_conntrack_mms.c v0.3 2002-09-22
6693 + *
6694 + *      This program is free software; you can redistribute it and/or
6695 + *      modify it under the terms of the GNU General Public License
6696 + *      as published by the Free Software Foundation; either version
6697 + *      2 of the License, or (at your option) any later version.
6698 + *
6699 + *      Module load syntax:
6700 + *      insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
6701 + *
6702 + *      Please give the ports of all MMS servers You wish to connect to.
6703 + *      If you don't specify ports, the default will be TCP port 1755.
6704 + *
6705 + *      More info on MMS protocol, firewalls and NAT:
6706 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
6707 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
6708 + *
6709 + *      The SDP project people are reverse-engineering MMS:
6710 + *      http://get.to/sdp
6711 + */
6712 +
6713 +#include <linux/config.h>
6714 +#include <linux/module.h>
6715 +#include <linux/netfilter.h>
6716 +#include <linux/ip.h>
6717 +#include <linux/ctype.h>
6718 +#include <net/checksum.h>
6719 +#include <net/tcp.h>
6720 +
6721 +#include <linux/netfilter_ipv4/lockhelp.h>
6722 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
6723 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
6724 +
6725 +DECLARE_LOCK(ip_mms_lock);
6726 +struct module *ip_conntrack_mms = THIS_MODULE;
6727 +
6728 +#define MAX_PORTS 8
6729 +static int ports[MAX_PORTS];
6730 +static int ports_c;
6731 +#ifdef MODULE_PARM
6732 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6733 +#endif
6734 +
6735 +#if 0 
6736 +#define DEBUGP printk
6737 +#else
6738 +#define DEBUGP(format, args...)
6739 +#endif
6740 +
6741 +EXPORT_SYMBOL(ip_mms_lock);
6742 +
6743 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6744 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
6745 +MODULE_LICENSE("GPL");
6746 +
6747 +/* #define isdigit(c) (c >= '0' && c <= '9') */
6748 +
6749 +/* copied from drivers/usb/serial/io_edgeport.c - not perfect but will do the trick */
6750 +static void unicode_to_ascii (char *string, short *unicode, int unicode_size)
6751 +{
6752 +       int i;
6753 +       for (i = 0; i < unicode_size; ++i) {
6754 +               string[i] = (char)(unicode[i]);
6755 +       }
6756 +       string[unicode_size] = 0x00;
6757 +}
6758 +
6759 +__inline static int atoi(char *s) 
6760 +{
6761 +       int i=0;
6762 +       while (isdigit(*s)) {
6763 +               i = i*10 + *(s++) - '0';
6764 +       }
6765 +       return i;
6766 +}
6767 +
6768 +/* convert ip address string like "192.168.0.10" to unsigned int */
6769 +__inline static u_int32_t asciiiptoi(char *s)
6770 +{
6771 +       unsigned int i, j, k;
6772 +
6773 +       for(i=k=0; k<3; ++k, ++s, i<<=8) {
6774 +               i+=atoi(s);
6775 +               for(j=0; (*(++s) != '.') && (j<3); ++j)
6776 +                       ;
6777 +       }
6778 +       i+=atoi(s);
6779 +       return ntohl(i);
6780 +}
6781 +
6782 +int parse_mms(const char *data, 
6783 +             const unsigned int datalen,
6784 +             u_int32_t *mms_ip,
6785 +             u_int16_t *mms_proto,
6786 +             u_int16_t *mms_port,
6787 +             char **mms_string_b,
6788 +             char **mms_string_e,
6789 +             char **mms_padding_e)
6790 +{
6791 +       int unicode_size, i;
6792 +       char tempstring[28];       /* "\\255.255.255.255\UDP\65535" */
6793 +       char getlengthstring[28];
6794 +       
6795 +       for(unicode_size=0; 
6796 +           (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
6797 +           unicode_size++)
6798 +               if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen)) 
6799 +                       return -1; /* out of bounds - incomplete packet */
6800 +       
6801 +       unicode_to_ascii(tempstring, (short *)(data+MMS_SRV_UNICODE_STRING_OFFSET), unicode_size);
6802 +       DEBUGP("ip_conntrack_mms: offset 60: %s\n", (const char *)(tempstring));
6803 +       
6804 +       /* IP address ? */
6805 +       *mms_ip = asciiiptoi(tempstring+2);
6806 +       
6807 +       i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
6808 +               
6809 +       /* protocol ? */
6810 +       if(strncmp(tempstring+3+i, "TCP", 3)==0)
6811 +               *mms_proto = IPPROTO_TCP;
6812 +       else if(strncmp(tempstring+3+i, "UDP", 3)==0)
6813 +               *mms_proto = IPPROTO_UDP;
6814 +
6815 +       /* port ? */
6816 +       *mms_port = atoi(tempstring+7+i);
6817 +
6818 +       /* we store a pointer to the beginning of the "\\a.b.c.d\proto\port" 
6819 +          unicode string, one to the end of the string, and one to the end 
6820 +          of the packet, since we must keep track of the number of bytes 
6821 +          between end of the unicode string and the end of packet (padding) */
6822 +       *mms_string_b  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET);
6823 +       *mms_string_e  = (char *)(data + MMS_SRV_UNICODE_STRING_OFFSET + unicode_size * 2);
6824 +       *mms_padding_e = (char *)(data + datalen); /* looks funny, doesn't it */
6825 +       return 0;
6826 +}
6827 +
6828 +
6829 +/* FIXME: This should be in userspace.  Later. */
6830 +static int help(const struct iphdr *iph, size_t len,
6831 +               struct ip_conntrack *ct,
6832 +               enum ip_conntrack_info ctinfo)
6833 +{
6834 +       /* tcplen not negative guaranteed by ip_conntrack_tcp.c */
6835 +       struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
6836 +       const char *data = (const char *)tcph + tcph->doff * 4;
6837 +       unsigned int tcplen = len - iph->ihl * 4;
6838 +       unsigned int datalen = tcplen - tcph->doff * 4;
6839 +       int dir = CTINFO2DIR(ctinfo);
6840 +       struct ip_conntrack_expect expect, *exp = &expect; 
6841 +       struct ip_ct_mms_expect *exp_mms_info = &exp->help.exp_mms_info;
6842 +       
6843 +       u_int32_t mms_ip;
6844 +       u_int16_t mms_proto;
6845 +       char mms_proto_string[8];
6846 +       u_int16_t mms_port;
6847 +       char *mms_string_b, *mms_string_e, *mms_padding_e;
6848 +            
6849 +       /* Until there's been traffic both ways, don't look in packets. */
6850 +       if (ctinfo != IP_CT_ESTABLISHED
6851 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
6852 +               DEBUGP("ip_conntrack_mms: Conntrackinfo = %u\n", ctinfo);
6853 +               return NF_ACCEPT;
6854 +       }
6855 +
6856 +       /* Not whole TCP header? */
6857 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff*4) {
6858 +               DEBUGP("ip_conntrack_mms: tcplen = %u\n", (unsigned)tcplen);
6859 +               return NF_ACCEPT;
6860 +       }
6861 +
6862 +       /* Checksum invalid?  Ignore. */
6863 +       /* FIXME: Source route IP option packets --RR */
6864 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
6865 +           csum_partial((char *)tcph, tcplen, 0))) {
6866 +               DEBUGP("mms_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
6867 +                      tcph, tcplen, NIPQUAD(iph->saddr),
6868 +                      NIPQUAD(iph->daddr));
6869 +               return NF_ACCEPT;
6870 +       }
6871 +       
6872 +       /* Only look at packets with 0x00030002/196610 on bytes 36->39 of TCP payload */
6873 +       /* FIXME: There is an issue with only looking at this packet: before this packet, 
6874 +          the client has already sent a packet to the server with the server's hostname 
6875 +          according to the client (think of it as the "Host: " header in HTTP/1.1). The 
6876 +          server will break the connection if this doesn't correspond to its own host 
6877 +          header. The client can also connect to an IP address; if it's the server's IP
6878 +          address, it will not break the connection. When doing DNAT on a connection 
6879 +          where the client uses a server's IP address, the nat module should detect
6880 +          this and change this string accordingly to the DNATed address. This should
6881 +          probably be done by checking for an IP address, then storing it as a member
6882 +          of struct ip_ct_mms_expect and checking for it in ip_nat_mms...
6883 +          */
6884 +       if( (MMS_SRV_MSG_OFFSET < datalen) && 
6885 +           ((*(u32 *)(data+MMS_SRV_MSG_OFFSET)) == MMS_SRV_MSG_ID)) {
6886 +               DEBUGP("ip_conntrack_mms: offset 37: %u %u %u %u, datalen:%u\n", 
6887 +                      (u8)*(data+36), (u8)*(data+37), 
6888 +                      (u8)*(data+38), (u8)*(data+39),
6889 +                      datalen);
6890 +               if(parse_mms(data, datalen, &mms_ip, &mms_proto, &mms_port,
6891 +                            &mms_string_b, &mms_string_e, &mms_padding_e))
6892 +                       if(net_ratelimit())
6893 +                               /* FIXME: more verbose debugging ? */
6894 +                               printk(KERN_WARNING
6895 +                                      "ip_conntrack_mms: Unable to parse data payload\n");
6896 +
6897 +               memset(&expect, 0, sizeof(expect));
6898 +
6899 +               sprintf(mms_proto_string, "(%u)", mms_proto);
6900 +               DEBUGP("ip_conntrack_mms: adding %s expectation %u.%u.%u.%u -> %u.%u.%u.%u:%u\n",
6901 +                      mms_proto == IPPROTO_TCP ? "TCP"
6902 +                      : mms_proto == IPPROTO_UDP ? "UDP":mms_proto_string,
6903 +                      NIPQUAD(ct->tuplehash[!dir].tuple.src.ip),
6904 +                      NIPQUAD(mms_ip),
6905 +                      mms_port);
6906 +               
6907 +               /* it's possible that the client will just ask the server to tunnel
6908 +                  the stream over the same TCP session (from port 1755): there's 
6909 +                  shouldn't be a need to add an expectation in that case, but it
6910 +                  makes NAT packet mangling so much easier */
6911 +               LOCK_BH(&ip_mms_lock);
6912 +
6913 +               DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
6914 +               
6915 +               exp->seq = ntohl(tcph->seq) + (mms_string_b - data);
6916 +               exp_mms_info->len     = (mms_string_e  - mms_string_b);
6917 +               exp_mms_info->padding = (mms_padding_e - mms_string_e);
6918 +               exp_mms_info->port    = mms_port;
6919 +               
6920 +               DEBUGP("ip_conntrack_mms: wrote info seq=%u (ofs=%u), len=%d, padding=%u\n",
6921 +                      exp->seq, (mms_string_e - data), exp_mms_info->len, exp_mms_info->padding);
6922 +               
6923 +               exp->tuple = ((struct ip_conntrack_tuple)
6924 +                             { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
6925 +                             { mms_ip,
6926 +                               { .tcp = { (__u16) ntohs(mms_port) } },
6927 +                               mms_proto } }
6928 +                            );
6929 +               exp->mask  = ((struct ip_conntrack_tuple)
6930 +                            { { 0xFFFFFFFF, { 0 } },
6931 +                              { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6932 +               exp->expectfn = NULL;
6933 +               ip_conntrack_expect_related(ct, &expect);
6934 +               UNLOCK_BH(&ip_mms_lock);
6935 +       }
6936 +
6937 +       return NF_ACCEPT;
6938 +}
6939 +
6940 +static struct ip_conntrack_helper mms[MAX_PORTS];
6941 +static char mms_names[MAX_PORTS][10];
6942 +
6943 +/* Not __exit: called from init() */
6944 +static void fini(void)
6945 +{
6946 +       int i;
6947 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6948 +               DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
6949 +                               ports[i]);
6950 +               ip_conntrack_helper_unregister(&mms[i]);
6951 +       }
6952 +}
6953 +
6954 +static int __init init(void)
6955 +{
6956 +       int i, ret;
6957 +       char *tmpname;
6958 +
6959 +       if (ports[0] == 0)
6960 +               ports[0] = MMS_PORT;
6961 +
6962 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6963 +               memset(&mms[i], 0, sizeof(struct ip_conntrack_helper));
6964 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
6965 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
6966 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
6967 +               mms[i].mask.dst.protonum = 0xFFFF;
6968 +               mms[i].max_expected = 1;
6969 +               mms[i].timeout = 0;
6970 +               mms[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
6971 +               mms[i].me = THIS_MODULE;
6972 +               mms[i].help = help;
6973 +
6974 +               tmpname = &mms_names[i][0];
6975 +               if (ports[i] == MMS_PORT)
6976 +                       sprintf(tmpname, "mms");
6977 +               else
6978 +                       sprintf(tmpname, "mms-%d", ports[i]);
6979 +               mms[i].name = tmpname;
6980 +
6981 +               DEBUGP("ip_conntrack_mms: registering helper for port %d\n", 
6982 +                               ports[i]);
6983 +               ret = ip_conntrack_helper_register(&mms[i]);
6984 +
6985 +               if (ret) {
6986 +                       fini();
6987 +                       return ret;
6988 +               }
6989 +               ports_c++;
6990 +       }
6991 +       return 0;
6992 +}
6993 +
6994 +module_init(init);
6995 +module_exit(fini);
6996 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_pptp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_pptp.c
6997 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_pptp.c     Thu Jan  1 00:00:00 1970
6998 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_pptp.c Wed Sep 24 09:18:16 2003
6999 @@ -0,0 +1,639 @@
7000 +/*
7001 + * ip_conntrack_pptp.c - Version 1.9
7002 + *
7003 + * Connection tracking support for PPTP (Point to Point Tunneling Protocol).
7004 + * PPTP is a a protocol for creating virtual private networks.
7005 + * It is a specification defined by Microsoft and some vendors
7006 + * working with Microsoft.  PPTP is built on top of a modified
7007 + * version of the Internet Generic Routing Encapsulation Protocol.
7008 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
7009 + * PPTP can be found in RFC 2637
7010 + *
7011 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
7012 + *
7013 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
7014 + *
7015 + * Limitations:
7016 + *      - We blindly assume that control connections are always
7017 + *        established in PNS->PAC direction.  This is a violation
7018 + *        of RFFC2673
7019 + *
7020 + * TODO: - finish support for multiple calls within one session
7021 + *        (needs expect reservations in newnat)
7022 + *      - testing of incoming PPTP calls 
7023 + *
7024 + * Changes: 
7025 + *     2002-02-05 - Version 1.3
7026 + *       - Call ip_conntrack_unexpect_related() from 
7027 + *         pptp_timeout_related() to destroy expectations in case
7028 + *         CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
7029 + *         (Philip Craig <philipc@snapgear.com>)
7030 + *       - Add Version information at module loadtime
7031 + *     2002-02-10 - Version 1.6
7032 + *       - move to C99 style initializers
7033 + *       - remove second expectation if first arrives
7034 + *
7035 + */
7036 +
7037 +#include <linux/config.h>
7038 +#include <linux/module.h>
7039 +#include <linux/netfilter.h>
7040 +#include <linux/ip.h>
7041 +#include <net/checksum.h>
7042 +#include <net/tcp.h>
7043 +
7044 +#include <linux/netfilter_ipv4/lockhelp.h>
7045 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7046 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
7047 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
7048 +
7049 +#define IP_CT_PPTP_VERSION "1.9"
7050 +
7051 +MODULE_LICENSE("GPL");
7052 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
7053 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
7054 +
7055 +DECLARE_LOCK(ip_pptp_lock);
7056 +
7057 +#if 0
7058 +#include "ip_conntrack_pptp_priv.h"
7059 +#define DEBUGP(format, args...)        printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
7060 +                                       ": " format, ## args)
7061 +#else
7062 +#define DEBUGP(format, args...)
7063 +#endif
7064 +
7065 +#define SECS *HZ
7066 +#define MINS * 60 SECS
7067 +#define HOURS * 60 MINS
7068 +#define DAYS * 24 HOURS
7069 +
7070 +#define PPTP_GRE_TIMEOUT               (10 MINS)
7071 +#define PPTP_GRE_STREAM_TIMEOUT        (5 DAYS)
7072 +
7073 +static int pptp_expectfn(struct ip_conntrack *ct)
7074 +{
7075 +       struct ip_conntrack *master;
7076 +       struct ip_conntrack_expect *exp;
7077 +
7078 +       DEBUGP("increasing timeouts\n");
7079 +       /* increase timeout of GRE data channel conntrack entry */
7080 +       ct->proto.gre.timeout = PPTP_GRE_TIMEOUT;
7081 +       ct->proto.gre.stream_timeout = PPTP_GRE_STREAM_TIMEOUT;
7082 +
7083 +       master = master_ct(ct);
7084 +       if (!master) {
7085 +               DEBUGP(" no master!!!\n");
7086 +               return 0;
7087 +       }
7088 +
7089 +       exp = ct->master;
7090 +       if (!exp) {
7091 +               DEBUGP("no expectation!!\n");
7092 +               return 0;
7093 +       }
7094 +
7095 +       DEBUGP("completing tuples with ct info\n");
7096 +       /* we can do this, since we're unconfirmed */
7097 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key == 
7098 +               htonl(master->help.ct_pptp_info.pac_call_id)) { 
7099 +               /* assume PNS->PAC */
7100 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key = 
7101 +                       htonl(master->help.ct_pptp_info.pns_call_id);
7102 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
7103 +                       htonl(master->help.ct_pptp_info.pns_call_id);
7104 +       } else {
7105 +               /* assume PAC->PNS */
7106 +               ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
7107 +                       htonl(master->help.ct_pptp_info.pac_call_id);
7108 +               ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
7109 +                       htonl(master->help.ct_pptp_info.pac_call_id);
7110 +       }
7111 +       
7112 +       /* delete other expectation */
7113 +       if (exp->expected_list.next != &exp->expected_list) {
7114 +               struct ip_conntrack_expect *other_exp;
7115 +               struct list_head *cur_item, *next;
7116 +
7117 +               for (cur_item = master->sibling_list.next;
7118 +                    cur_item != &master->sibling_list; cur_item = next) {
7119 +                       next = cur_item->next;
7120 +                       other_exp = list_entry(cur_item,
7121 +                                              struct ip_conntrack_expect,
7122 +                                              expected_list);
7123 +                       /* remove only if occurred at same sequence number */
7124 +                       if (other_exp != exp && other_exp->seq == exp->seq) {
7125 +                               DEBUGP("unexpecting other direction\n");
7126 +                               ip_ct_gre_keymap_destroy(other_exp);
7127 +                               ip_conntrack_unexpect_related(other_exp);
7128 +                       }
7129 +               }
7130 +       }
7131 +
7132 +       return 0;
7133 +}
7134 +
7135 +/* timeout GRE data connections */
7136 +static int pptp_timeout_related(struct ip_conntrack *ct)
7137 +{
7138 +       struct list_head *cur_item, *next;
7139 +       struct ip_conntrack_expect *exp;
7140 +
7141 +       /* FIXME: do we have to lock something ? */
7142 +       for (cur_item = ct->sibling_list.next;
7143 +           cur_item != &ct->sibling_list; cur_item = next) {
7144 +               next = cur_item->next;
7145 +               exp = list_entry(cur_item, struct ip_conntrack_expect,
7146 +                                expected_list);
7147 +
7148 +               ip_ct_gre_keymap_destroy(exp);
7149 +               if (!exp->sibling) {
7150 +                       ip_conntrack_unexpect_related(exp);
7151 +                       continue;
7152 +               }
7153 +
7154 +               DEBUGP("killing conntrack %p\n",
7155 +                       exp->sibling);
7156 +               exp->sibling->proto.gre.timeout = 0;
7157 +               exp->sibling->proto.gre.stream_timeout = 0;
7158 +
7159 +               if (del_timer(&exp->sibling->timeout))
7160 +                       ip_ct_death_by_timeout((unsigned long)exp->sibling);
7161 +       }
7162 +
7163 +       return 0;
7164 +}
7165 +
7166 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
7167 +static inline int
7168 +exp_gre(struct ip_conntrack *master,
7169 +       u_int32_t seq,
7170 +       u_int16_t callid,
7171 +       u_int16_t peer_callid)
7172 +{
7173 +       struct ip_conntrack_expect exp;
7174 +       struct ip_conntrack_tuple inv_tuple;
7175 +
7176 +       memset(&exp, 0, sizeof(exp));
7177 +       /* tuple in original direction, PNS->PAC */
7178 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
7179 +       exp.tuple.src.u.gre.key = htonl(ntohs(peer_callid));
7180 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
7181 +       exp.tuple.dst.u.gre.key = htonl(ntohs(callid));
7182 +       exp.tuple.dst.u.gre.protocol = __constant_htons(GRE_PROTOCOL_PPTP);
7183 +       exp.tuple.dst.u.gre.version = GRE_VERSION_PPTP;
7184 +       exp.tuple.dst.protonum = IPPROTO_GRE;
7185 +
7186 +       exp.mask.src.ip = 0xffffffff;
7187 +       exp.mask.src.u.all = 0;
7188 +       exp.mask.dst.u.all = 0;
7189 +       exp.mask.dst.u.gre.key = 0xffffffff;
7190 +       exp.mask.dst.u.gre.version = 0xff;
7191 +       exp.mask.dst.u.gre.protocol = 0xffff;
7192 +       exp.mask.dst.ip = 0xffffffff;
7193 +       exp.mask.dst.protonum = 0xffff;
7194 +                       
7195 +       exp.seq = seq;
7196 +       exp.expectfn = pptp_expectfn;
7197 +
7198 +       exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
7199 +       exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
7200 +
7201 +       DEBUGP("calling expect_related ");
7202 +       DUMP_TUPLE_RAW(&exp.tuple);
7203 +       
7204 +       /* Add GRE keymap entries */
7205 +       if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
7206 +               return 1;
7207 +
7208 +       invert_tuplepr(&inv_tuple, &exp.tuple);
7209 +       if (ip_ct_gre_keymap_add(&exp, &inv_tuple, 1) != 0) {
7210 +               ip_ct_gre_keymap_destroy(&exp);
7211 +               return 1;
7212 +       }
7213 +       
7214 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
7215 +               ip_ct_gre_keymap_destroy(&exp);
7216 +               DEBUGP("cannot expect_related()\n");
7217 +               return 1;
7218 +       }
7219 +
7220 +       /* tuple in reply direction, PAC->PNS */
7221 +       exp.tuple.src.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
7222 +       exp.tuple.src.u.gre.key = htonl(ntohs(callid));
7223 +       exp.tuple.dst.ip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
7224 +       exp.tuple.dst.u.gre.key = htonl(ntohs(peer_callid));
7225 +
7226 +       DEBUGP("calling expect_related ");
7227 +       DUMP_TUPLE_RAW(&exp.tuple);
7228 +       
7229 +       /* Add GRE keymap entries */
7230 +       ip_ct_gre_keymap_add(&exp, &exp.tuple, 0);
7231 +       invert_tuplepr(&inv_tuple, &exp.tuple);
7232 +       ip_ct_gre_keymap_add(&exp, &inv_tuple, 1);
7233 +       /* FIXME: cannot handle error correctly, since we need to free
7234 +        * the above keymap :( */
7235 +       
7236 +       if (ip_conntrack_expect_related(master, &exp) != 0) {
7237 +               /* free the second pair of keypmaps */
7238 +               ip_ct_gre_keymap_destroy(&exp);
7239 +               DEBUGP("cannot expect_related():\n");
7240 +               return 1;
7241 +       }
7242 +
7243 +       return 0;
7244 +}
7245 +
7246 +static inline int 
7247 +pptp_inbound_pkt(struct tcphdr *tcph,
7248 +                struct pptp_pkt_hdr *pptph, 
7249 +                size_t datalen,
7250 +                struct ip_conntrack *ct,
7251 +                enum ip_conntrack_info ctinfo)
7252 +{
7253 +       struct PptpControlHeader *ctlh;
7254 +        union pptp_ctrl_union pptpReq;
7255 +       
7256 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
7257 +       u_int16_t msg, *cid, *pcid;
7258 +       u_int32_t seq;  
7259 +
7260 +       ctlh = (struct PptpControlHeader *) 
7261 +               ((char *) pptph + sizeof(struct pptp_pkt_hdr));
7262 +       pptpReq.rawreq = (void *) 
7263 +               ((char *) ctlh + sizeof(struct PptpControlHeader));
7264 +
7265 +       msg = ntohs(ctlh->messageType);
7266 +       DEBUGP("inbound control message %s\n", strMName[msg]);
7267 +
7268 +       switch (msg) {
7269 +       case PPTP_START_SESSION_REPLY:
7270 +               /* server confirms new control session */
7271 +               if (info->sstate < PPTP_SESSION_REQUESTED) {
7272 +                       DEBUGP("%s without START_SESS_REQUEST\n",
7273 +                               strMName[msg]);
7274 +                       break;
7275 +               }
7276 +               if (pptpReq.srep->resultCode == PPTP_START_OK)
7277 +                       info->sstate = PPTP_SESSION_CONFIRMED;
7278 +               else 
7279 +                       info->sstate = PPTP_SESSION_ERROR;
7280 +               break;
7281 +
7282 +       case PPTP_STOP_SESSION_REPLY:
7283 +               /* server confirms end of control session */
7284 +               if (info->sstate > PPTP_SESSION_STOPREQ) {
7285 +                       DEBUGP("%s without STOP_SESS_REQUEST\n",
7286 +                               strMName[msg]);
7287 +                       break;
7288 +               }
7289 +               if (pptpReq.strep->resultCode == PPTP_STOP_OK)
7290 +                       info->sstate = PPTP_SESSION_NONE;
7291 +               else
7292 +                       info->sstate = PPTP_SESSION_ERROR;
7293 +               break;
7294 +
7295 +       case PPTP_OUT_CALL_REPLY:
7296 +               /* server accepted call, we now expect GRE frames */
7297 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
7298 +                       DEBUGP("%s but no session\n", strMName[msg]);
7299 +                       break;
7300 +               }
7301 +               if (info->cstate != PPTP_CALL_OUT_REQ &&
7302 +                   info->cstate != PPTP_CALL_OUT_CONF) {
7303 +                       DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
7304 +                       break;
7305 +               }
7306 +               if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
7307 +                       info->cstate = PPTP_CALL_NONE;
7308 +                       break;
7309 +               }
7310 +
7311 +               cid = &pptpReq.ocack->callID;
7312 +               pcid = &pptpReq.ocack->peersCallID;
7313 +
7314 +               info->pac_call_id = ntohs(*cid);
7315 +               
7316 +               if (htons(info->pns_call_id) != *pcid) {
7317 +                       DEBUGP("%s for unknown callid %u\n",
7318 +                               strMName[msg], ntohs(*pcid));
7319 +                       break;
7320 +               }
7321 +
7322 +               DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg], 
7323 +                       ntohs(*cid), ntohs(*pcid));
7324 +               
7325 +               info->cstate = PPTP_CALL_OUT_CONF;
7326 +
7327 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
7328 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
7329 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
7330 +               break;
7331 +
7332 +       case PPTP_IN_CALL_REQUEST:
7333 +               /* server tells us about incoming call request */
7334 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
7335 +                       DEBUGP("%s but no session\n", strMName[msg]);
7336 +                       break;
7337 +               }
7338 +               pcid = &pptpReq.icack->peersCallID;
7339 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
7340 +               info->cstate = PPTP_CALL_IN_REQ;
7341 +               info->pac_call_id= ntohs(*pcid);
7342 +               break;
7343 +
7344 +       case PPTP_IN_CALL_CONNECT:
7345 +               /* server tells us about incoming call established */
7346 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
7347 +                       DEBUGP("%s but no session\n", strMName[msg]);
7348 +                       break;
7349 +               }
7350 +               if (info->sstate != PPTP_CALL_IN_REP
7351 +                   && info->sstate != PPTP_CALL_IN_CONF) {
7352 +                       DEBUGP("%s but never sent IN_CALL_REPLY\n",
7353 +                               strMName[msg]);
7354 +                       break;
7355 +               }
7356 +
7357 +               pcid = &pptpReq.iccon->peersCallID;
7358 +               cid = &info->pac_call_id;
7359 +
7360 +               if (info->pns_call_id != ntohs(*pcid)) {
7361 +                       DEBUGP("%s for unknown CallID %u\n", 
7362 +                               strMName[msg], ntohs(*cid));
7363 +                       break;
7364 +               }
7365 +
7366 +               DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
7367 +               info->cstate = PPTP_CALL_IN_CONF;
7368 +
7369 +               /* we expect a GRE connection from PAC to PNS */
7370 +               seq = ntohl(tcph->seq) + ((void *)pcid - (void *)pptph);
7371 +               if (exp_gre(ct, seq, *cid, *pcid) != 0)
7372 +                       printk("ip_conntrack_pptp: error during exp_gre\n");
7373 +
7374 +               break;
7375 +
7376 +       case PPTP_CALL_DISCONNECT_NOTIFY:
7377 +               /* server confirms disconnect */
7378 +               cid = &pptpReq.disc->callID;
7379 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
7380 +               info->cstate = PPTP_CALL_NONE;
7381 +
7382 +               /* untrack this call id, unexpect GRE packets */
7383 +               pptp_timeout_related(ct);
7384 +               break;
7385 +
7386 +       case PPTP_WAN_ERROR_NOTIFY:
7387 +               break;
7388 +
7389 +       case PPTP_ECHO_REQUEST:
7390 +       case PPTP_ECHO_REPLY:
7391 +               /* I don't have to explain these ;) */
7392 +               break;
7393 +       default:
7394 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
7395 +                       ? strMName[msg]:strMName[0], msg);
7396 +               break;
7397 +       }
7398 +
7399 +       return NF_ACCEPT;
7400 +
7401 +}
7402 +
7403 +static inline int
7404 +pptp_outbound_pkt(struct tcphdr *tcph,
7405 +                 struct pptp_pkt_hdr *pptph,
7406 +                 size_t datalen,
7407 +                 struct ip_conntrack *ct,
7408 +                 enum ip_conntrack_info ctinfo)
7409 +{
7410 +       struct PptpControlHeader *ctlh;
7411 +        union pptp_ctrl_union pptpReq;
7412 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
7413 +       u_int16_t msg, *cid, *pcid;
7414 +
7415 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
7416 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
7417 +
7418 +       msg = ntohs(ctlh->messageType);
7419 +       DEBUGP("outbound control message %s\n", strMName[msg]);
7420 +
7421 +       switch (msg) {
7422 +       case PPTP_START_SESSION_REQUEST:
7423 +               /* client requests for new control session */
7424 +               if (info->sstate != PPTP_SESSION_NONE) {
7425 +                       DEBUGP("%s but we already have one",
7426 +                               strMName[msg]);
7427 +               }
7428 +               info->sstate = PPTP_SESSION_REQUESTED;
7429 +               break;
7430 +       case PPTP_STOP_SESSION_REQUEST:
7431 +               /* client requests end of control session */
7432 +               info->sstate = PPTP_SESSION_STOPREQ;
7433 +               break;
7434 +
7435 +       case PPTP_OUT_CALL_REQUEST:
7436 +               /* client initiating connection to server */
7437 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
7438 +                       DEBUGP("%s but no session\n",
7439 +                               strMName[msg]);
7440 +                       break;
7441 +               }
7442 +               info->cstate = PPTP_CALL_OUT_REQ;
7443 +               /* track PNS call id */
7444 +               cid = &pptpReq.ocreq->callID;
7445 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*cid));
7446 +               info->pns_call_id = ntohs(*cid);
7447 +               break;
7448 +       case PPTP_IN_CALL_REPLY:
7449 +               /* client answers incoming call */
7450 +               if (info->cstate != PPTP_CALL_IN_REQ
7451 +                   && info->cstate != PPTP_CALL_IN_REP) {
7452 +                       DEBUGP("%s without incall_req\n", 
7453 +                               strMName[msg]);
7454 +                       break;
7455 +               }
7456 +               if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
7457 +                       info->cstate = PPTP_CALL_NONE;
7458 +                       break;
7459 +               }
7460 +               pcid = &pptpReq.icack->peersCallID;
7461 +               if (info->pac_call_id != ntohs(*pcid)) {
7462 +                       DEBUGP("%s for unknown call %u\n", 
7463 +                               strMName[msg], ntohs(*pcid));
7464 +                       break;
7465 +               }
7466 +               DEBUGP("%s, CID=%X\n", strMName[msg], ntohs(*pcid));
7467 +               /* part two of the three-way handshake */
7468 +               info->cstate = PPTP_CALL_IN_REP;
7469 +               info->pns_call_id = ntohs(pptpReq.icack->callID);
7470 +               break;
7471 +
7472 +       case PPTP_CALL_CLEAR_REQUEST:
7473 +               /* client requests hangup of call */
7474 +               if (info->sstate != PPTP_SESSION_CONFIRMED) {
7475 +                       DEBUGP("CLEAR_CALL but no session\n");
7476 +                       break;
7477 +               }
7478 +               /* FUTURE: iterate over all calls and check if
7479 +                * call ID is valid.  We don't do this without newnat,
7480 +                * because we only know about last call */
7481 +               info->cstate = PPTP_CALL_CLEAR_REQ;
7482 +               break;
7483 +       case PPTP_SET_LINK_INFO:
7484 +               break;
7485 +       case PPTP_ECHO_REQUEST:
7486 +       case PPTP_ECHO_REPLY:
7487 +               /* I don't have to explain these ;) */
7488 +               break;
7489 +       default:
7490 +               DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)? 
7491 +                       strMName[msg]:strMName[0], msg);
7492 +               /* unknown: no need to create GRE masq table entry */
7493 +               break;
7494 +       }
7495 +
7496 +       return NF_ACCEPT;
7497 +}
7498 +
7499 +
7500 +/* track caller id inside control connection, call expect_related */
7501 +static int 
7502 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
7503 +                   struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7504 +
7505 +{
7506 +       struct pptp_pkt_hdr *pptph;
7507 +       
7508 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
7509 +       u_int32_t tcplen = len - iph->ihl * 4;
7510 +       u_int32_t datalen = tcplen - tcph->doff * 4;
7511 +       void *datalimit;
7512 +       int dir = CTINFO2DIR(ctinfo);
7513 +       struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
7514 +
7515 +       int oldsstate, oldcstate;
7516 +       int ret;
7517 +
7518 +       /* don't do any tracking before tcp handshake complete */
7519 +       if (ctinfo != IP_CT_ESTABLISHED 
7520 +           && ctinfo != IP_CT_ESTABLISHED+IP_CT_IS_REPLY) {
7521 +               DEBUGP("ctinfo = %u, skipping\n", ctinfo);
7522 +               return NF_ACCEPT;
7523 +       }
7524 +       
7525 +       /* not a complete TCP header? */
7526 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
7527 +               DEBUGP("tcplen = %u\n", tcplen);
7528 +               return NF_ACCEPT;
7529 +       }
7530 +
7531 +       /* checksum invalid? */
7532 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
7533 +                       csum_partial((char *) tcph, tcplen, 0))) {
7534 +               printk(KERN_NOTICE __FILE__ ": bad csum\n");
7535 +               /* W2K PPTP server sends TCP packets with wrong checksum :(( */
7536 +               //return NF_ACCEPT;
7537 +       }
7538 +
7539 +       if (tcph->fin || tcph->rst) {
7540 +               DEBUGP("RST/FIN received, timeouting GRE\n");
7541 +               /* can't do this after real newnat */
7542 +               info->cstate = PPTP_CALL_NONE;
7543 +
7544 +               /* untrack this call id, unexpect GRE packets */
7545 +               pptp_timeout_related(ct);
7546 +       }
7547 +
7548 +
7549 +       pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
7550 +       datalimit = (void *) pptph + datalen;
7551 +
7552 +       /* not a full pptp packet header? */
7553 +       if ((void *) pptph+sizeof(*pptph) >= datalimit) {
7554 +               DEBUGP("no full PPTP header, can't track\n");
7555 +               return NF_ACCEPT;
7556 +       }
7557 +       
7558 +       /* if it's not a control message we can't do anything with it */
7559 +        if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
7560 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
7561 +               DEBUGP("not a control packet\n");
7562 +               return NF_ACCEPT;
7563 +       }
7564 +
7565 +       oldsstate = info->sstate;
7566 +       oldcstate = info->cstate;
7567 +
7568 +       LOCK_BH(&ip_pptp_lock);
7569 +
7570 +       /* FIXME: We just blindly assume that the control connection is always
7571 +        * established from PNS->PAC.  However, RFC makes no guarantee */
7572 +       if (dir == IP_CT_DIR_ORIGINAL)
7573 +               /* client -> server (PNS -> PAC) */
7574 +               ret = pptp_outbound_pkt(tcph, pptph, datalen, ct, ctinfo);
7575 +       else
7576 +               /* server -> client (PAC -> PNS) */
7577 +               ret = pptp_inbound_pkt(tcph, pptph, datalen, ct, ctinfo);
7578 +       DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
7579 +               oldsstate, info->sstate, oldcstate, info->cstate);
7580 +       UNLOCK_BH(&ip_pptp_lock);
7581 +
7582 +       return ret;
7583 +}
7584 +
7585 +/* control protocol helper */
7586 +static struct ip_conntrack_helper pptp = { 
7587 +       .list = { NULL, NULL },
7588 +       .name = "pptp", 
7589 +       .flags = IP_CT_HELPER_F_REUSE_EXPECT,
7590 +       .me = THIS_MODULE,
7591 +       .max_expected = 2,
7592 +       .timeout = 0,
7593 +       .tuple = { .src = { .ip = 0, 
7594 +                           .u = { .tcp = { .port =  
7595 +                                   __constant_htons(PPTP_CONTROL_PORT) } } 
7596 +                         }, 
7597 +                  .dst = { .ip = 0, 
7598 +                           .u = { .all = 0 },
7599 +                           .protonum = IPPROTO_TCP
7600 +                         } 
7601 +                },
7602 +       .mask = { .src = { .ip = 0, 
7603 +                          .u = { .tcp = { .port = 0xffff } } 
7604 +                        }, 
7605 +                 .dst = { .ip = 0, 
7606 +                          .u = { .all = 0 },
7607 +                          .protonum = 0xffff 
7608 +                        } 
7609 +               },
7610 +       .help = conntrack_pptp_help
7611 +};
7612 +
7613 +/* ip_conntrack_pptp initialization */
7614 +static int __init init(void)
7615 +{
7616 +       int retcode;
7617 +
7618 +       DEBUGP(__FILE__ ": registering helper\n");
7619 +       if ((retcode = ip_conntrack_helper_register(&pptp))) {
7620 +                printk(KERN_ERR "Unable to register conntrack application "
7621 +                               "helper for pptp: %d\n", retcode);
7622 +               return -EIO;
7623 +       }
7624 +
7625 +       printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
7626 +       return 0;
7627 +}
7628 +
7629 +static void __exit fini(void)
7630 +{
7631 +       ip_conntrack_helper_unregister(&pptp);
7632 +       printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
7633 +}
7634 +
7635 +module_init(init);
7636 +module_exit(fini);
7637 +
7638 +EXPORT_SYMBOL(ip_pptp_lock);
7639 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h linux-2.4.20/net/ipv4/netfilter/ip_conntrack_pptp_priv.h
7640 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_pptp_priv.h        Thu Jan  1 00:00:00 1970
7641 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_pptp_priv.h    Wed Sep 24 09:17:55 2003
7642 @@ -0,0 +1,24 @@
7643 +#ifndef _IP_CT_PPTP_PRIV_H
7644 +#define _IP_CT_PPTP_PRIV_H
7645 +
7646 +/* PptpControlMessageType names */
7647 +static const char *strMName[] = {
7648 +       "UNKNOWN_MESSAGE",
7649 +       "START_SESSION_REQUEST",
7650 +       "START_SESSION_REPLY",
7651 +       "STOP_SESSION_REQUEST",
7652 +       "STOP_SESSION_REPLY",
7653 +       "ECHO_REQUEST",
7654 +       "ECHO_REPLY",
7655 +       "OUT_CALL_REQUEST",
7656 +       "OUT_CALL_REPLY",
7657 +       "IN_CALL_REQUEST",
7658 +       "IN_CALL_REPLY",
7659 +       "IN_CALL_CONNECT",
7660 +       "CALL_CLEAR_REQUEST",
7661 +       "CALL_DISCONNECT_NOTIFY",
7662 +       "WAN_ERROR_NOTIFY",
7663 +       "SET_LINK_INFO"
7664 +};
7665 +
7666 +#endif
7667 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_generic.c
7668 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_generic.c    Thu Nov 28 23:53:15 2002
7669 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_generic.c        Wed Sep 24 09:16:22 2003
7670 @@ -4,7 +4,7 @@
7671  #include <linux/netfilter.h>
7672  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
7673  
7674 -#define GENERIC_TIMEOUT (600*HZ)
7675 +unsigned long ip_ct_generic_timeout = 600*HZ;
7676  
7677  static int generic_pkt_to_tuple(const void *datah, size_t datalen,
7678                                 struct ip_conntrack_tuple *tuple)
7679 @@ -43,7 +43,7 @@
7680                        struct iphdr *iph, size_t len,
7681                        enum ip_conntrack_info conntrackinfo)
7682  {
7683 -       ip_ct_refresh(conntrack, GENERIC_TIMEOUT);
7684 +       ip_ct_refresh(conntrack, ip_ct_generic_timeout);
7685         return NF_ACCEPT;
7686  }
7687  
7688 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_gre.c
7689 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_gre.c        Thu Jan  1 00:00:00 1970
7690 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_gre.c    Wed Sep 24 09:17:55 2003
7691 @@ -0,0 +1,343 @@
7692 +/*
7693 + * ip_conntrack_proto_gre.c - Version 1.2 
7694 + *
7695 + * Connection tracking protocol helper module for GRE.
7696 + *
7697 + * GRE is a generic encapsulation protocol, which is generally not very
7698 + * suited for NAT, as it has no protocol-specific part as port numbers.
7699 + *
7700 + * It has an optional key field, which may help us distinguishing two 
7701 + * connections between the same two hosts.
7702 + *
7703 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
7704 + *
7705 + * PPTP is built on top of a modified version of GRE, and has a mandatory
7706 + * field called "CallID", which serves us for the same purpose as the key
7707 + * field in plain GRE.
7708 + *
7709 + * Documentation about PPTP can be found in RFC 2637
7710 + *
7711 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
7712 + *
7713 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
7714 + *
7715 + */
7716 +
7717 +#include <linux/config.h>
7718 +#include <linux/module.h>
7719 +#include <linux/types.h>
7720 +#include <linux/timer.h>
7721 +#include <linux/netfilter.h>
7722 +#include <linux/ip.h>
7723 +#include <linux/in.h>
7724 +#include <linux/list.h>
7725 +
7726 +#include <linux/netfilter_ipv4/lockhelp.h>
7727 +
7728 +DECLARE_RWLOCK(ip_ct_gre_lock);
7729 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_ct_gre_lock)
7730 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_ct_gre_lock)
7731 +
7732 +#include <linux/netfilter_ipv4/listhelp.h>
7733 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
7734 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
7735 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
7736 +
7737 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
7738 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
7739 +
7740 +MODULE_LICENSE("GPL");
7741 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
7742 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
7743 +
7744 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
7745 +#define GRE_TIMEOUT            (30*HZ)
7746 +#define GRE_STREAM_TIMEOUT     (180*HZ)
7747 +
7748 +#if 0
7749 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
7750 +                                      ": " format, ## args)
7751 +#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x:%u:0x%x\n", \
7752 +                       NIPQUAD((x)->src.ip), ntohl((x)->src.u.gre.key), \
7753 +                       NIPQUAD((x)->dst.ip), ntohl((x)->dst.u.gre.key), \
7754 +                       (x)->dst.u.gre.version, \
7755 +                       ntohs((x)->dst.u.gre.protocol))
7756 +#else
7757 +#define DEBUGP(x, args...)
7758 +#define DUMP_TUPLE_GRE(x)
7759 +#endif
7760 +                               
7761 +/* GRE KEYMAP HANDLING FUNCTIONS */
7762 +static LIST_HEAD(gre_keymap_list);
7763 +
7764 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
7765 +                               const struct ip_conntrack_tuple *t)
7766 +{
7767 +       return ((km->tuple.src.ip == t->src.ip) &&
7768 +               (km->tuple.dst.ip == t->dst.ip) &&
7769 +               (km->tuple.dst.protonum == t->dst.protonum) &&
7770 +               (km->tuple.dst.u.all == t->dst.u.all));
7771 +}
7772 +
7773 +/* look up the source key for a given tuple */
7774 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
7775 +{
7776 +       struct ip_ct_gre_keymap *km;
7777 +       u_int32_t key;
7778 +
7779 +       READ_LOCK(&ip_ct_gre_lock);
7780 +       km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
7781 +                       struct ip_ct_gre_keymap *, t);
7782 +       if (!km) {
7783 +               READ_UNLOCK(&ip_ct_gre_lock);
7784 +               return 0;
7785 +       }
7786 +
7787 +       key = km->tuple.src.u.gre.key;
7788 +       READ_UNLOCK(&ip_ct_gre_lock);
7789 +
7790 +       return key;
7791 +}
7792 +
7793 +/* add a single keymap entry, associate with specified expect */
7794 +int ip_ct_gre_keymap_add(struct ip_conntrack_expect *exp,
7795 +                        struct ip_conntrack_tuple *t, int reply)
7796 +{
7797 +       struct ip_ct_gre_keymap *km;
7798 +
7799 +       km = kmalloc(sizeof(*km), GFP_ATOMIC);
7800 +       if (!km)
7801 +               return -1;
7802 +
7803 +       /* initializing list head should be sufficient */
7804 +       memset(km, 0, sizeof(*km));
7805 +
7806 +       memcpy(&km->tuple, t, sizeof(*t));
7807 +
7808 +       if (!reply)
7809 +               exp->proto.gre.keymap_orig = km;
7810 +       else
7811 +               exp->proto.gre.keymap_reply = km;
7812 +
7813 +       DEBUGP("adding new entry %p: ", km);
7814 +       DUMP_TUPLE_GRE(&km->tuple);
7815 +
7816 +       WRITE_LOCK(&ip_ct_gre_lock);
7817 +       list_append(&gre_keymap_list, km);
7818 +       WRITE_UNLOCK(&ip_ct_gre_lock);
7819 +
7820 +       return 0;
7821 +}
7822 +
7823 +/* change the tuple of a keymap entry (used by nat helper) */
7824 +void ip_ct_gre_keymap_change(struct ip_ct_gre_keymap *km,
7825 +                            struct ip_conntrack_tuple *t)
7826 +{
7827 +       DEBUGP("changing entry %p to: ", km);
7828 +       DUMP_TUPLE_GRE(t);
7829 +
7830 +       WRITE_LOCK(&ip_ct_gre_lock);
7831 +       memcpy(&km->tuple, t, sizeof(km->tuple));
7832 +       WRITE_UNLOCK(&ip_ct_gre_lock);
7833 +}
7834 +
7835 +/* destroy the keymap entries associated with specified expect */
7836 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
7837 +{
7838 +       DEBUGP("entering for exp %p\n", exp);
7839 +       WRITE_LOCK(&ip_ct_gre_lock);
7840 +       if (exp->proto.gre.keymap_orig) {
7841 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_orig);
7842 +               list_del(&exp->proto.gre.keymap_orig->list);
7843 +               kfree(exp->proto.gre.keymap_orig);
7844 +               exp->proto.gre.keymap_orig = NULL;
7845 +       }
7846 +       if (exp->proto.gre.keymap_reply) {
7847 +               DEBUGP("removing %p from list\n", exp->proto.gre.keymap_reply);
7848 +               list_del(&exp->proto.gre.keymap_reply->list);
7849 +               kfree(exp->proto.gre.keymap_reply);
7850 +               exp->proto.gre.keymap_reply = NULL;
7851 +       }
7852 +       WRITE_UNLOCK(&ip_ct_gre_lock);
7853 +}
7854 +
7855 +
7856 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
7857 +
7858 +/* invert gre part of tuple */
7859 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
7860 +                           const struct ip_conntrack_tuple *orig)
7861 +{
7862 +       tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
7863 +       tuple->dst.u.gre.version = orig->dst.u.gre.version;
7864 +
7865 +       tuple->dst.u.gre.key = orig->src.u.gre.key;
7866 +       tuple->src.u.gre.key = orig->dst.u.gre.key;
7867 +
7868 +       return 1;
7869 +}
7870 +
7871 +/* gre hdr info to tuple */
7872 +static int gre_pkt_to_tuple(const void *datah, size_t datalen,
7873 +                           struct ip_conntrack_tuple *tuple)
7874 +{
7875 +       struct gre_hdr *grehdr = (struct gre_hdr *) datah;
7876 +       struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
7877 +       u_int32_t srckey;
7878 +
7879 +       /* core guarantees 8 protocol bytes, no need for size check */
7880 +
7881 +       tuple->dst.u.gre.version = grehdr->version; 
7882 +       tuple->dst.u.gre.protocol = grehdr->protocol;
7883 +
7884 +       switch (grehdr->version) {
7885 +               case GRE_VERSION_1701:
7886 +                       if (!grehdr->key) {
7887 +                               DEBUGP("Can't track GRE without key\n");
7888 +                               return 0;
7889 +                       }
7890 +                       tuple->dst.u.gre.key = *(gre_key(grehdr));
7891 +                       break;
7892 +
7893 +               case GRE_VERSION_PPTP:
7894 +                       if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
7895 +                               DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
7896 +                               return 0;
7897 +                       }
7898 +                       tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
7899 +                       break;
7900 +
7901 +               default:
7902 +                       printk(KERN_WARNING "unknown GRE version %hu\n",
7903 +                               tuple->dst.u.gre.version);
7904 +                       return 0;
7905 +       }
7906 +
7907 +       srckey = gre_keymap_lookup(tuple);
7908 +
7909 +#if 0
7910 +       DEBUGP("found src key %x for tuple ", ntohl(srckey));
7911 +       DUMP_TUPLE_GRE(tuple);
7912 +#endif
7913 +       tuple->src.u.gre.key = srckey;
7914 +
7915 +       return 1;
7916 +}
7917 +
7918 +/* print gre part of tuple */
7919 +static unsigned int gre_print_tuple(char *buffer,
7920 +                                   const struct ip_conntrack_tuple *tuple)
7921 +{
7922 +       return sprintf(buffer, "version=%d protocol=0x%04x srckey=0x%x dstkey=0x%x ", 
7923 +                       tuple->dst.u.gre.version,
7924 +                       ntohs(tuple->dst.u.gre.protocol),
7925 +                       ntohl(tuple->src.u.gre.key),
7926 +                       ntohl(tuple->dst.u.gre.key));
7927 +}
7928 +
7929 +/* print private data for conntrack */
7930 +static unsigned int gre_print_conntrack(char *buffer,
7931 +                                       const struct ip_conntrack *ct)
7932 +{
7933 +       return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
7934 +                      (ct->proto.gre.timeout / HZ),
7935 +                      (ct->proto.gre.stream_timeout / HZ));
7936 +}
7937 +
7938 +/* Returns verdict for packet, and may modify conntrack */
7939 +static int gre_packet(struct ip_conntrack *ct,
7940 +                     struct iphdr *iph, size_t len,
7941 +                     enum ip_conntrack_info conntrackinfo)
7942 +{
7943 +       /* If we've seen traffic both ways, this is a GRE connection.
7944 +        * Extend timeout. */
7945 +       if (ct->status & IPS_SEEN_REPLY) {
7946 +               ip_ct_refresh(ct, ct->proto.gre.stream_timeout);
7947 +               /* Also, more likely to be important, and not a probe. */
7948 +               set_bit(IPS_ASSURED_BIT, &ct->status);
7949 +       } else
7950 +               ip_ct_refresh(ct, ct->proto.gre.timeout);
7951 +       
7952 +       return NF_ACCEPT;
7953 +}
7954 +
7955 +/* Called when a new connection for this protocol found. */
7956 +static int gre_new(struct ip_conntrack *ct,
7957 +                  struct iphdr *iph, size_t len)
7958 +{ 
7959 +       DEBUGP(": ");
7960 +       DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
7961 +
7962 +       /* initialize to sane value.  Ideally a conntrack helper
7963 +        * (e.g. in case of pptp) is increasing them */
7964 +       ct->proto.gre.stream_timeout = GRE_STREAM_TIMEOUT;
7965 +       ct->proto.gre.timeout = GRE_TIMEOUT;
7966 +
7967 +       return 1;
7968 +}
7969 +
7970 +/* Called when a conntrack entry has already been removed from the hashes
7971 + * and is about to be deleted from memory */
7972 +static void gre_destroy(struct ip_conntrack *ct)
7973 +{
7974 +       struct ip_conntrack_expect *master = ct->master;
7975 +
7976 +       DEBUGP(" entering\n");
7977 +
7978 +       if (!master) {
7979 +               DEBUGP("no master exp for ct %p\n", ct);
7980 +               return;
7981 +       }
7982 +
7983 +       ip_ct_gre_keymap_destroy(master);
7984 +}
7985 +
7986 +/* protocol helper struct */
7987 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
7988 +                                           "gre", 
7989 +                                           gre_pkt_to_tuple,
7990 +                                           gre_invert_tuple,
7991 +                                           gre_print_tuple,
7992 +                                           gre_print_conntrack,
7993 +                                           gre_packet,
7994 +                                           gre_new,
7995 +                                           gre_destroy,
7996 +                                           NULL,
7997 +                                           THIS_MODULE };
7998 +
7999 +/* ip_conntrack_proto_gre initialization */
8000 +static int __init init(void)
8001 +{
8002 +       int retcode;
8003 +
8004 +       if ((retcode = ip_conntrack_protocol_register(&gre))) {
8005 +                printk(KERN_ERR "Unable to register conntrack protocol "
8006 +                               "helper for gre: %d\n", retcode);
8007 +               return -EIO;
8008 +       }
8009 +
8010 +       return 0;
8011 +}
8012 +
8013 +static void __exit fini(void)
8014 +{
8015 +       struct list_head *pos, *n;
8016 +
8017 +       /* delete all keymap entries */
8018 +       WRITE_LOCK(&ip_ct_gre_lock);
8019 +       list_for_each_safe(pos, n, &gre_keymap_list) {
8020 +               DEBUGP("deleting keymap %p at module unload time\n", pos);
8021 +               list_del(pos);
8022 +               kfree(pos);
8023 +       }
8024 +       WRITE_UNLOCK(&ip_ct_gre_lock);
8025 +
8026 +       ip_conntrack_protocol_unregister(&gre); 
8027 +}
8028 +
8029 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
8030 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
8031 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
8032 +
8033 +module_init(init);
8034 +module_exit(fini);
8035 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
8036 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_icmp.c       Thu Nov 28 23:53:15 2002
8037 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_icmp.c   Wed Sep 24 09:16:22 2003
8038 @@ -6,7 +6,7 @@
8039  #include <linux/icmp.h>
8040  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
8041  
8042 -#define ICMP_TIMEOUT (30*HZ)
8043 +unsigned long ip_ct_icmp_timeout = 30*HZ;
8044  
8045  #if 0
8046  #define DEBUGP printk
8047 @@ -82,7 +82,7 @@
8048                         ct->timeout.function((unsigned long)ct);
8049         } else {
8050                 atomic_inc(&ct->proto.icmp.count);
8051 -               ip_ct_refresh(ct, ICMP_TIMEOUT);
8052 +               ip_ct_refresh(ct, ip_ct_icmp_timeout);
8053         }
8054  
8055         return NF_ACCEPT;
8056 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
8057 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_tcp.c        Thu Nov 28 23:53:15 2002
8058 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_tcp.c    Wed Sep 24 09:16:22 2003
8059 @@ -1,4 +1,3 @@
8060 -#define __NO_VERSION__
8061  #include <linux/types.h>
8062  #include <linux/sched.h>
8063  #include <linux/timer.h>
8064 @@ -50,20 +49,28 @@
8065  #define HOURS * 60 MINS
8066  #define DAYS * 24 HOURS
8067  
8068 -
8069 -static unsigned long tcp_timeouts[]
8070 -= { 30 MINS,   /*      TCP_CONNTRACK_NONE,     */
8071 -    5 DAYS,    /*      TCP_CONNTRACK_ESTABLISHED,      */
8072 -    2 MINS,    /*      TCP_CONNTRACK_SYN_SENT, */
8073 -    60 SECS,   /*      TCP_CONNTRACK_SYN_RECV, */
8074 -    2 MINS,    /*      TCP_CONNTRACK_FIN_WAIT, */
8075 -    2 MINS,    /*      TCP_CONNTRACK_TIME_WAIT,        */
8076 -    10 SECS,   /*      TCP_CONNTRACK_CLOSE,    */
8077 -    60 SECS,   /*      TCP_CONNTRACK_CLOSE_WAIT,       */
8078 -    30 SECS,   /*      TCP_CONNTRACK_LAST_ACK, */
8079 -    2 MINS,    /*      TCP_CONNTRACK_LISTEN,   */
8080 -};
8081 -
8082 +unsigned long ip_ct_tcp_timeout_syn_sent =      2 MINS;
8083 +unsigned long ip_ct_tcp_timeout_syn_recv =     60 SECS;
8084 +unsigned long ip_ct_tcp_timeout_established =   5 DAYS;
8085 +unsigned long ip_ct_tcp_timeout_fin_wait =      2 MINS;
8086 +unsigned long ip_ct_tcp_timeout_close_wait =    3 DAYS;
8087 +unsigned long ip_ct_tcp_timeout_last_ack =     30 SECS;
8088 +unsigned long ip_ct_tcp_timeout_time_wait =     2 MINS;
8089 +unsigned long ip_ct_tcp_timeout_close =        10 SECS;
8090 +
8091 +static unsigned long * tcp_timeouts[]
8092 += { 0,                                 /*      TCP_CONNTRACK_NONE */
8093 +    &ip_ct_tcp_timeout_established,    /*      TCP_CONNTRACK_ESTABLISHED,      */
8094 +    &ip_ct_tcp_timeout_syn_sent,       /*      TCP_CONNTRACK_SYN_SENT, */
8095 +    &ip_ct_tcp_timeout_syn_recv,       /*      TCP_CONNTRACK_SYN_RECV, */
8096 +    &ip_ct_tcp_timeout_fin_wait,       /*      TCP_CONNTRACK_FIN_WAIT, */
8097 +    &ip_ct_tcp_timeout_time_wait,      /*      TCP_CONNTRACK_TIME_WAIT,        */
8098 +    &ip_ct_tcp_timeout_close,          /*      TCP_CONNTRACK_CLOSE,    */
8099 +    &ip_ct_tcp_timeout_close_wait,     /*      TCP_CONNTRACK_CLOSE_WAIT,       */
8100 +    &ip_ct_tcp_timeout_last_ack,       /*      TCP_CONNTRACK_LAST_ACK, */
8101 +    0,                                 /*      TCP_CONNTRACK_LISTEN */
8102 + };
8103
8104  #define sNO TCP_CONNTRACK_NONE
8105  #define sES TCP_CONNTRACK_ESTABLISHED
8106  #define sSS TCP_CONNTRACK_SYN_SENT
8107 @@ -186,13 +193,13 @@
8108             && tcph->syn && tcph->ack)
8109                 conntrack->proto.tcp.handshake_ack
8110                         = htonl(ntohl(tcph->seq) + 1);
8111 -       WRITE_UNLOCK(&tcp_lock);
8112  
8113         /* If only reply is a RST, we can consider ourselves not to
8114            have an established connection: this is a fairly common
8115            problem case, so we can delete the conntrack
8116            immediately.  --RR */
8117 -       if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {
8118 +       if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
8119 +               WRITE_UNLOCK(&tcp_lock);
8120                 if (del_timer(&conntrack->timeout))
8121                         conntrack->timeout.function((unsigned long)conntrack);
8122         } else {
8123 @@ -203,7 +210,8 @@
8124                     && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
8125                         set_bit(IPS_ASSURED_BIT, &conntrack->status);
8126  
8127 -               ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);
8128 +               WRITE_UNLOCK(&tcp_lock);
8129 +               ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
8130         }
8131  
8132         return NF_ACCEPT;
8133 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_udp.c
8134 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_proto_udp.c        Thu Nov 28 23:53:15 2002
8135 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_proto_udp.c    Wed Sep 24 09:16:22 2003
8136 @@ -6,8 +6,8 @@
8137  #include <linux/udp.h>
8138  #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
8139  
8140 -#define UDP_TIMEOUT (30*HZ)
8141 -#define UDP_STREAM_TIMEOUT (180*HZ)
8142 +unsigned long ip_ct_udp_timeout = 30*HZ;
8143 +unsigned long ip_ct_udp_timeout_stream = 180*HZ;
8144  
8145  static int udp_pkt_to_tuple(const void *datah, size_t datalen,
8146                             struct ip_conntrack_tuple *tuple)
8147 @@ -51,12 +51,12 @@
8148  {
8149         /* If we've seen traffic both ways, this is some kind of UDP
8150            stream.  Extend timeout. */
8151 -       if (conntrack->status & IPS_SEEN_REPLY) {
8152 -               ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT);
8153 +       if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
8154 +               ip_ct_refresh(conntrack, ip_ct_udp_timeout_stream);
8155                 /* Also, more likely to be important, and not a probe */
8156                 set_bit(IPS_ASSURED_BIT, &conntrack->status);
8157         } else
8158 -               ip_ct_refresh(conntrack, UDP_TIMEOUT);
8159 +               ip_ct_refresh(conntrack, ip_ct_udp_timeout);
8160  
8161         return NF_ACCEPT;
8162  }
8163 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_quake3.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_quake3.c
8164 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_quake3.c   Thu Jan  1 00:00:00 1970
8165 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_quake3.c       Wed Sep 24 09:17:58 2003
8166 @@ -0,0 +1,156 @@
8167 +/* Quake3 extension for IP connection tracking
8168 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
8169 + * based on ip_conntrack_ftp.c and ip_conntrack_tftp.c
8170 + *
8171 + * ip_conntrack_quake3.c v0.04 2002-08-31
8172 + *
8173 + *      This program is free software; you can redistribute it and/or
8174 + *      modify it under the terms of the GNU General Public License
8175 + *      as published by the Free Software Foundation; either version
8176 + *      2 of the License, or (at your option) any later version.
8177 + *
8178 + *      Module load syntax:
8179 + *      insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
8180 + *
8181 + *      please give the ports of all Quake3 master servers You wish to 
8182 + *      connect to. If you don't specify ports, the default will be UDP 
8183 + *      port 27950.
8184 + *
8185 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
8186 + */
8187 +
8188 +#include <linux/module.h>
8189 +#include <linux/ip.h>
8190 +#include <linux/udp.h>
8191 +
8192 +#include <linux/netfilter.h>
8193 +#include <linux/netfilter_ipv4/ip_tables.h>
8194 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8195 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
8196 +
8197 +struct module *ip_conntrack_quake3 = THIS_MODULE;
8198 +
8199 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8200 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
8201 +MODULE_LICENSE("GPL");
8202 +
8203 +#define MAX_PORTS 8
8204 +static int ports[MAX_PORTS];
8205 +static int ports_c = 0;
8206 +#ifdef MODULE_PARM
8207 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8208 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
8209 +#endif
8210 +
8211 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
8212 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
8213 +#if 0 
8214 +#define DEBUGP printk
8215 +#else
8216 +#define DEBUGP(format, args...)
8217 +#endif
8218 +
8219 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
8220 +
8221 +static int quake3_help(const struct iphdr *iph, size_t len,
8222 +       struct ip_conntrack *ct,
8223 +       enum ip_conntrack_info ctinfo)
8224 +{
8225 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
8226 +       int dir = CTINFO2DIR(ctinfo);
8227 +       struct ip_conntrack_expect exp;
8228 +       int i;
8229 +       
8230 +        /* Until there's been traffic both ways, don't look in packets. note: it's UDP ! */
8231 +       if (ctinfo != IP_CT_ESTABLISHED
8232 +           && ctinfo != IP_CT_IS_REPLY) {
8233 +               DEBUGP("ip_conntrack_quake3: not ok ! Conntrackinfo = %u\n", ctinfo);
8234 +               return NF_ACCEPT;
8235 +       } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
8236 +       
8237 +       if (strnicmp((const char *)udph + 12, quake3s_conntrack.pattern, quake3s_conntrack.plen) == 0) {
8238 +               for(i=31;    /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
8239 +                   i+6 < ntohs(udph->len);
8240 +                   i+=7) {
8241 +                       DEBUGP("ip_conntrack_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n",
8242 +                              i, ntohs(udph->len),
8243 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ), 
8244 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
8245 +
8246 +                       memset(&exp, 0, sizeof(exp));
8247 +
8248 +                       exp.tuple = ((struct ip_conntrack_tuple)
8249 +                                    { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
8250 +                                      { (u_int32_t) *((u_int32_t *)((int)udph + i)), 
8251 +                                      { .udp = { (__u16) *((__u16 *)((int)udph+i+4)) } }, 
8252 +                                        IPPROTO_UDP } }
8253 +                                   );
8254 +                       exp.mask  = ((struct ip_conntrack_tuple)
8255 +                                    { { 0xFFFFFFFF, { 0 } },
8256 +                                      { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
8257 +                       exp.expectfn = NULL;
8258 +
8259 +                       ip_conntrack_expect_related(ct, &exp);
8260 +               }
8261 +
8262 +       }
8263 +       
8264 +       return(NF_ACCEPT);
8265 +}
8266 +
8267 +static struct ip_conntrack_helper quake3[MAX_PORTS];
8268 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
8269 +
8270 +static void fini(void)
8271 +{
8272 +       int i;
8273 +
8274 +       for(i = 0 ; (i < ports_c); i++) {
8275 +               DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
8276 +                                       ports[i]);
8277 +               ip_conntrack_helper_unregister(&quake3[i]);
8278 +       } 
8279 +}
8280 +
8281 +static int __init init(void)
8282 +{
8283 +       int i, ret;
8284 +       char *tmpname;
8285 +
8286 +       if(!ports[0])
8287 +               ports[0]=QUAKE3_MASTER_PORT;
8288 +
8289 +       for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
8290 +               /* Create helper structure */
8291 +               memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
8292 +
8293 +               quake3[i].tuple.dst.protonum = IPPROTO_UDP;
8294 +               quake3[i].tuple.src.u.udp.port = htons(ports[i]);
8295 +               quake3[i].mask.dst.protonum = 0xFFFF;
8296 +               quake3[i].mask.src.u.udp.port = 0xFFFF;
8297 +               quake3[i].help = quake3_help;
8298 +               quake3[i].me = THIS_MODULE;
8299 +
8300 +               tmpname = &quake3_names[i][0];
8301 +               if (ports[i] == QUAKE3_MASTER_PORT)
8302 +                       sprintf(tmpname, "quake3");
8303 +               else
8304 +                       sprintf(tmpname, "quake3-%d", i);
8305 +               quake3[i].name = tmpname;
8306 +               
8307 +               DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
8308 +                      ports[i]);
8309 +
8310 +               ret=ip_conntrack_helper_register(&quake3[i]);
8311 +               if(ret) {
8312 +                       fini();
8313 +                       return(ret);
8314 +               }
8315 +               ports_c++;
8316 +       }
8317 +
8318 +       return(0);
8319 +}
8320 +
8321 +module_init(init);
8322 +module_exit(fini);
8323 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c
8324 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c  Thu Jan  1 00:00:00 1970
8325 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rpc_tcp.c      Wed Sep 24 09:18:01 2003
8326 @@ -0,0 +1,508 @@
8327 +/* RPC extension for IP (TCP) connection tracking, Version 2.2
8328 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
8329 + *     - original rpc tracking module
8330 + *     - "recent" connection handling for kernel 2.3+ netfilter
8331 + *
8332 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8333 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
8334 + *
8335 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
8336 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
8337 + *     - extended matching to support filtering on procedures
8338 + *
8339 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
8340 + *
8341 + *     This program is free software; you can redistribute it and/or
8342 + *     modify it under the terms of the GNU General Public License
8343 + *     as published by the Free Software Foundation; either version
8344 + *     2 of the License, or (at your option) any later version.
8345 + **
8346 + *     Module load syntax:
8347 + *     insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
8348 + *
8349 + *     Please give the ports of all RPC servers you wish to connect to.
8350 + *     If you don't specify ports, the default will be port 111.
8351 + **
8352 + *     Note to all:
8353 + *
8354 + *     RPCs should not be exposed to the internet - ask the Pentagon;
8355 + *
8356 + *       "The unidentified crackers pleaded guilty in July to charges
8357 + *        of juvenile delinquency stemming from a string of Pentagon
8358 + *        network intrusions in February.
8359 + *
8360 + *        The youths, going by the names TooShort and Makaveli, used
8361 + *        a common server security hole to break in, according to
8362 + *        Dane Jasper, owner of the California Internet service
8363 + *        provider, Sonic. They used the hole, known as the 'statd'
8364 + *        exploit, to attempt more than 800 break-ins, Jasper said."
8365 + *
8366 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
8367 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
8368 + **
8369 + */
8370 +
8371 +#include <linux/module.h>
8372 +#include <linux/netfilter.h>
8373 +#include <linux/ip.h>
8374 +#include <net/checksum.h>
8375 +#include <net/tcp.h>
8376 +
8377 +#include <asm/param.h>
8378 +#include <linux/sched.h>
8379 +#include <linux/timer.h>
8380 +#include <linux/stddef.h>
8381 +#include <linux/list.h>
8382 +
8383 +#include <linux/netfilter_ipv4/lockhelp.h>
8384 +#include <linux/netfilter_ipv4/ip_tables.h>
8385 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8386 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
8387 +
8388 +#define MAX_PORTS 8
8389 +static int ports[MAX_PORTS];
8390 +static int ports_n_c = 0;
8391 +
8392 +#ifdef MODULE_PARM
8393 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8394 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8395 +#endif
8396 +
8397 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8398 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
8399 +MODULE_LICENSE("GPL");
8400 +
8401 +#if 0
8402 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
8403 +                                       format, ## args)
8404 +#else
8405 +#define DEBUGP(format, args...)
8406 +#endif
8407 +
8408 +DECLARE_RWLOCK(ipct_rpc_tcp_lock);
8409 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock)
8410 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock)
8411 +#include <linux/netfilter_ipv4/listhelp.h>
8412 +
8413 +/* For future conections RPC, using client's cache bindings
8414 + * I'll use ip_conntrack_lock to lock these lists         */
8415 +
8416 +LIST_HEAD(request_p_list_tcp);
8417 +
8418 +
8419 +static void delete_request_p(unsigned long request_p_ul) 
8420 +{
8421 +       struct request_p *p = (void *)request_p_ul;
8422 +       
8423 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
8424 +       LIST_DELETE(&request_p_list_tcp, p);
8425 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8426 +       kfree(p);
8427 +       return;
8428 +}
8429 +
8430 +
8431 +static void req_cl(struct request_p * r)
8432 +{
8433 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
8434 +       del_timer(&r->timeout);
8435 +       LIST_DELETE(&request_p_list_tcp, r);
8436 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8437 +       kfree(r);
8438 +       return;
8439 +}
8440 +
8441 +
8442 +static void clean_request(struct list_head *list)
8443 +{
8444 +       struct list_head *first = list->prev;
8445 +       struct list_head *temp = list->next;
8446 +       struct list_head *aux;
8447 +
8448 +       if (list_empty(list))
8449 +               return;
8450 +
8451 +       while (first != temp) {
8452 +               aux = temp->next;
8453 +               req_cl((struct request_p *)temp);
8454 +               temp = aux;     
8455 +       }
8456 +       req_cl((struct request_p *)temp);
8457 +       return;
8458 +}
8459 +
8460 +
8461 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
8462 +                    u_int16_t port)
8463 +{
8464 +       struct request_p *req_p;
8465 +       
8466 +       /* Verifies if entry already exists */
8467 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
8468 +       req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
8469 +               struct request_p *, xid, ip, port);
8470 +
8471 +       if (req_p) {
8472 +               /* Refresh timeout */
8473 +               if (del_timer(&req_p->timeout)) {
8474 +                       req_p->timeout.expires = jiffies + EXP;
8475 +                       add_timer(&req_p->timeout);     
8476 +               } 
8477 +               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8478 +               return; 
8479 +
8480 +       }
8481 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8482 +       
8483 +       /* Allocate new request_p */
8484 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
8485 +       if (!req_p) {
8486 +               DEBUGP("can't allocate request_p\n");
8487 +               return;                 
8488 +       }
8489 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
8490 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
8491 +                       NULL }}); 
8492 +      
8493 +       /* Initialize timer */
8494 +       init_timer(&req_p->timeout);
8495 +       req_p->timeout.function = delete_request_p;
8496 +       add_timer(&req_p->timeout); 
8497 +
8498 +       /* Put in list */
8499 +       WRITE_LOCK(&ipct_rpc_tcp_lock);
8500 +       list_prepend(&request_p_list_tcp, req_p);
8501 +       WRITE_UNLOCK(&ipct_rpc_tcp_lock); 
8502 +       return; 
8503 +
8504 +}
8505 +
8506 +
8507 +static int check_rpc_packet(const u_int32_t *data,
8508 +                       int dir, struct ip_conntrack *ct,
8509 +                       struct list_head request_p_list)
8510 +{
8511 +       struct request_p *req_p;
8512 +       u_int32_t xid;
8513 +       struct ip_conntrack_expect expect, *exp = &expect;
8514 +
8515 +        /* Translstion's buffer for XDR */
8516 +        u_int16_t port_buf;
8517 +
8518 +
8519 +       /* Get XID */
8520 +       xid = *data;
8521 +
8522 +       /* This does sanity checking on RPC payloads,
8523 +        * and permits only the RPC "get port" (3)
8524 +        * in authorised procedures in client
8525 +        * communications with the portmapper.
8526 +        */
8527 +
8528 +       /* perform direction dependant RPC work */
8529 +       if (dir == IP_CT_DIR_ORIGINAL) {
8530 +
8531 +               data += 5;
8532 +
8533 +               /* Get RPC requestor */
8534 +               if (IXDR_GET_INT32(data) != 3) {
8535 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
8536 +                       return NF_ACCEPT;
8537 +               }
8538 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
8539 +
8540 +               data++;
8541 +
8542 +               /* Jump Credentials and Verfifier */
8543 +               data += IXDR_GET_INT32(data) + 2;
8544 +               data += IXDR_GET_INT32(data) + 2;
8545 +
8546 +               /* Get RPC procedure */
8547 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
8548 +                       (unsigned int)IXDR_GET_INT32(data));
8549 +
8550 +               /* Get RPC protocol and store against client parameters */
8551 +               data = data + 2;
8552 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
8553 +                               ct->tuplehash[dir].tuple.src.u.all);
8554 +
8555 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
8556 +                       xid, IXDR_GET_INT32(data),
8557 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
8558 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
8559 +
8560 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
8561 +                       (unsigned int)IXDR_GET_INT32(data));
8562 +
8563 +       } else {
8564 +
8565 +               /* Check for returning packet's stored counterpart */
8566 +               req_p = LIST_FIND(&request_p_list_tcp, request_p_cmp,
8567 +                                 struct request_p *, xid,
8568 +                                 ct->tuplehash[!dir].tuple.src.ip,
8569 +                                 ct->tuplehash[!dir].tuple.src.u.all);
8570 +
8571 +               /* Drop unexpected packets */
8572 +               if (!req_p) {
8573 +                       DEBUGP("packet is not expected. [skip]\n");
8574 +                       return NF_ACCEPT;
8575 +               }
8576 +
8577 +               /* Verifies if packet is really an RPC reply packet */
8578 +               data = data++;
8579 +               if (IXDR_GET_INT32(data) != 1) {
8580 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
8581 +                       return NF_ACCEPT;
8582 +               }
8583 +
8584 +               /* Is status accept? */
8585 +               data++;
8586 +               if (IXDR_GET_INT32(data)) {
8587 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
8588 +                       return NF_ACCEPT;
8589 +               }
8590 +
8591 +               /* Get Verifier length. Jump verifier */
8592 +               data++;
8593 +               data = data + IXDR_GET_INT32(data) + 2;
8594 +
8595 +               /* Is accpet status "success"? */
8596 +               if (IXDR_GET_INT32(data)) {
8597 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
8598 +                       return NF_ACCEPT;
8599 +               }
8600 +
8601 +               /* Get server port number */      
8602 +               data++;
8603 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
8604 +
8605 +               /* If a packet has made it this far then it deserves an
8606 +                * expectation ...  if port == 0, then this service is 
8607 +                * not going to be registered.
8608 +                */
8609 +               if (port_buf) {
8610 +                       DEBUGP("port found: %u\n", port_buf);
8611 +
8612 +                       memset(&expect, 0, sizeof(expect));
8613 +
8614 +                       /* Watch out, Radioactive-Man! */
8615 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
8616 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
8617 +                       exp->mask.src.ip = 0xffffffff;
8618 +                       exp->mask.dst.ip = 0xffffffff;
8619 +
8620 +                       switch (req_p->proto) {
8621 +                               case IPPROTO_UDP:
8622 +                                       exp->tuple.src.u.udp.port = 0;
8623 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
8624 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
8625 +                                       exp->mask.src.u.udp.port = 0;
8626 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
8627 +                                       exp->mask.dst.protonum = 0xffff;
8628 +                                       break;
8629 +
8630 +                               case IPPROTO_TCP:
8631 +                                       exp->tuple.src.u.tcp.port = 0;
8632 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
8633 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
8634 +                                       exp->mask.src.u.tcp.port = 0;
8635 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
8636 +                                       exp->mask.dst.protonum = 0xffff;
8637 +                                       break;
8638 +                       }
8639 +                       exp->expectfn = NULL;
8640 +
8641 +                       ip_conntrack_expect_related(ct, &expect);
8642 +
8643 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
8644 +                               NIPQUAD(exp->tuple.src.ip),
8645 +                               NIPQUAD(exp->tuple.dst.ip),
8646 +                               port_buf, req_p->proto);
8647 +
8648 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
8649 +                               NIPQUAD(exp->mask.src.ip),
8650 +                               NIPQUAD(exp->mask.dst.ip),
8651 +                               exp->mask.dst.protonum);
8652 +
8653 +               }
8654 +
8655 +               req_cl(req_p);
8656 +
8657 +               DEBUGP("packet evaluated. [expect]\n");
8658 +               return NF_ACCEPT;
8659 +       }
8660 +
8661 +       return NF_ACCEPT;
8662 +
8663 +}
8664 +
8665 +
8666 +/* RPC TCP helper */
8667 +static int help(const struct iphdr *iph, size_t len,
8668 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
8669 +{
8670 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
8671 +       const u_int32_t *data = (const u_int32_t *)tcph + tcph->doff;
8672 +       size_t tcplen = len - iph->ihl * 4;
8673 +
8674 +       int dir = CTINFO2DIR(ctinfo);
8675 +       int crp_ret;
8676 +
8677 +
8678 +       DEBUGP("new packet to evaluate ..\n");
8679 +
8680 +       /* This works for packets like handshake packets, ignore */
8681 +       if (len == ((tcph->doff + iph->ihl) * 4)) {
8682 +               DEBUGP("packet has no data (may still be handshaking). [skip]\n");
8683 +               return NF_ACCEPT;
8684 +       }
8685 +
8686 +       /* Until there's been traffic both ways, don't look in packets. */
8687 +       if (ctinfo != IP_CT_ESTABLISHED
8688 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
8689 +               DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
8690 +               DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
8691 +               DEBUGP("packet is not yet part of a two way stream. [skip]\n");
8692 +               return NF_ACCEPT;
8693 +       }
8694 +
8695 +       /* Not whole TCP header? */
8696 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
8697 +               DEBUGP("TCP header length is; tcplen=%u ..\n", (unsigned) tcplen);
8698 +               DEBUGP("packet does not contain a complete TCP header. [skip]\n");
8699 +               return NF_ACCEPT;
8700 +       }
8701 +
8702 +       /* FIXME: Source route IP option packets --RR */
8703 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
8704 +                        csum_partial((char *) tcph, tcplen, 0))) {
8705 +               DEBUGP("csum; %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
8706 +                    tcph, tcplen, NIPQUAD(iph->saddr),
8707 +                    NIPQUAD(iph->daddr));
8708 +               DEBUGP("[note: failure to get past this error may indicate source routing]\n");
8709 +               DEBUGP("packet contains a bad checksum. [skip]\n");
8710 +               return NF_ACCEPT;
8711 +       }
8712 +
8713 +       /* perform direction dependant protocol work */
8714 +       if (dir == IP_CT_DIR_ORIGINAL) {
8715 +
8716 +               DEBUGP("packet is from the initiator. [cont]\n");
8717 +
8718 +               /* Tests if packet len is ok */
8719 +               if ((tcplen - (tcph->doff * 4)) != 60) {
8720 +                       DEBUGP("packet length is not correct. [skip]\n");
8721 +                       return NF_ACCEPT;
8722 +               }
8723 +
8724 +       } else {
8725 +
8726 +               DEBUGP("packet is from the receiver. [cont]\n");
8727 +
8728 +               /* Tests if packet len is ok */
8729 +               if ((tcplen - (tcph->doff * 4)) != 32) {
8730 +                       DEBUGP("packet length is not correct. [skip]\n");
8731 +                       return NF_ACCEPT;
8732 +               }
8733 +       }
8734 +
8735 +       /* Get to the data */
8736 +       data++;
8737 +
8738 +       /* Check the RPC data */
8739 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
8740 +
8741 +       return crp_ret;
8742 +
8743 +}
8744 +
8745 +
8746 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
8747 +
8748 +static void fini(void);
8749 +
8750 +
8751 +static int __init init(void)
8752 +{
8753 +       int port, ret;
8754 +       static char name[10];
8755 +
8756 +
8757 +       /* If no port given, default to standard RPC port */
8758 +       if (ports[0] == 0)
8759 +               ports[0] = RPC_PORT;
8760 +
8761 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
8762 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
8763 +
8764 +                if (ports[port] == RPC_PORT)
8765 +                        sprintf(name, "rpc");
8766 +                else
8767 +                        sprintf(name, "rpc-%d", port);
8768 +
8769 +               rpc_helpers[port].name = name;
8770 +               rpc_helpers[port].me = THIS_MODULE;
8771 +               rpc_helpers[port].max_expected = 1;
8772 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
8773 +               rpc_helpers[port].timeout = 0;
8774 +
8775 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
8776 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
8777 +
8778 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
8779 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
8780 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
8781 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
8782 +
8783 +               rpc_helpers[port].help = help;
8784 +
8785 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
8786 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8787 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
8788 +                       ntohs(rpc_helpers[port].tuple.dst.u.tcp.port),
8789 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
8790 +                       ntohs(rpc_helpers[port].tuple.src.u.tcp.port));
8791 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
8792 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
8793 +                       ntohs(rpc_helpers[port].mask.dst.u.tcp.port),
8794 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
8795 +                       ntohs(rpc_helpers[port].mask.src.u.tcp.port));
8796 +
8797 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
8798 +
8799 +               if (ret) {
8800 +                       printk("ERROR registering port %d\n",
8801 +                               ports[port]);
8802 +                       fini();
8803 +                       return -EBUSY;
8804 +               }
8805 +               ports_n_c++;
8806 +       }
8807 +       return 0;
8808 +}
8809 +
8810 +
8811 +/* This function is intentionally _NOT_ defined as __exit, because 
8812 + * it is needed by the init function */
8813 +static void fini(void)
8814 +{
8815 +       int port;
8816 +
8817 +       DEBUGP("cleaning request list\n");
8818 +       clean_request(&request_p_list_tcp);
8819 +
8820 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
8821 +               DEBUGP("unregistering port %d\n", ports[port]);
8822 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
8823 +       }
8824 +}
8825 +
8826 +
8827 +module_init(init);
8828 +module_exit(fini);
8829 +
8830 +struct module *ip_conntrack_rpc_tcp = THIS_MODULE;
8831 +EXPORT_SYMBOL(request_p_list_tcp);
8832 +EXPORT_SYMBOL(ip_conntrack_rpc_tcp);
8833 +EXPORT_SYMBOL(ipct_rpc_tcp_lock);
8834 +
8835 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rpc_udp.c
8836 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rpc_udp.c  Thu Jan  1 00:00:00 1970
8837 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rpc_udp.c      Wed Sep 24 09:18:01 2003
8838 @@ -0,0 +1,503 @@
8839 +/* RPC extension for IP (UDP) connection tracking, Version 2.2
8840 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
8841 + *     - original rpc tracking module
8842 + *     - "recent" connection handling for kernel 2.3+ netfilter
8843 + *
8844 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8845 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
8846 + *
8847 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
8848 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
8849 + *     - extended matching to support filtering on procedures
8850 + *
8851 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
8852 + *
8853 + *     This program is free software; you can redistribute it and/or
8854 + *     modify it under the terms of the GNU General Public License
8855 + *     as published by the Free Software Foundation; either version
8856 + *     2 of the License, or (at your option) any later version.
8857 + **
8858 + *     Module load syntax:
8859 + *     insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
8860 + *
8861 + *     Please give the ports of all RPC servers you wish to connect to.
8862 + *     If you don't specify ports, the default will be port 111.
8863 + **
8864 + *     Note to all:
8865 + *
8866 + *     RPCs should not be exposed to the internet - ask the Pentagon;
8867 + *
8868 + *       "The unidentified crackers pleaded guilty in July to charges
8869 + *        of juvenile delinquency stemming from a string of Pentagon
8870 + *        network intrusions in February.
8871 + *
8872 + *        The youths, going by the names TooShort and Makaveli, used
8873 + *        a common server security hole to break in, according to
8874 + *        Dane Jasper, owner of the California Internet service
8875 + *        provider, Sonic. They used the hole, known as the 'statd'
8876 + *        exploit, to attempt more than 800 break-ins, Jasper said."
8877 + *
8878 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
8879 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
8880 + **
8881 + */
8882 +
8883 +#include <linux/module.h>
8884 +#include <linux/netfilter.h>
8885 +#include <linux/ip.h>
8886 +#include <net/checksum.h>
8887 +#include <net/udp.h>
8888 +
8889 +#include <asm/param.h>
8890 +#include <linux/sched.h>
8891 +#include <linux/timer.h>
8892 +#include <linux/stddef.h>
8893 +#include <linux/list.h>
8894 +
8895 +#include <linux/netfilter_ipv4/lockhelp.h>
8896 +#include <linux/netfilter_ipv4/ip_tables.h>
8897 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
8898 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
8899 +
8900 +#define MAX_PORTS 8
8901 +static int ports[MAX_PORTS];
8902 +static int ports_n_c = 0;
8903 +
8904 +#ifdef MODULE_PARM
8905 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8906 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8907 +#endif
8908 +
8909 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8910 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
8911 +MODULE_LICENSE("GPL");
8912 +
8913 +#if 0
8914 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
8915 +                                       format, ## args)
8916 +#else
8917 +#define DEBUGP(format, args...)
8918 +#endif
8919 +
8920 +DECLARE_RWLOCK(ipct_rpc_udp_lock);
8921 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock)
8922 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock)
8923 +#include <linux/netfilter_ipv4/listhelp.h>
8924 +
8925 +/* For future conections RPC, using client's cache bindings
8926 + * I'll use ip_conntrack_lock to lock these lists           */
8927 +
8928 +LIST_HEAD(request_p_list_udp);
8929 +
8930 +
8931 +static void delete_request_p(unsigned long request_p_ul)
8932 +{
8933 +       struct request_p *p = (void *)request_p_ul;
8934 +       
8935 +       WRITE_LOCK(&ipct_rpc_udp_lock);
8936 +       LIST_DELETE(&request_p_list_udp, p);
8937 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
8938 +       kfree(p);
8939 +       return;
8940 +}
8941 +
8942 +
8943 +static void req_cl(struct request_p * r)
8944 +{
8945 +       WRITE_LOCK(&ipct_rpc_udp_lock);
8946 +       del_timer(&r->timeout);
8947 +       LIST_DELETE(&request_p_list_udp, r);
8948 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
8949 +       kfree(r);
8950 +       return;
8951 +}
8952 +
8953 +
8954 +static void clean_request(struct list_head *list)
8955 +{
8956 +       struct list_head *first = list->prev;
8957 +       struct list_head *temp = list->next;
8958 +       struct list_head *aux;
8959 +
8960 +       if (list_empty(list))
8961 +               return;
8962 +
8963 +       while (first != temp) {
8964 +               aux = temp->next;
8965 +               req_cl((struct request_p *)temp);
8966 +               temp = aux;     
8967 +       }
8968 +       req_cl((struct request_p *)temp);
8969 +       return;
8970 +}
8971 +
8972 +
8973 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
8974 +                    u_int16_t port)
8975 +{
8976 +       struct request_p *req_p;
8977 +        
8978 +       /* Verifies if entry already exists */
8979 +       WRITE_LOCK(&ipct_rpc_udp_lock);
8980 +       req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
8981 +               struct request_p *, xid, ip, port);
8982 +
8983 +       if (req_p) {
8984 +               /* Refresh timeout */
8985 +               if (del_timer(&req_p->timeout)) {
8986 +                       req_p->timeout.expires = jiffies + EXP;
8987 +                       add_timer(&req_p->timeout);     
8988 +               } 
8989 +               WRITE_UNLOCK(&ipct_rpc_udp_lock);
8990 +               return; 
8991 +
8992 +       }
8993 +       WRITE_UNLOCK(&ipct_rpc_udp_lock);
8994 +       
8995 +       /* Allocate new request_p */
8996 +       req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
8997 +       if (!req_p) {
8998 +               DEBUGP("can't allocate request_p\n");
8999 +               return;                 
9000 +       }
9001 +       *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto, 
9002 +               { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
9003 +                       NULL }}); 
9004 +      
9005 +       /* Initialize timer */
9006 +       init_timer(&req_p->timeout);
9007 +       req_p->timeout.function = delete_request_p;
9008 +       add_timer(&req_p->timeout); 
9009 +
9010 +       /* Put in list */
9011 +       WRITE_LOCK(&ipct_rpc_udp_lock);
9012 +       list_prepend(&request_p_list_udp, req_p);
9013 +       WRITE_UNLOCK(&ipct_rpc_udp_lock); 
9014 +       return; 
9015 +
9016 +}
9017 +
9018 +
9019 +static int check_rpc_packet(const u_int32_t *data,
9020 +                       int dir, struct ip_conntrack *ct,
9021 +                       struct list_head request_p_list)
9022 +{
9023 +       struct request_p *req_p;
9024 +       u_int32_t xid;
9025 +       struct ip_conntrack_expect expect, *exp = &expect;
9026 +
9027 +       /* Translstion's buffer for XDR */
9028 +       u_int16_t port_buf;
9029 +
9030 +
9031 +       /* Get XID */
9032 +       xid = *data;
9033 +
9034 +       /* This does sanity checking on RPC payloads,
9035 +        * and permits only the RPC "get port" (3)
9036 +        * in authorised procedures in client
9037 +        * communications with the portmapper.
9038 +        */
9039 +
9040 +       /* perform direction dependant RPC work */
9041 +       if (dir == IP_CT_DIR_ORIGINAL) {
9042 +
9043 +               data += 5;
9044 +
9045 +               /* Get RPC requestor */
9046 +               if (IXDR_GET_INT32(data) != 3) {
9047 +                       DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
9048 +                       return NF_ACCEPT;
9049 +               }
9050 +               DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
9051 +
9052 +               data++;
9053 +
9054 +               /* Jump Credentials and Verfifier */
9055 +               data = data + IXDR_GET_INT32(data) + 2;
9056 +               data = data + IXDR_GET_INT32(data) + 2;
9057 +
9058 +               /* Get RPC procedure */
9059 +               DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
9060 +                       (unsigned int)IXDR_GET_INT32(data));
9061 +
9062 +               /* Get RPC protocol and store against client parameters */
9063 +               data = data + 2;
9064 +               alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
9065 +                               ct->tuplehash[dir].tuple.src.u.all);
9066 +
9067 +               DEBUGP("allocated RPC req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
9068 +                       xid, IXDR_GET_INT32(data),
9069 +                       NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
9070 +                       ntohs(ct->tuplehash[dir].tuple.src.u.all));
9071 +
9072 +               DEBUGP("allocated RPC request for protocol %u. [done]\n",
9073 +                       (unsigned int)IXDR_GET_INT32(data));
9074 +
9075 +       } else {
9076 +
9077 +               /* Check for returning packet's stored counterpart */
9078 +               req_p = LIST_FIND(&request_p_list_udp, request_p_cmp,
9079 +                                 struct request_p *, xid,
9080 +                                 ct->tuplehash[!dir].tuple.src.ip,
9081 +                                 ct->tuplehash[!dir].tuple.src.u.all);
9082 +
9083 +               /* Drop unexpected packets */
9084 +               if (!req_p) {
9085 +                       DEBUGP("packet is not expected. [skip]\n");
9086 +                       return NF_ACCEPT;
9087 +               }
9088 +
9089 +               /* Verifies if packet is really an RPC reply packet */
9090 +               data = data++;
9091 +               if (IXDR_GET_INT32(data) != 1) {
9092 +                       DEBUGP("packet is not a valid RPC reply. [skip]\n");
9093 +                       return NF_ACCEPT;
9094 +               }
9095 +
9096 +               /* Is status accept? */
9097 +               data++;
9098 +               if (IXDR_GET_INT32(data)) {
9099 +                       DEBUGP("packet is not an RPC accept. [skip]\n");
9100 +                       return NF_ACCEPT;
9101 +               }
9102 +
9103 +               /* Get Verifier length. Jump verifier */
9104 +               data++;
9105 +               data = data + IXDR_GET_INT32(data) + 2;
9106 +
9107 +               /* Is accpet status "success"? */
9108 +               if (IXDR_GET_INT32(data)) {
9109 +                       DEBUGP("packet is not an RPC accept status of success. [skip]\n");
9110 +                       return NF_ACCEPT;
9111 +               }
9112 +
9113 +               /* Get server port number */      
9114 +               data++;
9115 +               port_buf = (u_int16_t) IXDR_GET_INT32(data);
9116 +
9117 +               /* If a packet has made it this far then it deserves an
9118 +                * expectation ...  if port == 0, then this service is 
9119 +                * not going to be registered.
9120 +                */
9121 +               if (port_buf) {
9122 +                       DEBUGP("port found: %u\n", port_buf);
9123 +
9124 +                       memset(&expect, 0, sizeof(expect));
9125 +
9126 +                       /* Watch out, Radioactive-Man! */
9127 +                       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
9128 +                       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
9129 +                       exp->mask.src.ip = 0xffffffff;
9130 +                       exp->mask.dst.ip = 0xffffffff;
9131 +
9132 +                       switch (req_p->proto) {
9133 +                               case IPPROTO_UDP:
9134 +                                       exp->tuple.src.u.udp.port = 0;
9135 +                                       exp->tuple.dst.u.udp.port = htons(port_buf);
9136 +                                       exp->tuple.dst.protonum = IPPROTO_UDP;
9137 +                                       exp->mask.src.u.udp.port = 0;
9138 +                                       exp->mask.dst.u.udp.port = htons(0xffff);
9139 +                                       exp->mask.dst.protonum = 0xffff;
9140 +                                       break;
9141 +
9142 +                               case IPPROTO_TCP:
9143 +                                       exp->tuple.src.u.tcp.port = 0;
9144 +                                       exp->tuple.dst.u.tcp.port = htons(port_buf);
9145 +                                       exp->tuple.dst.protonum = IPPROTO_TCP;
9146 +                                       exp->mask.src.u.tcp.port = 0;
9147 +                                       exp->mask.dst.u.tcp.port = htons(0xffff);
9148 +                                       exp->mask.dst.protonum = 0xffff;
9149 +                                       break;
9150 +                       }
9151 +                       exp->expectfn = NULL;
9152 +
9153 +                       ip_conntrack_expect_related(ct, &expect);
9154 +
9155 +                       DEBUGP("expect related ip   %u.%u.%u.%u:0-%u.%u.%u.%u:%u proto=%u\n",
9156 +                               NIPQUAD(exp->tuple.src.ip),
9157 +                               NIPQUAD(exp->tuple.dst.ip),
9158 +                               port_buf, req_p->proto);
9159 +
9160 +                       DEBUGP("expect related mask %u.%u.%u.%u:0-%u.%u.%u.%u:65535 proto=%u\n",
9161 +                               NIPQUAD(exp->mask.src.ip),
9162 +                               NIPQUAD(exp->mask.dst.ip),
9163 +                               exp->mask.dst.protonum);
9164 +
9165 +               }
9166 +
9167 +               req_cl(req_p);
9168 +
9169 +               DEBUGP("packet evaluated. [expect]\n");
9170 +               return NF_ACCEPT;
9171 +       }
9172 +
9173 +       return NF_ACCEPT;
9174 +
9175 +}
9176 +
9177 +
9178 +/* RPC UDP helper */
9179 +static int help(const struct iphdr *iph, size_t len,
9180 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
9181 +{
9182 +       struct udphdr *udph = (void *) iph + iph->ihl * 4;
9183 +       const u_int32_t *data = (const u_int32_t *)udph + 2;
9184 +       size_t udplen = len - iph->ihl * 4;
9185 +       int dir = CTINFO2DIR(ctinfo);
9186 +       int crp_ret;
9187 +
9188 +       /* Checksum */
9189 +       const u_int16_t *chsm = (const u_int16_t *)udph + 3;
9190 +
9191 +
9192 +       DEBUGP("new packet to evaluate ..\n");
9193 +
9194 +       /* Not whole UDP header? */
9195 +       if (udplen < sizeof(struct udphdr)) {
9196 +               DEBUGP("UDP header length is; udplen=%u ..\n", (unsigned) udplen);
9197 +               DEBUGP("packet does not contain a complete UDP header. [skip]\n");
9198 +               return NF_ACCEPT;
9199 +       }
9200 +
9201 +       /* FIXME: Source route IP option packets --RR */
9202 +       if (*chsm) {
9203 +               if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
9204 +                   csum_partial((char *)udph, udplen, 0))) {
9205 +                       DEBUGP("[note: failure to get past this error may indicate source routing]\n");
9206 +                       DEBUGP("packet contains a bad checksum. [skip]\n");
9207 +                       return NF_ACCEPT;
9208 +                  } 
9209 +       }
9210 +
9211 +       /* perform direction dependant protocol work */
9212 +       if (dir == IP_CT_DIR_ORIGINAL) {
9213 +
9214 +               DEBUGP("packet is from the initiator. [cont]\n");
9215 +
9216 +               /* Tests if packet len is ok */
9217 +               if ((udplen - sizeof(struct udphdr)) != 56) {
9218 +                       DEBUGP("packet length is not correct. [skip]\n");
9219 +                       return NF_ACCEPT;
9220 +               }
9221 +
9222 +       } else {
9223 +
9224 +               DEBUGP("packet is from the receiver. [cont]\n");
9225 +
9226 +               /* Until there's been traffic both ways, don't look in packets. */
9227 +               if (ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
9228 +                       DEBUGP("connection tracking state is; ctinfo=%u ..\n", ctinfo);
9229 +                       DEBUGP("[note: failure to get past this error may indicate asymmetric routing]\n");
9230 +                       DEBUGP("packet is not yet part of a two way stream. [skip]\n");
9231 +                       return NF_ACCEPT;
9232 +               }
9233 +
9234 +               /* Tests if packet len is ok */
9235 +                       if ((udplen - sizeof(struct udphdr)) != 28) {
9236 +                       DEBUGP("packet length is not correct. [skip]\n");
9237 +                       return NF_ACCEPT;
9238 +               }
9239 +
9240 +       }
9241 +
9242 +       /* Get to the data */
9243 +       /* udp *data == *correct */
9244 +
9245 +       /* Check the RPC data */
9246 +       crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
9247 +
9248 +       return crp_ret;
9249 +
9250 +}
9251 +
9252 +
9253 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
9254 +
9255 +static void fini(void);
9256 +
9257 +
9258 +static int __init init(void)
9259 +{
9260 +       int port, ret;
9261 +       static char name[10];
9262 +
9263 +
9264 +       /* If no port given, default to standard RPC port */
9265 +       if (ports[0] == 0)
9266 +               ports[0] = RPC_PORT;
9267 +
9268 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9269 +               memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
9270 +
9271 +                if (ports[port] == RPC_PORT)
9272 +                        sprintf(name, "rpc");
9273 +                else
9274 +                        sprintf(name, "rpc-%d", port);
9275 +
9276 +               rpc_helpers[port].name = name;
9277 +               rpc_helpers[port].me = THIS_MODULE;
9278 +               rpc_helpers[port].max_expected = 1;
9279 +               rpc_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
9280 +               rpc_helpers[port].timeout = 0;
9281 +
9282 +               rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
9283 +               rpc_helpers[port].mask.dst.protonum = 0xffff;
9284 +
9285 +               /* RPC can come from ports 0:65535 to ports[port] (111) */
9286 +               rpc_helpers[port].tuple.src.u.udp.port = htons(ports[port]);
9287 +               rpc_helpers[port].mask.src.u.udp.port = htons(0xffff);
9288 +               rpc_helpers[port].mask.dst.u.udp.port = htons(0x0);
9289 +
9290 +               rpc_helpers[port].help = help;
9291 +
9292 +               DEBUGP("registering helper for port #%d: %d/UDP\n", port, ports[port]);
9293 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
9294 +                       NIPQUAD(rpc_helpers[port].tuple.dst.ip),
9295 +                       ntohs(rpc_helpers[port].tuple.dst.u.udp.port),
9296 +                       NIPQUAD(rpc_helpers[port].tuple.src.ip),
9297 +                       ntohs(rpc_helpers[port].tuple.src.u.udp.port));
9298 +               DEBUGP("helper match mask %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
9299 +                       NIPQUAD(rpc_helpers[port].mask.dst.ip),
9300 +                       ntohs(rpc_helpers[port].mask.dst.u.udp.port),
9301 +                       NIPQUAD(rpc_helpers[port].mask.src.ip),
9302 +                       ntohs(rpc_helpers[port].mask.src.u.udp.port));
9303 +
9304 +               ret = ip_conntrack_helper_register(&rpc_helpers[port]);
9305 +
9306 +               if (ret) {
9307 +                       printk("ERROR registering port %d\n",
9308 +                               ports[port]);
9309 +                       fini();
9310 +                       return -EBUSY;
9311 +               }
9312 +               ports_n_c++;
9313 +       }
9314 +       return 0;
9315 +}
9316 +
9317 +
9318 +/* This function is intentionally _NOT_ defined as __exit, because 
9319 + * it is needed by the init function */
9320 +static void fini(void)
9321 +{
9322 +       int port;
9323 +
9324 +       DEBUGP("cleaning request list\n");
9325 +       clean_request(&request_p_list_udp);
9326 +
9327 +       for (port = 0; (port < ports_n_c) && ports[port]; port++) {
9328 +               DEBUGP("unregistering port %d\n", ports[port]);
9329 +               ip_conntrack_helper_unregister(&rpc_helpers[port]);
9330 +       }
9331 +}
9332 +
9333 +
9334 +module_init(init);
9335 +module_exit(fini);
9336 +
9337 +struct module *ip_conntrack_rpc_udp = THIS_MODULE;
9338 +EXPORT_SYMBOL(request_p_list_udp);
9339 +EXPORT_SYMBOL(ip_conntrack_rpc_udp);
9340 +EXPORT_SYMBOL(ipct_rpc_udp_lock);
9341 +
9342 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rsh.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rsh.c
9343 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_rsh.c      Thu Jan  1 00:00:00 1970
9344 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_rsh.c  Wed Sep 24 09:18:03 2003
9345 @@ -0,0 +1,331 @@
9346 +/* RSH extension for IP connection tracking, Version 1.0
9347 + * (C) 2002 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
9348 + * based on HW's ip_conntrack_irc.c    
9349 + *
9350 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
9351 + *
9352 + *      This program is free software; you can redistribute it and/or
9353 + *      modify it under the terms of the GNU General Public License
9354 + *      as published by the Free Software Foundation; either version
9355 + *      2 of the License, or (at your option) any later version.
9356 + **
9357 + *     Module load syntax:
9358 + *     insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
9359 + *     
9360 + *     please give the ports of all RSH servers You wish to connect to.
9361 + *     If You don't specify ports, the default will be port 514
9362 + **
9363 + *      Note to all:
9364 + *        RSH blows ... you should use SSH (openssh.org) to replace it,
9365 + *        unfortunately I babysit some sysadmins that won't migrate
9366 + *       their legacy crap, in our second tier.
9367 + */
9368 +
9369 +
9370 +/*
9371 + *  Some docco ripped from the net to teach me all there is to know about
9372 + *  RSH, in 16.5 seconds (ie, all of the non-netfilter docco used to write
9373 + *  this module).
9374 + *
9375 + *  I have no idea what "unix rshd man pages" these guys have .. but that
9376 + *  is some pretty detailed docco!
9377 + **
9378 + *
9379 + *  4. Of the rsh protocol.
9380 + *  -----------------------
9381 + * 
9382 + *   The rshd listens on TCP port #514. The following info is from the unix
9383 + *   rshd man pages :
9384 + * 
9385 + *   "Service Request Protocol
9386 + * 
9387 + *    When the rshd daemon receives a service request, it initiates the
9388 + *    following protocol:
9389 + * 
9390 + *     1. The rshd daemon checks the source port number for the request.
9391 + *        If the port number is not in the range 0 through 1023, the rshd daemon
9392 + *        terminates the connection.
9393 + * 
9394 + *     2. The rshd daemon reads characters from the socket up to a null byte.
9395 + *        The string read is interpreted as an ASCII number (base 10). If this
9396 + *        number is nonzero, the rshd daemon interprets it as the port number
9397 + *        of a secondary stream to be used as standard error. A second connection
9398 + *        is created to the specified port on the client host. The source port
9399 + *        on the local host is in the range 0 through 1023.
9400 + * 
9401 + *     3. The rshd daemon uses the source address of the initial connection
9402 + *        request to determine the name of the client host. If the name cannot
9403 + *        be determined, the rshd daemon uses the dotted decimal representation
9404 + *        of the client host's address.
9405 + * 
9406 + *     4. The rshd daemon retrieves the following information from the initial
9407 + *        socket:
9408 + * 
9409 + *         * A null-terminated string of at most 16 bytes interpreted as
9410 + *           the user name of the user on the client host.
9411 + * 
9412 + *         * A null-terminated string of at most 16 bytes interpreted as
9413 + *           the user name to be used on the local server host.
9414 + * 
9415 + *         * Another null-terminated string interpreted as a command line
9416 + *           to be passed to a shell on the local server host.
9417 + * 
9418 + *     5. The rshd daemon attempts to validate the user using the following steps:
9419 + * 
9420 + *         a. The rshd daemon looks up the local user name in the /etc/passwd
9421 + *            file and tries to switch to the home directory (using the chdir
9422 + *            subroutine). If either the lookup or the directory change fails,
9423 + *            the rshd daemon terminates the connection.
9424 + * 
9425 + *         b. If the local user ID is a nonzero value, the rshd daemon searches
9426 + *            the /etc/hosts.equiv file to see if the name of the client
9427 + *            workstation is listed. If the client workstation is listed as an
9428 + *            equivalent host, the rshd daemon validates the user.
9429 + * 
9430 + *         c. If the $HOME/.rhosts file exists, the rshd daemon tries to
9431 + *            authenticate the user by checking the .rhosts file.
9432 + * 
9433 + *         d. If either the $HOME/.rhosts authentication fails or the
9434 + *            client host is not an equivalent host, the rshd daemon
9435 + *            terminates the connection.
9436 + * 
9437 + *     6. Once rshd validates the user, the rshd daemon returns a null byte
9438 + *        on the initial connection and passes the command line to the user's
9439 + *        local login shell. The shell then inherits the network connections
9440 + *        established by the rshd daemon."
9441 + * 
9442 + */
9443 +
9444 +
9445 +#include <linux/module.h>
9446 +#include <linux/netfilter.h>
9447 +#include <linux/ip.h>
9448 +#include <net/checksum.h>
9449 +#include <net/tcp.h>
9450 +
9451 +#include <linux/netfilter_ipv4/lockhelp.h>
9452 +#include <linux/netfilter_ipv4/ip_tables.h>
9453 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9454 +#include <linux/netfilter_ipv4/ip_conntrack_rsh.h>
9455 +
9456 +#define MAX_PORTS 8
9457 +static int ports[MAX_PORTS];
9458 +static int ports_n_c = 0;
9459 +
9460 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
9461 +MODULE_DESCRIPTION("RSH connection tracking module");
9462 +MODULE_LICENSE("GPL");
9463 +#ifdef MODULE_PARM
9464 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9465 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
9466 +#endif
9467 +
9468 +DECLARE_LOCK(ip_rsh_lock);
9469 +struct module *ip_conntrack_rsh = THIS_MODULE;
9470 +
9471 +#if 0
9472 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
9473 +                                       format, ## args)
9474 +#else
9475 +#define DEBUGP(format, args...)
9476 +#endif
9477 +
9478 +
9479 +
9480 +/* FIXME: This should be in userspace.  Later. */
9481 +static int help(const struct iphdr *iph, size_t len,
9482 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
9483 +{
9484 +       /* tcplen not negative guarenteed by ip_conntrack_tcp.c */
9485 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
9486 +       const char *data = (const char *) tcph + tcph->doff * 4;
9487 +       u_int32_t tcplen = len - iph->ihl * 4;
9488 +       int dir = CTINFO2DIR(ctinfo);
9489 +        struct ip_conntrack_expect expect, *exp = &expect;
9490 +        struct ip_ct_rsh_expect *exp_rsh_info = &exp->help.exp_rsh_info;
9491 +       u_int16_t port;
9492 +       int maxoctet;
9493 +
9494 +       /*  note that "maxoctet" is used to maintain sanity (8 was the
9495 +        *  original array size used in rshd/glibc) -- is there a
9496 +        *  vulnerability in rshd.c in the looped port *= 10?
9497 +        */
9498 +
9499 +
9500 +       DEBUGP("entered\n");
9501 +
9502 +       /* bail if packet is not from RSH client */
9503 +       if (dir == IP_CT_DIR_REPLY)
9504 +               return NF_ACCEPT;
9505 +
9506 +       /* Until there's been traffic both ways, don't look in packets. */
9507 +       if (ctinfo != IP_CT_ESTABLISHED
9508 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
9509 +               DEBUGP("Conntrackinfo = %u\n", ctinfo);
9510 +               return NF_ACCEPT;
9511 +       }
9512 +
9513 +       /* Not whole TCP header? */
9514 +       if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
9515 +               DEBUGP("tcplen = %u\n", (unsigned) tcplen);
9516 +               return NF_ACCEPT;
9517 +       }
9518 +
9519 +       /* Checksum invalid?  Ignore. */
9520 +       /* FIXME: Source route IP option packets --RR */
9521 +       if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
9522 +                        csum_partial((char *) tcph, tcplen, 0))) {
9523 +               DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
9524 +                    tcph, tcplen, NIPQUAD(iph->saddr),
9525 +                    NIPQUAD(iph->daddr));
9526 +               return NF_ACCEPT;
9527 +       }
9528 +
9529 +       /* find the rsh stderr port */
9530 +       maxoctet = 4;
9531 +       port = 0;
9532 +       for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
9533 +               if (*data < 0)
9534 +                       return(1);
9535 +               if (*data == 0)
9536 +                       break;
9537 +               if (*data < 48 || *data > 57) {
9538 +                       DEBUGP("these aren't the packets you're looking for ..\n");
9539 +                       return NF_ACCEPT;
9540 +               }
9541 +               port = port * 10 + ( *data - 48 );
9542 +       }
9543 +
9544 +       /* dont relate sessions that try to expose the client */
9545 +       DEBUGP("found port %u\n", port);
9546 +       if (port > 1023) {
9547 +               DEBUGP("skipping, expected port size is greater than 1023!\n");
9548 +               return NF_ACCEPT;
9549 +       }
9550 +
9551 +
9552 +       LOCK_BH(&ip_rsh_lock);
9553 +
9554 +       /*  new(,related) connection is;
9555 +        *          reply + dst (uint)port + src port (0:1023)
9556 +        */
9557 +       memset(&expect, 0, sizeof(expect));
9558 +
9559 +       /*  save some discovered data, in case someone ever wants to write
9560 +        *  a NAT module for this bastard ..
9561 +        */
9562 +       exp_rsh_info->port = port;
9563 +
9564 +       DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
9565 +
9566 +
9567 +       /* Watch out, Radioactive-Man! */
9568 +       exp->tuple.src.ip = ct->tuplehash[!dir].tuple.src.ip;
9569 +       exp->tuple.dst.ip = ct->tuplehash[!dir].tuple.dst.ip;
9570 +       exp->tuple.src.u.tcp.port = 0;
9571 +       exp->tuple.dst.u.tcp.port = htons(exp_rsh_info->port);
9572 +       exp->tuple.dst.protonum = IPPROTO_TCP;
9573 +
9574 +       exp->mask.src.ip = 0xffffffff;
9575 +       exp->mask.dst.ip = 0xffffffff;
9576 +
9577 +       exp->mask.src.u.tcp.port = htons(0xfc00);
9578 +       exp->mask.dst.u.tcp.port = htons(0xfc00);
9579 +       exp->mask.dst.protonum = 0xffff;
9580 +
9581 +       exp->expectfn = NULL;
9582 +
9583 +       ip_conntrack_expect_related(ct, &expect);
9584 +
9585 +       DEBUGP("expect related ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
9586 +               NIPQUAD(exp->tuple.src.ip),
9587 +               ntohs(exp->tuple.src.u.tcp.port),
9588 +               NIPQUAD(exp->tuple.dst.ip),
9589 +               ntohs(exp->tuple.dst.u.tcp.port));
9590 +
9591 +       DEBUGP("expect related mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
9592 +               NIPQUAD(exp->mask.src.ip),
9593 +               ntohs(exp->mask.src.u.tcp.port),
9594 +               NIPQUAD(exp->mask.dst.ip),
9595 +               ntohs(exp->mask.dst.u.tcp.port));
9596 +       UNLOCK_BH(&ip_rsh_lock);
9597 +
9598 +       return NF_ACCEPT;
9599 +}
9600 +
9601 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
9602 +
9603 +static void fini(void);
9604 +
9605 +static int __init init(void)
9606 +{
9607 +       int port, ret;
9608 +       static char name[10];
9609 +
9610 +
9611 +       /* If no port given, default to standard RSH port */
9612 +       if (ports[0] == 0)
9613 +               ports[0] = RSH_PORT;
9614 +
9615 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9616 +               memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
9617 +
9618 +                if (ports[port] == RSH_PORT)
9619 +                        sprintf(name, "rsh");
9620 +                else
9621 +                        sprintf(name, "rsh-%d", port);
9622 +
9623 +               rsh_helpers[port].name = name;
9624 +               rsh_helpers[port].me = THIS_MODULE;
9625 +               rsh_helpers[port].max_expected = 1;
9626 +               rsh_helpers[port].flags = IP_CT_HELPER_F_REUSE_EXPECT;
9627 +               rsh_helpers[port].timeout = 0;
9628 +
9629 +               rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
9630 +               rsh_helpers[port].mask.dst.protonum = 0xffff;
9631 +
9632 +               /* RSH must come from ports 0:1023 to ports[port] (514) */
9633 +               rsh_helpers[port].tuple.src.u.tcp.port = htons(ports[port]);
9634 +               rsh_helpers[port].mask.src.u.tcp.port = htons(0xfc00);
9635 +               rsh_helpers[port].mask.dst.u.tcp.port = htons(0xfc00);
9636 +
9637 +               rsh_helpers[port].help = help;
9638 +
9639 +               DEBUGP("registering helper for port #%d: %d/TCP\n", port, ports[port]);
9640 +               DEBUGP("helper match ip   %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
9641 +                       NIPQUAD(rsh_helpers[port].tuple.src.ip),
9642 +                       ntohs(rsh_helpers[port].tuple.src.u.tcp.port),
9643 +                       NIPQUAD(rsh_helpers[port].tuple.dst.ip),
9644 +                       ntohs(rsh_helpers[port].tuple.dst.u.tcp.port));
9645 +               DEBUGP("helper match mask %u.%u.%u.%u:%u-%u.%u.%u.%u:%u\n",
9646 +                       NIPQUAD(rsh_helpers[port].mask.src.ip),
9647 +                       ntohs(rsh_helpers[port].mask.src.u.tcp.port),
9648 +                       NIPQUAD(rsh_helpers[port].mask.dst.ip),
9649 +                       ntohs(rsh_helpers[port].mask.dst.u.tcp.port));
9650 +
9651 +               ret = ip_conntrack_helper_register(&rsh_helpers[port]);
9652 +
9653 +               if (ret) {
9654 +                       printk("ERROR registering port %d\n",
9655 +                               ports[port]);
9656 +                       fini();
9657 +                       return -EBUSY;
9658 +               }
9659 +               ports_n_c++;
9660 +       }
9661 +       return 0;
9662 +}
9663 +
9664 +/* This function is intentionally _NOT_ defined as __exit, because 
9665 + * it is needed by the init function */
9666 +static void fini(void)
9667 +{
9668 +       int port;
9669 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9670 +               DEBUGP("unregistering port %d\n", ports[port]);
9671 +               ip_conntrack_helper_unregister(&rsh_helpers[port]);
9672 +       }
9673 +}
9674 +
9675 +module_init(init);
9676 +module_exit(fini);
9677 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_standalone.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_standalone.c
9678 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_standalone.c       Thu Nov 28 23:53:15 2002
9679 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_standalone.c   Wed Sep 24 09:18:16 2003
9680 @@ -7,6 +7,7 @@
9681  /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
9682     Public Licence. */
9683  
9684 +#include <linux/config.h>
9685  #include <linux/types.h>
9686  #include <linux/ip.h>
9687  #include <linux/netfilter.h>
9688 @@ -16,6 +17,9 @@
9689  #include <linux/proc_fs.h>
9690  #include <linux/version.h>
9691  #include <linux/brlock.h>
9692 +#ifdef CONFIG_SYSCTL
9693 +#include <linux/sysctl.h>
9694 +#endif
9695  #include <net/checksum.h>
9696  
9697  #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
9698 @@ -77,7 +81,7 @@
9699  }
9700  
9701  static unsigned int
9702 -print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
9703 +print_conntrack(char *buffer, struct ip_conntrack *conntrack)
9704  {
9705         unsigned int len;
9706         struct ip_conntrack_protocol *proto
9707 @@ -95,15 +99,18 @@
9708         len += print_tuple(buffer + len,
9709                            &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
9710                            proto);
9711 -       if (!(conntrack->status & IPS_SEEN_REPLY))
9712 +       if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
9713                 len += sprintf(buffer + len, "[UNREPLIED] ");
9714         len += print_tuple(buffer + len,
9715                            &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
9716                            proto);
9717 -       if (conntrack->status & IPS_ASSURED)
9718 +       if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
9719                 len += sprintf(buffer + len, "[ASSURED] ");
9720         len += sprintf(buffer + len, "use=%u ",
9721                        atomic_read(&conntrack->ct_general.use));
9722 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
9723 +       len += sprintf(buffer + len, "mark=%ld ", conntrack->mark);
9724 +#endif
9725         len += sprintf(buffer + len, "\n");
9726  
9727         return len;
9728 @@ -239,6 +246,98 @@
9729  static struct nf_hook_ops ip_conntrack_local_in_ops
9730  = { { NULL, NULL }, ip_confirm, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_LAST-1 };
9731  
9732 +/* Sysctl support */
9733 +
9734 +#ifdef CONFIG_SYSCTL
9735 +
9736 +/* From ip_conntrack_core.c */
9737 +extern int ip_conntrack_max;
9738 +
9739 +/* From ip_conntrack_proto_tcp.c */
9740 +extern unsigned long ip_ct_tcp_timeout_syn_sent;
9741 +extern unsigned long ip_ct_tcp_timeout_syn_recv;
9742 +extern unsigned long ip_ct_tcp_timeout_established;
9743 +extern unsigned long ip_ct_tcp_timeout_fin_wait;
9744 +extern unsigned long ip_ct_tcp_timeout_close_wait;
9745 +extern unsigned long ip_ct_tcp_timeout_last_ack;
9746 +extern unsigned long ip_ct_tcp_timeout_time_wait;
9747 +extern unsigned long ip_ct_tcp_timeout_close;
9748 +
9749 +/* From ip_conntrack_proto_udp.c */
9750 +extern unsigned long ip_ct_udp_timeout;
9751 +extern unsigned long ip_ct_udp_timeout_stream;
9752 +
9753 +/* From ip_conntrack_proto_icmp.c */
9754 +extern unsigned long ip_ct_icmp_timeout;
9755 +
9756 +/* From ip_conntrack_proto_icmp.c */
9757 +extern unsigned long ip_ct_generic_timeout;
9758 +
9759 +static struct ctl_table_header *ip_ct_sysctl_header;
9760 +
9761 +static ctl_table ip_ct_sysctl_table[] = {
9762 +       {NET_IPV4_NF_CONNTRACK_MAX, "ip_conntrack_max",
9763 +        &ip_conntrack_max, sizeof(int), 0644, NULL,
9764 +        &proc_dointvec},
9765 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_SENT, "ip_conntrack_tcp_timeout_syn_sent",
9766 +        &ip_ct_tcp_timeout_syn_sent, sizeof(unsigned int), 0644, NULL,
9767 +        &proc_dointvec_jiffies},
9768 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_SYN_RECV, "ip_conntrack_tcp_timeout_syn_recv",
9769 +        &ip_ct_tcp_timeout_syn_recv, sizeof(unsigned int), 0644, NULL,
9770 +        &proc_dointvec_jiffies},
9771 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_ESTABLISHED, "ip_conntrack_tcp_timeout_established",
9772 +        &ip_ct_tcp_timeout_established, sizeof(unsigned int), 0644, NULL,
9773 +        &proc_dointvec_jiffies},
9774 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_FIN_WAIT, "ip_conntrack_tcp_timeout_fin_wait",
9775 +        &ip_ct_tcp_timeout_fin_wait, sizeof(unsigned int), 0644, NULL,
9776 +        &proc_dointvec_jiffies},
9777 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE_WAIT, "ip_conntrack_tcp_timeout_close_wait",
9778 +        &ip_ct_tcp_timeout_close_wait, sizeof(unsigned int), 0644, NULL,
9779 +        &proc_dointvec_jiffies},
9780 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_LAST_ACK, "ip_conntrack_tcp_timeout_last_ack",
9781 +        &ip_ct_tcp_timeout_last_ack, sizeof(unsigned int), 0644, NULL,
9782 +        &proc_dointvec_jiffies},
9783 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_TIME_WAIT, "ip_conntrack_tcp_timeout_time_wait",
9784 +        &ip_ct_tcp_timeout_time_wait, sizeof(unsigned int), 0644, NULL,
9785 +        &proc_dointvec_jiffies},
9786 +       {NET_IPV4_NF_CONNTRACK_TCP_TIMEOUT_CLOSE, "ip_conntrack_tcp_timeout_close",
9787 +        &ip_ct_tcp_timeout_close, sizeof(unsigned int), 0644, NULL,
9788 +        &proc_dointvec_jiffies},
9789 +       {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT, "ip_conntrack_udp_timeout",
9790 +        &ip_ct_udp_timeout, sizeof(unsigned int), 0644, NULL,
9791 +        &proc_dointvec_jiffies},
9792 +       {NET_IPV4_NF_CONNTRACK_UDP_TIMEOUT_STREAM, "ip_conntrack_udp_timeout_stream",
9793 +        &ip_ct_udp_timeout_stream, sizeof(unsigned int), 0644, NULL,
9794 +        &proc_dointvec_jiffies},
9795 +       {NET_IPV4_NF_CONNTRACK_ICMP_TIMEOUT, "ip_conntrack_icmp_timeout",
9796 +        &ip_ct_icmp_timeout, sizeof(unsigned int), 0644, NULL,
9797 +        &proc_dointvec_jiffies},
9798 +       {NET_IPV4_NF_CONNTRACK_GENERIC_TIMEOUT, "ip_conntrack_generic_timeout",
9799 +        &ip_ct_generic_timeout, sizeof(unsigned int), 0644, NULL,
9800 +        &proc_dointvec_jiffies},
9801 +       {0}
9802 +};
9803 +
9804 +#define NET_IP_CONNTRACK_MAX 2089
9805 +
9806 +static ctl_table ip_ct_netfilter_table[] = {
9807 +       {NET_IPV4_NETFILTER, "netfilter", NULL, 0, 0555, ip_ct_sysctl_table, 0, 0, 0, 0, 0},
9808 +       {NET_IP_CONNTRACK_MAX, "ip_conntrack_max",
9809 +        &ip_conntrack_max, sizeof(int), 0644, NULL,
9810 +        &proc_dointvec},
9811 +       {0}
9812 +};
9813 +
9814 +static ctl_table ip_ct_ipv4_table[] = {
9815 +       {NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
9816 +       {0}
9817 +};
9818 +
9819 +static ctl_table ip_ct_net_table[] = {
9820 +       {CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
9821 +       {0}
9822 +};
9823 +#endif
9824  static int init_or_cleanup(int init)
9825  {
9826         struct proc_dir_entry *proc;
9827 @@ -274,10 +373,20 @@
9828                 printk("ip_conntrack: can't register local in hook.\n");
9829                 goto cleanup_inoutandlocalops;
9830         }
9831 +#ifdef CONFIG_SYSCTL
9832 +       ip_ct_sysctl_header = register_sysctl_table(ip_ct_net_table, 0);
9833 +       if (ip_ct_sysctl_header == NULL) {
9834 +               printk("ip_conntrack: can't register to sysctl.\n");
9835 +               goto cleanup;
9836 +       }
9837 +#endif
9838  
9839         return ret;
9840  
9841   cleanup:
9842 +#ifdef CONFIG_SYSCTL
9843 +       unregister_sysctl_table(ip_ct_sysctl_header);
9844 +#endif
9845         nf_unregister_hook(&ip_conntrack_local_in_ops);
9846   cleanup_inoutandlocalops:
9847         nf_unregister_hook(&ip_conntrack_out_ops);
9848 @@ -293,13 +402,20 @@
9849         return ret;
9850  }
9851  
9852 -/* FIXME: Allow NULL functions and sub in pointers to generic for
9853 -   them. --RR */
9854 +/**
9855 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
9856 + * @proto: structure describing this layer 4 protocol helper
9857 + *
9858 + * This function is called by layer 4 protocol helpers to register 
9859 + * themselves with the conntrack core.
9860 + */
9861  int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
9862  {
9863         int ret = 0;
9864         struct list_head *i;
9865  
9866 +       /* FIXME: Allow NULL functions and sub in pointers to generic for
9867 +          them. --RR */
9868         WRITE_LOCK(&ip_conntrack_lock);
9869         for (i = protocol_list.next; i != &protocol_list; i = i->next) {
9870                 if (((struct ip_conntrack_protocol *)i)->proto
9871 @@ -317,12 +433,20 @@
9872         return ret;
9873  }
9874  
9875 +/**
9876 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
9877 + * @proto: structure describing this layer 4 protocol helper
9878 + *
9879 + * This function is called byh layer 4 protocol helpers to unregister
9880 + * themselvers from the conntrack core.  Please note that all conntrack
9881 + * entries for this protocol are deleted from the conntrack hash table.
9882 + */
9883  void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
9884  {
9885         WRITE_LOCK(&ip_conntrack_lock);
9886  
9887 -       /* ip_ct_find_proto() returns proto_generic in case there is no protocol 
9888 -        * helper. So this should be enough - HW */
9889 +       /* ip_ct_find_proto() returns proto_generic in case there is no
9890 +        * protocol helper. So this should be enough - HW */
9891         LIST_DELETE(&protocol_list, proto);
9892         WRITE_UNLOCK(&ip_conntrack_lock);
9893         
9894 @@ -355,11 +479,13 @@
9895  EXPORT_SYMBOL(ip_conntrack_alter_reply);
9896  EXPORT_SYMBOL(ip_conntrack_destroyed);
9897  EXPORT_SYMBOL(ip_conntrack_get);
9898 +EXPORT_SYMBOL(ip_conntrack_get_tuple);
9899  EXPORT_SYMBOL(ip_conntrack_module);
9900  EXPORT_SYMBOL(ip_conntrack_helper_register);
9901  EXPORT_SYMBOL(ip_conntrack_helper_unregister);
9902  EXPORT_SYMBOL(ip_ct_selective_cleanup);
9903  EXPORT_SYMBOL(ip_ct_refresh);
9904 +EXPORT_SYMBOL(ip_ct_death_by_timeout);
9905  EXPORT_SYMBOL(ip_ct_find_proto);
9906  EXPORT_SYMBOL(__ip_ct_find_proto);
9907  EXPORT_SYMBOL(ip_ct_find_helper);
9908 @@ -374,5 +500,6 @@
9909  EXPORT_SYMBOL(ip_conntrack_expect_list);
9910  EXPORT_SYMBOL(ip_conntrack_lock);
9911  EXPORT_SYMBOL(ip_conntrack_hash);
9912 +EXPORT_SYMBOL(ip_conntrack_untracked);
9913  EXPORT_SYMBOL_GPL(ip_conntrack_find_get);
9914  EXPORT_SYMBOL_GPL(ip_conntrack_put);
9915 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_talk.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_talk.c
9916 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_talk.c     Thu Jan  1 00:00:00 1970
9917 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_talk.c Wed Sep 24 09:18:08 2003
9918 @@ -0,0 +1,360 @@
9919 +/* 
9920 + * talk extension for IP connection tracking. 
9921 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
9922 + *
9923 + *      This program is free software; you can redistribute it and/or
9924 + *      modify it under the terms of the GNU General Public License
9925 + *      as published by the Free Software Foundation; either version
9926 + *      2 of the License, or (at your option) any later version.
9927 + **
9928 + *     Module load syntax:
9929 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
9930 + *
9931 + *             talk=[0|1]      disable|enable old talk support
9932 + *            ntalk=[0|1]      disable|enable ntalk support
9933 + *           ntalk2=[0|1]      disable|enable ntalk2 support
9934 + *
9935 + *     The default is talk=1 ntalk=1 ntalk2=1
9936 + *
9937 + *     The helper does not support simultaneous talk requests.
9938 + **
9939 + *
9940 + *             ASCII art on talk protocols
9941 + *     
9942 + *     
9943 + *     caller server               callee server
9944 + *             |     \           /
9945 + *             |       \       /
9946 + *             |         \   /
9947 + *             |           /  
9948 + *             |         /   \
9949 + *           2 |     1 /       \ 3
9950 + *     caller client  ----------- callee client
9951 + *                              4
9952 + *
9953 + *     1. caller client <-> callee server: LOOK_UP, then ANNOUNCE invitation 
9954 + *    ( 2. caller client <-> caller server: LEAVE_INVITE to server )
9955 + *     3. callee client <-> caller server: LOOK_UP invitation
9956 + *     4. callee client <-> caller client: talk data channel
9957 + *
9958 + * [1]: M. Hunter, talk: a historical protocol for interactive communication
9959 + *      draft-hunter-talk-00.txt
9960 + * [2]: D.B. Chapman, E.D. Zwicky: Building Internet Firewalls (O'Reilly)      
9961 + */
9962 +#include <linux/config.h>
9963 +#include <linux/module.h>
9964 +#include <linux/netfilter.h>
9965 +#include <linux/ip.h>
9966 +#include <net/checksum.h>
9967 +#include <net/udp.h>
9968 +
9969 +#include <linux/netfilter_ipv4/lockhelp.h>
9970 +#include <linux/netfilter_ipv4/ip_conntrack.h>
9971 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
9972 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
9973 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
9974 +
9975 +/* Default all talk protocols are supported */
9976 +static int talk = 1;
9977 +static int ntalk = 1;
9978 +static int ntalk2 = 1;
9979 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
9980 +MODULE_DESCRIPTION("talk connection tracking module");
9981 +MODULE_LICENSE("GPL");
9982 +#ifdef MODULE_PARM
9983 +MODULE_PARM(talk, "i");
9984 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
9985 +MODULE_PARM(ntalk, "i");
9986 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
9987 +MODULE_PARM(ntalk2, "i");
9988 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
9989 +#endif
9990 +
9991 +DECLARE_LOCK(ip_talk_lock);
9992 +struct module *ip_conntrack_talk = THIS_MODULE;
9993 +
9994 +#if 0
9995 +#define DEBUGP printk
9996 +#else
9997 +#define DEBUGP(format, args...)
9998 +#endif
9999 +
10000 +static int talk_expect(struct ip_conntrack *ct);
10001 +static int ntalk_expect(struct ip_conntrack *ct);
10002 +
10003 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
10004 +
10005 +static int talk_help_response(const struct iphdr *iph, size_t len,
10006 +                             struct ip_conntrack *ct,
10007 +                             enum ip_conntrack_info ctinfo,
10008 +                             int talk_port,
10009 +                             u_char mode,
10010 +                             u_char type,
10011 +                             u_char answer,
10012 +                             struct talk_addr *addr)
10013 +{
10014 +       int dir = CTINFO2DIR(ctinfo);
10015 +       struct ip_conntrack_expect expect, *exp = &expect;
10016 +       struct ip_ct_talk_expect *exp_talk_info = &exp->help.exp_talk_info;
10017 +
10018 +       DEBUGP("ip_ct_talk_help_response: %u.%u.%u.%u:%u, type %d answer %d\n",
10019 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
10020 +               type, answer);
10021 +
10022 +       if (!(answer == SUCCESS && type == mode))
10023 +               return NF_ACCEPT;
10024 +       
10025 +       memset(&expect, 0, sizeof(expect));
10026 +       
10027 +       if (type == ANNOUNCE) {
10028 +
10029 +               DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
10030 +
10031 +               /* update the talk info */
10032 +               LOCK_BH(&ip_talk_lock);
10033 +               exp_talk_info->port = htons(talk_port);
10034 +
10035 +               /* expect callee client -> caller server message */
10036 +               exp->tuple = ((struct ip_conntrack_tuple)
10037 +                       { { ct->tuplehash[dir].tuple.src.ip,
10038 +                           { 0 } },
10039 +                         { ct->tuplehash[dir].tuple.dst.ip,
10040 +                           { .tcp = { htons(talk_port) } },
10041 +                           IPPROTO_UDP }});
10042 +               exp->mask = ((struct ip_conntrack_tuple)
10043 +                       { { 0xFFFFFFFF, { 0 } },
10044 +                         { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
10045 +               
10046 +               exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
10047 +
10048 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller daemon %u.%u.%u.%u:%u!\n",
10049 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.udp.port),
10050 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.udp.port));
10051 +
10052 +               /* Ignore failure; should only happen with NAT */
10053 +               ip_conntrack_expect_related(ct, &expect);
10054 +               UNLOCK_BH(&ip_talk_lock);
10055 +       }
10056 +       if (type == LOOK_UP) {
10057 +
10058 +               DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
10059 +
10060 +               /* update the talk info */
10061 +               LOCK_BH(&ip_talk_lock);
10062 +               exp_talk_info->port = addr->ta_port;
10063 +
10064 +               /* expect callee client -> caller client connection */
10065 +               exp->tuple = ((struct ip_conntrack_tuple)
10066 +                       { { ct->tuplehash[!dir].tuple.src.ip,
10067 +                           { 0 } },
10068 +                         { addr->ta_addr,
10069 +                           { addr->ta_port },
10070 +                           IPPROTO_TCP }});
10071 +               exp->mask = ((struct ip_conntrack_tuple)
10072 +                       { { 0xFFFFFFFF, { 0 } },
10073 +                         { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
10074 +               
10075 +               exp->expectfn = NULL;
10076 +               
10077 +               DEBUGP("ip_ct_talk_help_response: callee client %u.%u.%u.%u:%u -> caller client %u.%u.%u.%u:%u!\n",
10078 +                      NIPQUAD(exp->tuple.src.ip), ntohs(exp->tuple.src.u.tcp.port),
10079 +                      NIPQUAD(exp->tuple.dst.ip), ntohs(exp->tuple.dst.u.tcp.port));
10080 +
10081 +               /* Ignore failure; should only happen with NAT */
10082 +               ip_conntrack_expect_related(ct, &expect);
10083 +               UNLOCK_BH(&ip_talk_lock);
10084 +       }
10085 +                   
10086 +       return NF_ACCEPT;
10087 +}
10088 +
10089 +/* FIXME: This should be in userspace.  Later. */
10090 +static int talk_help(const struct iphdr *iph, size_t len,
10091 +                    struct ip_conntrack *ct,
10092 +                    enum ip_conntrack_info ctinfo,
10093 +                    int talk_port,
10094 +                    u_char mode)
10095 +{
10096 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10097 +       const char *data = (const char *)udph + sizeof(struct udphdr);
10098 +       int dir = CTINFO2DIR(ctinfo);
10099 +       size_t udplen;
10100 +
10101 +       DEBUGP("ip_ct_talk_help: help entered\n");
10102 +
10103 +       /* Until there's been traffic both ways, don't look in packets. */
10104 +       if (ctinfo != IP_CT_ESTABLISHED
10105 +           && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) {
10106 +               DEBUGP("ip_ct_talk_help: Conntrackinfo = %u\n", ctinfo);
10107 +               return NF_ACCEPT;
10108 +       }
10109 +
10110 +       /* Not whole UDP header? */
10111 +       udplen = len - iph->ihl * 4;
10112 +       if (udplen < sizeof(struct udphdr)) {
10113 +               DEBUGP("ip_ct_talk_help: too short for udph, udplen = %u\n", (unsigned)udplen);
10114 +               return NF_ACCEPT;
10115 +       }
10116 +
10117 +       /* Checksum invalid?  Ignore. */
10118 +       /* FIXME: Source route IP option packets --RR */
10119 +       if (csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
10120 +                             csum_partial((char *)udph, udplen, 0))) {
10121 +               DEBUGP("ip_ct_talk_help: bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n",
10122 +                      udph, udplen, NIPQUAD(iph->saddr),
10123 +                      NIPQUAD(iph->daddr));
10124 +               return NF_ACCEPT;
10125 +       }
10126 +       
10127 +       DEBUGP("ip_ct_talk_help: %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
10128 +               NIPQUAD(iph->saddr), ntohs(udph->source), NIPQUAD(iph->daddr), ntohs(udph->dest));
10129 +
10130 +       if (dir == IP_CT_DIR_ORIGINAL)
10131 +               return NF_ACCEPT;
10132 +               
10133 +       if (talk_port == TALK_PORT
10134 +           && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
10135 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
10136 +                                         ((struct talk_response *)data)->type, 
10137 +                                         ((struct talk_response *)data)->answer,
10138 +                                         &(((struct talk_response *)data)->addr));
10139 +       else if (talk_port == NTALK_PORT
10140 +                 && ntalk
10141 +                 && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
10142 +                 && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
10143 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
10144 +                                         ((struct ntalk_response *)data)->type, 
10145 +                                         ((struct ntalk_response *)data)->answer,
10146 +                                         &(((struct ntalk_response *)data)->addr));
10147 +       else if (talk_port == NTALK_PORT
10148 +                && ntalk2
10149 +                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
10150 +                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
10151 +               return talk_help_response(iph, len, ct, ctinfo, talk_port, mode,
10152 +                                         ((struct ntalk2_response *)data)->type, 
10153 +                                         ((struct ntalk2_response *)data)->answer,
10154 +                                         &(((struct ntalk2_response *)data)->addr));
10155 +       else {
10156 +               DEBUGP("ip_ct_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
10157 +                      (unsigned)udplen - sizeof(struct udphdr), 
10158 +                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
10159 +               return NF_ACCEPT;
10160 +       }
10161 +}
10162 +
10163 +static int lookup_help(const struct iphdr *iph, size_t len,
10164 +                      struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10165 +{
10166 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
10167 +}
10168 +
10169 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
10170 +                       struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10171 +{
10172 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
10173 +}
10174 +
10175 +static struct ip_conntrack_helper lookup_helpers[2] = 
10176 +       { { { NULL, NULL },
10177 +           "talk",                                     /* name */
10178 +           0,                                          /* flags */
10179 +           NULL,                                       /* module */
10180 +           1,                                          /* max_expected */
10181 +           240,                                        /* timeout */
10182 +            { { 0, { __constant_htons(TALK_PORT) } },  /* tuple */
10183 +             { 0, { 0 }, IPPROTO_UDP } },
10184 +           { { 0, { 0xFFFF } },                        /* mask */
10185 +             { 0, { 0 }, 0xFFFF } },
10186 +           lookup_help },                              /* helper */
10187 +          { { NULL, NULL },
10188 +            "ntalk",                                   /* name */
10189 +           0,                                          /* flags */
10190 +           NULL,                                       /* module */
10191 +           1,                                          /* max_expected */
10192 +           240,                                        /* timeout */
10193 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
10194 +             { 0, { 0 }, IPPROTO_UDP } },
10195 +           { { 0, { 0xFFFF } },                        /* mask */
10196 +             { 0, { 0 }, 0xFFFF } },
10197 +           lookup_nhelp }                              /* helper */
10198 +        };
10199 +
10200 +static int talk_expect(struct ip_conntrack *ct)
10201 +{
10202 +       DEBUGP("ip_conntrack_talk: calling talk_expectfn for ct %p\n", ct);
10203 +       WRITE_LOCK(&ip_conntrack_lock);
10204 +       ct->helper = &lookup_helpers[0];
10205 +       WRITE_UNLOCK(&ip_conntrack_lock);
10206 +        
10207 +       return NF_ACCEPT;       /* unused */
10208 +}
10209 +
10210 +static int ntalk_expect(struct ip_conntrack *ct)
10211 +{
10212 +       DEBUGP("ip_conntrack_talk: calling ntalk_expectfn for ct %p\n", ct);
10213 +       WRITE_LOCK(&ip_conntrack_lock);
10214 +       ct->helper = &lookup_helpers[1];
10215 +       WRITE_UNLOCK(&ip_conntrack_lock);
10216 +        
10217 +       return NF_ACCEPT;       /* unused */
10218 +}
10219 +
10220 +static int help(const struct iphdr *iph, size_t len,
10221 +               struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10222 +{
10223 +       return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
10224 +}
10225 +
10226 +static int nhelp(const struct iphdr *iph, size_t len,
10227 +                struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10228 +{
10229 +       return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
10230 +}
10231 +
10232 +static struct ip_conntrack_helper talk_helpers[2] = 
10233 +       { { { NULL, NULL },
10234 +           "talk",                                     /* name */
10235 +           0,                                          /* flags */
10236 +           THIS_MODULE,                                /* module */
10237 +           1,                                          /* max_expected */
10238 +           240,                                        /* timeout */
10239 +           { { 0, { __constant_htons(TALK_PORT) } },   /* tuple */
10240 +             { 0, { 0 }, IPPROTO_UDP } },
10241 +           { { 0, { 0xFFFF } },                        /* mask */
10242 +             { 0, { 0 }, 0xFFFF } },
10243 +           help },                                     /* helper */
10244 +          { { NULL, NULL },
10245 +           "ntalk",                                    /* name */
10246 +           0,                                          /* flags */
10247 +           THIS_MODULE,                                /* module */
10248 +           1,                                          /* max_expected */
10249 +           240,                                        /* timeout */
10250 +           { { 0, { __constant_htons(NTALK_PORT) } },  /* tuple */
10251 +             { 0, { 0 }, IPPROTO_UDP } },
10252 +           { { 0, { 0xFFFF } },                        /* mask */
10253 +             { 0, { 0 }, 0xFFFF } },
10254 +           nhelp }                                     /* helper */
10255 +       };
10256 +
10257 +static int __init init(void)
10258 +{
10259 +       if (talk > 0)
10260 +               ip_conntrack_helper_register(&talk_helpers[0]);
10261 +       if (ntalk > 0 || ntalk2 > 0)
10262 +               ip_conntrack_helper_register(&talk_helpers[1]);
10263 +               
10264 +       return 0;
10265 +}
10266 +
10267 +static void __exit fini(void)
10268 +{
10269 +       if (talk > 0)
10270 +               ip_conntrack_helper_unregister(&talk_helpers[0]);
10271 +       if (ntalk > 0 || ntalk2 > 0)
10272 +               ip_conntrack_helper_unregister(&talk_helpers[1]);
10273 +}
10274 +
10275 +EXPORT_SYMBOL(ip_talk_lock);
10276 +
10277 +module_init(init);
10278 +module_exit(fini);
10279 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_tftp.c linux-2.4.20/net/ipv4/netfilter/ip_conntrack_tftp.c
10280 --- linux-2.4.20.org/net/ipv4/netfilter/ip_conntrack_tftp.c     Thu Jan  1 00:00:00 1970
10281 +++ linux-2.4.20/net/ipv4/netfilter/ip_conntrack_tftp.c Wed Sep 24 09:16:24 2003
10282 @@ -0,0 +1,129 @@
10283 +/*
10284 + * Licensed under GNU GPL version 2 Copyright Magnus Boden <mb@ozaba.mine.nu>
10285 + * Version: 0.0.7
10286 + *
10287 + * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
10288 + *     - port to newnat API
10289 + *
10290 + */
10291 +
10292 +#include <linux/module.h>
10293 +#include <linux/ip.h>
10294 +#include <linux/udp.h>
10295 +
10296 +#include <linux/netfilter.h>
10297 +#include <linux/netfilter_ipv4/ip_tables.h>
10298 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10299 +#include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
10300 +
10301 +MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
10302 +MODULE_DESCRIPTION("Netfilter connection tracking module for tftp");
10303 +MODULE_LICENSE("GPL");
10304 +
10305 +#define MAX_PORTS 8
10306 +static int ports[MAX_PORTS];
10307 +static int ports_c = 0;
10308 +#ifdef MODULE_PARM
10309 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
10310 +MODULE_PARM_DESC(ports, "port numbers of tftp servers");
10311 +#endif
10312 +
10313 +#if 0
10314 +#define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ": " \
10315 +                                      format, ## args)
10316 +#else
10317 +#define DEBUGP(format, args...)
10318 +#endif
10319 +
10320 +static int tftp_help(const struct iphdr *iph, size_t len,
10321 +       struct ip_conntrack *ct,
10322 +       enum ip_conntrack_info ctinfo)
10323 +{
10324 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
10325 +       struct tftphdr *tftph = (void *)udph + 8;
10326 +       struct ip_conntrack_expect exp;
10327 +       
10328 +       switch (ntohs(tftph->opcode)) {
10329 +       /* RRQ and WRQ works the same way */
10330 +       case TFTP_OPCODE_READ:
10331 +       case TFTP_OPCODE_WRITE:
10332 +               DEBUGP("");
10333 +               DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
10334 +               DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
10335 +               memset(&exp, 0, sizeof(exp));
10336 +
10337 +               exp.tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
10338 +               exp.mask.src.ip = 0xffffffff;
10339 +               exp.mask.dst.ip = 0xffffffff;
10340 +               exp.mask.dst.u.udp.port = 0xffff;
10341 +               exp.mask.dst.protonum = 0xffff;
10342 +               exp.expectfn = NULL;
10343 +
10344 +               DEBUGP("expect: ");
10345 +               DUMP_TUPLE(&exp.tuple);
10346 +               DUMP_TUPLE(&exp.mask);
10347 +               ip_conntrack_expect_related(ct, &exp);
10348 +               break;
10349 +       default:
10350 +               DEBUGP("Unknown opcode\n");
10351 +       }
10352 +       return NF_ACCEPT;
10353 +}
10354 +
10355 +static struct ip_conntrack_helper tftp[MAX_PORTS];
10356 +static char tftp_names[MAX_PORTS][10];
10357 +
10358 +static void fini(void)
10359 +{
10360 +       int i;
10361 +
10362 +       for (i = 0 ; i < ports_c; i++) {
10363 +               DEBUGP("unregistering helper for port %d\n",
10364 +                       ports[i]);
10365 +               ip_conntrack_helper_unregister(&tftp[i]);
10366 +       } 
10367 +}
10368 +
10369 +static int __init init(void)
10370 +{
10371 +       int i, ret;
10372 +       char *tmpname;
10373 +
10374 +       if (!ports[0])
10375 +               ports[0]=TFTP_PORT;
10376 +
10377 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
10378 +               /* Create helper structure */
10379 +               tftp[i].tuple.dst.protonum = IPPROTO_UDP;
10380 +               tftp[i].tuple.src.u.udp.port = htons(ports[i]);
10381 +               tftp[i].mask.dst.protonum = 0xFFFF;
10382 +               tftp[i].mask.src.u.udp.port = 0xFFFF;
10383 +               tftp[i].max_expected = 1;
10384 +               tftp[i].timeout = 0;
10385 +               tftp[i].flags = IP_CT_HELPER_F_REUSE_EXPECT;
10386 +               tftp[i].me = THIS_MODULE;
10387 +               tftp[i].help = tftp_help;
10388 +
10389 +               tmpname = &tftp_names[i][0];
10390 +               if (ports[i] == TFTP_PORT)
10391 +                       sprintf(tmpname, "tftp");
10392 +               else
10393 +                       sprintf(tmpname, "tftp-%d", i);
10394 +               tftp[i].name = tmpname;
10395 +
10396 +               DEBUGP("port #%d: %d\n", i, ports[i]);
10397 +
10398 +               ret=ip_conntrack_helper_register(&tftp[i]);
10399 +               if (ret) {
10400 +                       printk("ERROR registering helper for port %d\n",
10401 +                               ports[i]);
10402 +                       fini();
10403 +                       return(ret);
10404 +               }
10405 +               ports_c++;
10406 +       }
10407 +       return(0);
10408 +}
10409 +
10410 +module_init(init);
10411 +module_exit(fini);
10412 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_amanda.c linux-2.4.20/net/ipv4/netfilter/ip_nat_amanda.c
10413 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_amanda.c Thu Jan  1 00:00:00 1970
10414 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_amanda.c     Wed Sep 24 09:16:24 2003
10415 @@ -0,0 +1,224 @@
10416 +/* Amanda extension for TCP NAT alteration.
10417 + * (C) 2002 by Brian J. Murrell <netfilter@interlinx.bc.ca>
10418 + * based on a copy of HW's ip_nat_irc.c as well as other modules
10419 + *
10420 + *      This program is free software; you can redistribute it and/or
10421 + *      modify it under the terms of the GNU General Public License
10422 + *      as published by the Free Software Foundation; either version
10423 + *      2 of the License, or (at your option) any later version.
10424 + *
10425 + *     Module load syntax:
10426 + *     insmod ip_nat_amanda.o
10427 + */
10428 +
10429 +#include <linux/module.h>
10430 +#include <linux/netfilter_ipv4.h>
10431 +#include <linux/ip.h>
10432 +#include <linux/udp.h>
10433 +#include <linux/kernel.h>
10434 +#include <net/tcp.h>
10435 +#include <net/udp.h>
10436 +
10437 +#include <linux/netfilter_ipv4/ip_nat.h>
10438 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10439 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10440 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10441 +#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
10442 +
10443 +
10444 +#if 0
10445 +#define DEBUGP printk
10446 +#define DUMP_OFFSET(x) printk("offset_before=%d, offset_after=%d, correction_pos=%u\n", x->offset_before, x->offset_after, x->correction_pos);
10447 +#else
10448 +#define DEBUGP(format, args...)
10449 +#define DUMP_OFFSET(x)
10450 +#endif
10451 +
10452 +MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
10453 +MODULE_DESCRIPTION("Amanda network address translation module");
10454 +MODULE_LICENSE("GPL");
10455 +
10456 +/* protects amanda part of conntracks */
10457 +DECLARE_LOCK_EXTERN(ip_amanda_lock);
10458 +
10459 +static unsigned int
10460 +amanda_nat_expected(struct sk_buff **pskb,
10461 +                unsigned int hooknum,
10462 +                struct ip_conntrack *ct,
10463 +                struct ip_nat_info *info)
10464 +{
10465 +       struct ip_nat_multi_range mr;
10466 +       u_int32_t newdstip, newsrcip, newip;
10467 +       u_int16_t port;
10468 +       struct ip_ct_amanda_expect *exp_info;
10469 +       struct ip_conntrack *master = master_ct(ct);
10470 +
10471 +       IP_NF_ASSERT(info);
10472 +       IP_NF_ASSERT(master);
10473 +
10474 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10475 +
10476 +       DEBUGP("nat_expected: We have a connection!\n");
10477 +       exp_info = &ct->master->help.exp_amanda_info;
10478 +
10479 +       newdstip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
10480 +       newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
10481 +       DEBUGP("nat_expected: %u.%u.%u.%u->%u.%u.%u.%u\n",
10482 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
10483 +
10484 +       port = exp_info->port;
10485 +
10486 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10487 +               newip = newsrcip;
10488 +       else
10489 +               newip = newdstip;
10490 +
10491 +       DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
10492 +
10493 +       mr.rangesize = 1;
10494 +       /* We don't want to manip the per-protocol, just the IPs. */
10495 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
10496 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
10497 +
10498 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
10499 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
10500 +               mr.range[0].min = mr.range[0].max
10501 +                       = ((union ip_conntrack_manip_proto)
10502 +                               { .udp = { htons(port) } });
10503 +       }
10504 +
10505 +       return ip_nat_setup_info(ct, &mr, hooknum);
10506 +}
10507 +
10508 +static int amanda_data_fixup(struct ip_conntrack *ct,
10509 +                         struct sk_buff **pskb,
10510 +                         enum ip_conntrack_info ctinfo,
10511 +                         struct ip_conntrack_expect *expect)
10512 +{
10513 +       u_int32_t newip;
10514 +       /* DATA 99999 MESG 99999 INDEX 99999 */
10515 +       char buffer[6];
10516 +       struct ip_conntrack_expect *exp = expect;
10517 +       struct ip_ct_amanda_expect *ct_amanda_info = &exp->help.exp_amanda_info;
10518 +       struct ip_conntrack_tuple t = exp->tuple;
10519 +       int port;
10520 +
10521 +       MUST_BE_LOCKED(&ip_amanda_lock);
10522 +
10523 +       newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
10524 +       DEBUGP ("ip_nat_amanda_help: newip = %u.%u.%u.%u\n", NIPQUAD(newip));
10525 +
10526 +       /* Alter conntrack's expectations. */
10527 +
10528 +       /* We can read expect here without conntrack lock, since it's
10529 +          only set in ip_conntrack_amanda, with ip_amanda_lock held
10530 +          writable */
10531 +
10532 +       t.dst.ip = newip;
10533 +       for (port = ct_amanda_info->port + 10; port != 0; port++) {
10534 +               t.dst.u.tcp.port = htons(port);
10535 +               if (ip_conntrack_change_expect(exp, &t) == 0)
10536 +                       break;
10537 +       }
10538 +
10539 +       if (port == 0)
10540 +               return 0;
10541 +
10542 +       sprintf(buffer, "%u", port);
10543 +
10544 +       return ip_nat_mangle_udp_packet(pskb, ct, ctinfo, /* XXX exp->seq */ ct_amanda_info->offset, 
10545 +                                       ct_amanda_info->len, buffer, strlen(buffer));
10546 +}
10547 +
10548 +static unsigned int help(struct ip_conntrack *ct,
10549 +                        struct ip_conntrack_expect *exp,
10550 +                        struct ip_nat_info *info,
10551 +                        enum ip_conntrack_info ctinfo,
10552 +                        unsigned int hooknum,
10553 +                        struct sk_buff **pskb)
10554 +{
10555 +       int dir;
10556 +
10557 +       if (!exp)
10558 +               DEBUGP("ip_nat_amanda: no exp!!");
10559 +               
10560 +       /* Only mangle things once: original direction in POST_ROUTING
10561 +          and reply direction on PRE_ROUTING. */
10562 +       dir = CTINFO2DIR(ctinfo);
10563 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
10564 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
10565 +               DEBUGP("ip_nat_amanda_help: Not touching dir %s at hook %s\n",
10566 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10567 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10568 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10569 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
10570 +                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
10571 +               return NF_ACCEPT;
10572 +       }
10573 +       DEBUGP("ip_nat_amanda_help: got beyond not touching: dir %s at hook %s for expect: ",
10574 +                  dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
10575 +                  hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
10576 +                  : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
10577 +                    : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
10578 +                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
10579 +       DUMP_TUPLE(&exp->tuple);
10580 +
10581 +       LOCK_BH(&ip_amanda_lock);
10582 +// XXX if (exp->seq != 0)
10583 +       if (exp->help.exp_amanda_info.offset != 0)
10584 +               /*  if this packet has a "seq" it needs to have it's content mangled */
10585 +               if (!amanda_data_fixup(ct, pskb, ctinfo, exp)) {
10586 +                       UNLOCK_BH(&ip_amanda_lock);
10587 +                       DEBUGP("ip_nat_amanda: NF_DROP\n");
10588 +                       return NF_DROP;
10589 +               }
10590 +       exp->help.exp_amanda_info.offset = 0;
10591 +       UNLOCK_BH(&ip_amanda_lock);
10592 +
10593 +       DEBUGP("ip_nat_amanda: NF_ACCEPT\n");
10594 +       return NF_ACCEPT;
10595 +}
10596 +
10597 +static struct ip_nat_helper ip_nat_amanda_helper;
10598 +
10599 +/* This function is intentionally _NOT_ defined as  __exit, because
10600 + * it is needed by init() */
10601 +static void fini(void)
10602 +{
10603 +       DEBUGP("ip_nat_amanda: unregistering nat helper\n");
10604 +       ip_nat_helper_unregister(&ip_nat_amanda_helper);
10605 +}
10606 +
10607 +static int __init init(void)
10608 +{
10609 +       int ret = 0;
10610 +       struct ip_nat_helper *hlpr;
10611 +
10612 +       hlpr = &ip_nat_amanda_helper;
10613 +       hlpr->tuple.dst.protonum = IPPROTO_UDP;
10614 +       hlpr->tuple.src.u.udp.port = htons(10080);
10615 +       hlpr->mask.src.u.udp.port = 0xFFFF;
10616 +       hlpr->mask.dst.protonum = 0xFFFF;
10617 +       hlpr->help = help;
10618 +       hlpr->flags = 0;
10619 +       hlpr->me = THIS_MODULE;
10620 +       hlpr->expect = amanda_nat_expected;
10621 +
10622 +       hlpr->name = "amanda";
10623 +
10624 +       DEBUGP
10625 +           ("ip_nat_amanda: Trying to register nat helper\n");
10626 +       ret = ip_nat_helper_register(hlpr);
10627 +
10628 +       if (ret) {
10629 +               printk
10630 +                   ("ip_nat_amanda: error registering nat helper\n");
10631 +               fini();
10632 +               return 1;
10633 +       }
10634 +       return ret;
10635 +}
10636 +
10637 +
10638 +module_init(init);
10639 +module_exit(fini);
10640 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_core.c linux-2.4.20/net/ipv4/netfilter/ip_nat_core.c
10641 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_core.c   Thu Nov 28 23:53:15 2002
10642 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_core.c       Wed Sep 24 09:18:12 2003
10643 @@ -1,10 +1,9 @@
10644  /* NAT for netfilter; shared with compatibility layer. */
10645  
10646  /* (c) 1999 Paul `Rusty' Russell.  Licenced under the GNU General
10647 -   Public Licence. */
10648 -#ifdef MODULE
10649 -#define __NO_VERSION__
10650 -#endif
10651 + * Public Licence. 
10652 + * (c) 2000-2002 by the netfilter core team <coreteam@netfilter.org>
10653 + */
10654  #include <linux/version.h>
10655  #include <linux/module.h>
10656  #include <linux/types.h>
10657 @@ -70,6 +69,7 @@
10658  static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
10659  {
10660         struct ip_nat_info *info = &conn->nat.info;
10661 +       unsigned int hs, hp;
10662  
10663         if (!info->initialized)
10664                 return;
10665 @@ -77,27 +77,31 @@
10666         IP_NF_ASSERT(info->bysource.conntrack);
10667         IP_NF_ASSERT(info->byipsproto.conntrack);
10668  
10669 +       hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
10670 +                        conn->tuplehash[IP_CT_DIR_ORIGINAL]
10671 +                        .tuple.dst.protonum);
10672 +
10673 +       hp = hash_by_ipsproto(conn->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip,
10674 +                             conn->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip,
10675 +                             conn->tuplehash[IP_CT_DIR_REPLY]
10676 +                             .tuple.dst.protonum);
10677 +
10678         WRITE_LOCK(&ip_nat_lock);
10679 -       LIST_DELETE(&bysource[hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL]
10680 -                                         .tuple.src,
10681 -                                         conn->tuplehash[IP_CT_DIR_ORIGINAL]
10682 -                                         .tuple.dst.protonum)],
10683 -                   &info->bysource);
10684 -
10685 -       LIST_DELETE(&byipsproto
10686 -                   [hash_by_ipsproto(conn->tuplehash[IP_CT_DIR_REPLY]
10687 -                                     .tuple.src.ip,
10688 -                                     conn->tuplehash[IP_CT_DIR_REPLY]
10689 -                                     .tuple.dst.ip,
10690 -                                     conn->tuplehash[IP_CT_DIR_REPLY]
10691 -                                     .tuple.dst.protonum)],
10692 -                   &info->byipsproto);
10693 +       LIST_DELETE(&bysource[hs], &info->bysource);
10694 +       LIST_DELETE(&byipsproto[hp], &info->byipsproto);
10695         WRITE_UNLOCK(&ip_nat_lock);
10696  }
10697  
10698 -/* We do checksum mangling, so if they were wrong before they're still
10699 - * wrong.  Also works for incomplete packets (eg. ICMP dest
10700 - * unreachables.) */
10701 +/**
10702 + * ip_nat_cheat_check - Incremental checksum change for IP/TCP checksum
10703 + * @oldvalinv: bit-inverted old value of 32bit word
10704 + * @newval: new value of 32bit word
10705 + * @oldcheck: old checksum value
10706 + *
10707 + * This function implements incremental checksum mangling, so if a checksum
10708 + * was wrong it will still be wrong after mangling.  Also works for incomplete
10709 + * packets (eg. ICMP dest unreachables).  Return value is the new checksum.
10710 + */
10711  u_int16_t
10712  ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
10713  {
10714 @@ -123,7 +127,14 @@
10715         return i;
10716  }
10717  
10718 -/* Is this tuple already taken? (not by us) */
10719 +/**
10720 + * ip_nat_used_tuple - Is this tuple already in use?
10721 + * @tuple: tuple to be used for this check
10722 + * @ignored_conntrack: conntrack excluded from this check
10723 + *
10724 + * This function checks for the reply (inverted) tuple in the conntrack
10725 + * hash.  This is necessarry with NAT, since there is no fixed mapping.
10726 + */
10727  int
10728  ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
10729                   const struct ip_conntrack *ignored_conntrack)
10730 @@ -162,8 +173,8 @@
10731                                 continue;
10732                 }
10733  
10734 -               if ((mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
10735 -                   && proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
10736 +               if (!(mr->range[i].flags & IP_NAT_RANGE_PROTO_SPECIFIED)
10737 +                   || proto->in_range(&newtuple, IP_NAT_MANIP_SRC,
10738                                        &mr->range[i].min, &mr->range[i].max))
10739                         return 1;
10740         }
10741 @@ -247,11 +258,12 @@
10742            const struct ip_conntrack *conntrack)
10743  {
10744         unsigned int score = 0;
10745 +       unsigned int h;
10746  
10747         MUST_BE_READ_LOCKED(&ip_nat_lock);
10748 -       LIST_FIND(&byipsproto[hash_by_ipsproto(src, dst, protonum)],
10749 -                 fake_cmp, struct ip_nat_hash *, src, dst, protonum, &score,
10750 -                 conntrack);
10751 +       h = hash_by_ipsproto(src, dst, protonum);
10752 +       LIST_FIND(&byipsproto[h], fake_cmp, struct ip_nat_hash *,
10753 +                 src, dst, protonum, &score, conntrack);
10754  
10755         return score;
10756  }
10757 @@ -434,7 +446,7 @@
10758         *tuple = *orig_tuple;
10759         while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
10760                != NULL) {
10761 -               DEBUGP("Found best for "); DUMP_TUPLE(tuple);
10762 +               DEBUGP("Found best for "); DUMP_TUPLE_RAW(tuple);
10763                 /* 3) The per-protocol part of the manip is made to
10764                    map into the range to make a unique tuple. */
10765  
10766 @@ -511,6 +523,19 @@
10767  #endif
10768  };
10769  
10770 +/**
10771 + * ip_nat_setup_info - Set up NAT mappings for NEW packet
10772 + * @conntrack: conntrack on which we operate
10773 + * @mr: address/port range which is valid for this NAT mapping
10774 + * @hooknum: hook at which this NAT mapping applies
10775 + *
10776 + * This function is called by NAT targets (SNAT,DNAT,...) and by
10777 + * the NAT application helper modules.  It is called for the NEW packet
10778 + * of a connection in order to specify which NAT mappings shall apply to
10779 + * this connection at a given hook.
10780 + *
10781 + * Note: The reply mappings are created automagically by this function. 
10782 + */
10783  unsigned int
10784  ip_nat_setup_info(struct ip_conntrack *conntrack,
10785                   const struct ip_nat_multi_range *mr,
10786 @@ -519,12 +544,14 @@
10787         struct ip_conntrack_tuple new_tuple, inv_tuple, reply;
10788         struct ip_conntrack_tuple orig_tp;
10789         struct ip_nat_info *info = &conntrack->nat.info;
10790 +       int in_hashes = info->initialized;
10791  
10792         MUST_BE_WRITE_LOCKED(&ip_nat_lock);
10793         IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
10794                      || hooknum == NF_IP_POST_ROUTING
10795                      || hooknum == NF_IP_LOCAL_OUT);
10796         IP_NF_ASSERT(info->num_manips < IP_NAT_MAX_MANIPS);
10797 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10798  
10799         /* What we've got will look like inverse of reply. Normally
10800            this is what is in the conntrack, except for prior
10801 @@ -573,9 +600,9 @@
10802                        HOOK2MANIP(hooknum)==IP_NAT_MANIP_SRC ? "SRC" : "DST",
10803                        conntrack);
10804                 DEBUGP("Original: ");
10805 -               DUMP_TUPLE(&orig_tp);
10806 +               DUMP_TUPLE_RAW(&orig_tp);
10807                 DEBUGP("New: ");
10808 -               DUMP_TUPLE(&new_tuple);
10809 +               DUMP_TUPLE_RAW(&new_tuple);
10810  #endif
10811  
10812                 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
10813 @@ -641,6 +668,14 @@
10814  
10815         /* It's done. */
10816         info->initialized |= (1 << HOOK2MANIP(hooknum));
10817 +
10818 +       if (in_hashes) {
10819 +               IP_NF_ASSERT(info->bysource.conntrack);
10820 +               replace_in_hashes(conntrack, info);
10821 +       } else {
10822 +               place_in_hashes(conntrack, info);
10823 +       }
10824 +
10825         return NF_ACCEPT;
10826  }
10827  
10828 @@ -799,6 +834,7 @@
10829                 struct ip_conntrack_expect *exp = NULL;
10830                 struct list_head *cur_item;
10831                 int ret = NF_ACCEPT;
10832 +               int helper_called = 0;
10833  
10834                 DEBUGP("do_bindings: helper existing for (%p)\n", ct);
10835  
10836 @@ -817,19 +853,21 @@
10837                                 continue;
10838  
10839                         if (exp_for_packet(exp, pskb)) {
10840 -                               /* FIXME: May be true multiple times in the case of UDP!! */
10841 -                               DEBUGP("calling nat helper (exp=%p) for packet\n",
10842 -                                       exp);
10843 +                               /* FIXME: May be true multiple times in the
10844 +                                * case of UDP!! */
10845 +                               DEBUGP("calling nat helper (exp=%p) for packet\n", exp);
10846                                 ret = helper->help(ct, exp, info, ctinfo, 
10847                                                    hooknum, pskb);
10848                                 if (ret != NF_ACCEPT) {
10849                                         READ_UNLOCK(&ip_conntrack_lock);
10850                                         return ret;
10851                                 }
10852 +                               helper_called = 1;
10853                         }
10854                 }
10855 -               /* Helper might want to manip the packet even when there is no expectation */
10856 -               if (!exp && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
10857 +               /* Helper might want to manip the packet even when there is no
10858 +                * matching expectation for this packet */
10859 +               if (!helper_called && helper->flags & IP_NAT_HELPER_F_ALWAYS) {
10860                         DEBUGP("calling nat helper for packet without expectation\n");
10861                         ret = helper->help(ct, NULL, info, ctinfo, 
10862                                            hooknum, pskb);
10863 @@ -915,7 +953,7 @@
10864                    packet, except it was never src/dst reversed, so
10865                    where we would normally apply a dst manip, we apply
10866                    a src, and vice versa. */
10867 -               if (info->manips[i].hooknum == opposite_hook[hooknum]) {
10868 +               if (info->manips[i].hooknum == hooknum) {
10869                         DEBUGP("icmp_reply: inner %s -> %u.%u.%u.%u %u\n",
10870                                info->manips[i].maniptype == IP_NAT_MANIP_SRC
10871                                ? "DST" : "SRC",
10872 @@ -926,9 +964,9 @@
10873                                   &info->manips[i].manip,
10874                                   !info->manips[i].maniptype,
10875                                   &skb->nfcache);
10876 -               /* Outer packet needs to have IP header NATed like
10877 -                   it's a reply. */
10878 -               } else if (info->manips[i].hooknum == hooknum) {
10879 +                       /* Outer packet needs to have IP header NATed like
10880 +                          it's a reply. */
10881 +
10882                         /* Use mapping to map outer packet: 0 give no
10883                             per-proto mapping */
10884                         DEBUGP("icmp_reply: outer %s -> %u.%u.%u.%u\n",
10885 @@ -982,6 +1020,10 @@
10886         /* FIXME: Man, this is a hack.  <SIGH> */
10887         IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
10888         ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
10889 +       
10890 +       /* Initialize fake conntrack so that NAT will skip it */
10891 +       ip_conntrack_untracked.nat.info.initialized |= 
10892 +               (1 << IP_NAT_MANIP_SRC) | (1 << IP_NAT_MANIP_DST);
10893  
10894         return 0;
10895  }
10896 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_cuseeme.c linux-2.4.20/net/ipv4/netfilter/ip_nat_cuseeme.c
10897 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_cuseeme.c        Thu Jan  1 00:00:00 1970
10898 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_cuseeme.c    Wed Sep 24 09:17:38 2003
10899 @@ -0,0 +1,289 @@
10900 +/* CuSeeMe extension for UDP NAT alteration.
10901 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
10902 + * based on ip_masq_cuseeme.c in 2.2 kernels
10903 + *
10904 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
10905 + *
10906 + *      This program is free software; you can redistribute it and/or
10907 + *      modify it under the terms of the GNU General Public License
10908 + *      as published by the Free Software Foundation; either version
10909 + *      2 of the License, or (at your option) any later version.
10910 + *
10911 + *      Module load syntax:
10912 + *      insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
10913 + *
10914 + *      Please give the ports of the CuSeeMe traffic you want to track.
10915 + *      If you don't specify ports, the default will be UDP port 7648.
10916 + *
10917 + *      CuSeeMe Protocol Documentation:
10918 + *      http://cu-seeme.net/squeek/tech/contents.html
10919 + *
10920 + */
10921 +
10922 +#include <linux/module.h>
10923 +#include <linux/netfilter_ipv4.h>
10924 +#include <linux/ip.h>
10925 +#include <linux/udp.h>
10926 +
10927 +#include <linux/netfilter.h>
10928 +#include <linux/netfilter_ipv4/ip_tables.h>
10929 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
10930 +#include <linux/netfilter_ipv4/ip_conntrack_cuseeme.h>
10931 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
10932 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
10933 +
10934 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
10935 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
10936 +MODULE_LICENSE("GPL");
10937 +
10938 +#define MAX_PORTS 8
10939 +
10940 +static int ports[MAX_PORTS];
10941 +static int ports_c = 0;
10942 +#ifdef MODULE_PARM
10943 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
10944 +MODULE_PARM_DESC(ports, "port numbers of CuSeeMe reflectors");
10945 +#endif
10946 +
10947 +#if 0
10948 +#define DEBUGP printk
10949 +#else
10950 +#define DEBUGP(format, args...)
10951 +#endif
10952 +
10953 +/* process packet from client->reflector, possibly manipulate client IP in payload */
10954 +void cuseeme_mangle_outgoing(struct ip_conntrack *ct,
10955 +                             struct ip_nat_info *info,
10956 +                             enum ip_conntrack_info ctinfo,
10957 +                             struct sk_buff **pskb,
10958 +                             char *data,
10959 +                             unsigned int datalen)
10960 +{
10961 +       char new_port_ip[6];
10962 +       struct cu_header *cu_head=(struct cu_header *)data;
10963 +       
10964 +       DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n", 
10965 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
10966 +               
10967 +       /* At least check that the data at offset 10 is the client's port and IP address */
10968 +       if ((ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip == cu_head->addr) &&
10969 +           (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port == cu_head->port)) {
10970 +               DEBUGP("ip_nat_cuseeme: rewrite outgoing client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n", 
10971 +                      NIPQUAD(cu_head->addr),
10972 +                      ntohs(cu_head->port),
10973 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
10974 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port));
10975 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
10976 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
10977 +               /* at offset 10, replace 6 bytes containing port + IP address */
10978 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
10979 +                                        10, 6, (char *)(new_port_ip), 6);
10980 +       } else 
10981 +               DEBUGP("ip_nat_cuseeme: expected outgoing client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
10982 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
10983 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port),
10984 +                      NIPQUAD(cu_head->addr),
10985 +                      ntohs(cu_head->port));
10986 +}
10987 +
10988 +/* process packet from reflector->client, possibly manipulate client IP & reflector IP in payload */
10989 +void cuseeme_mangle_incoming(struct ip_conntrack *ct,
10990 +                             struct ip_nat_info *info,
10991 +                             enum ip_conntrack_info ctinfo,
10992 +                             struct sk_buff **pskb,
10993 +                             char *data,
10994 +                             unsigned int datalen)
10995 +{
10996 +       char new_port_ip[6];
10997 +       struct cu_header *cu_head = (struct cu_header *)data;
10998 +       struct oc_header *oc_head = (struct oc_header *)data; 
10999 +       struct client_info *ci; 
11000 +       int i, off;
11001 +
11002 +       
11003 +       DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n", 
11004 +              ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
11005 +               
11006 +       /* Check if we're really dealing with the client's port + IP address before rewriting */
11007 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip == cu_head->dest_addr) &&
11008 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port == cu_head->dest_port)) {
11009 +               DEBUGP("ip_nat_cuseeme: rewrite incoming client %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 2\n",
11010 +                      NIPQUAD(cu_head->dest_addr),
11011 +                      ntohs(cu_head->dest_port),
11012 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
11013 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port));
11014 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
11015 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
11016 +               /* at offset 2, replace 6 bytes containing port + IP address */
11017 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
11018 +                                        2, 6, (char *)(new_port_ip), 6);
11019 +       } else 
11020 +               DEBUGP("ip_nat_cuseeme: expected incoming client %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
11021 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip),
11022 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port),
11023 +                      NIPQUAD(cu_head->dest_addr),
11024 +                      ntohs(cu_head->dest_port));
11025 +       
11026 +       /* Check if we're really dealing with the server's port + IP address before rewriting. 
11027 +          In some cases, the IP address == 0.0.0.0 so we don't rewrite anything */
11028 +       if((ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip == cu_head->addr) &&
11029 +          (ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port == cu_head->port)) {
11030 +               DEBUGP("in_nat_cuseeme: rewrite incoming server %u.%u.%u.%u:%u->%u.%u.%u.%u:%u at offset 10\n",
11031 +                      NIPQUAD(cu_head->addr),
11032 +                      ntohs(cu_head->port),
11033 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip),
11034 +                      ntohs(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port));
11035 +               *((u_int16_t *)new_port_ip) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.udp.port;
11036 +               *((u_int32_t *)(new_port_ip+2)) = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
11037 +               /* at offset 10, replace 6 bytes containing port + IP address */
11038 +               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
11039 +                                        10, 6, (char *)(new_port_ip), 6);
11040 +       } else 
11041 +               /* Sometimes we find 0.0.0.0, sometimes an IP address - the docs say this field
11042 +                  is not that important so we're not logging this unless we're debugging */
11043 +               DEBUGP("ip_nat_cuseeme: no biggie, expected incoming server %u.%u.%u.%u:%u, but got %u.%u.%u.%u:%u\n",
11044 +                      NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip),
11045 +                      ntohs(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u.udp.port),
11046 +                      NIPQUAD(cu_head->addr),
11047 +                      ntohs(cu_head->port));
11048 +       
11049 +       /* Spin through client_info structs until we find our own */
11050 +       if((ntohs(cu_head->data_type) == 101) && (datalen >= sizeof(struct oc_header))) {
11051 +               DEBUGP("ip_nat_cuseeme: looping through %u client_info structs\n", oc_head->client_count);
11052 +               for(i=0, off=sizeof(struct oc_header);
11053 +                   (i < oc_head->client_count && 
11054 +                   off+sizeof(struct client_info) <= datalen); 
11055 +                   i++) {
11056 +                       ci=(struct client_info *)(data+off);
11057 +                       DEBUGP("ip_nat_cuseeme: comparing %u.%u.%u.%u with %u.%u.%u.%u at offset %u\n", 
11058 +                              NIPQUAD(ci->address), NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
11059 +                              (unsigned int)((void *)&(ci->address) - (void *)cu_head));
11060 +                       if(ci->address == ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip) {
11061 +                               /* mangle this IP address */
11062 +                               DEBUGP("ip_nat_cuseeme: changing %u.%u.%u.%u->%u.%u.%u.%u at offset %u\n",
11063 +                                      NIPQUAD(ci->address), 
11064 +                                      NIPQUAD(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip),
11065 +                                      (unsigned int)((void *)&(ci->address) - (void *)cu_head));
11066 +                               ip_nat_mangle_udp_packet(pskb, ct, ctinfo,
11067 +                                                        (unsigned int)((void *)&(ci->address) - (void *)cu_head), 4, 
11068 +                                                        (char *)(&(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip)), 4);
11069 +                               break;
11070 +                       } else 
11071 +                               off+=sizeof(struct client_info);
11072 +               }
11073 +       } else
11074 +               DEBUGP("ip_nat_cuseeme: data_type %u, datalen %u < sizeof(struct oc_header) %u\n", 
11075 +                      ntohs(cu_head->data_type), datalen, sizeof(struct oc_header));
11076 +}
11077 +
11078 +static unsigned int 
11079 +cuseeme_nat_help(struct ip_conntrack *ct,
11080 +                 struct ip_conntrack_expect *exp,
11081 +                 struct ip_nat_info *info,
11082 +                 enum ip_conntrack_info ctinfo,
11083 +                 unsigned int hooknum,
11084 +                 struct sk_buff **pskb)
11085 +{
11086 +       struct iphdr *iph = (*pskb)->nh.iph;
11087 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
11088 +       int dir = CTINFO2DIR(ctinfo);
11089 +       unsigned int datalen = (*pskb)->len - iph->ihl * 4 - sizeof(struct udphdr);
11090 +       char *data = (char *) &udph[1];
11091 +       
11092 +       DEBUGP("ip_nat_cuseeme: cuseeme_nat_help, direction: %s hook: %s\n",
11093 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
11094 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
11095 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
11096 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
11097 +             );
11098 +       
11099 +       /* Only mangle things once: original direction in POST_ROUTING
11100 +          and reply direction on PRE_ROUTING. */
11101 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
11102 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
11103 +               DEBUGP("ip_nat_cuseeme: not touching dir %s at hook %s\n",
11104 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
11105 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
11106 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
11107 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
11108 +               return NF_ACCEPT;
11109 +       }
11110 +       
11111 +       if(datalen < sizeof(struct cu_header)) {
11112 +               /* packet too small */
11113 +               if (net_ratelimit())
11114 +                       printk("ip_nat_cuseeme: payload too small (%u, should be >= %u)\n", 
11115 +                              datalen, sizeof(struct cu_header));
11116 +               return NF_ACCEPT;
11117 +       }
11118 +
11119 +
11120 +       /* In the debugging output, "outgoing" is from client to server, and
11121 +          "incoming" is from server to client */
11122 +       if(HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) 
11123 +               cuseeme_mangle_outgoing(ct, info, ctinfo, pskb, data, datalen);
11124 +       else 
11125 +               cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
11126 +
11127 +       return NF_ACCEPT;
11128 +}
11129 +
11130 +static struct ip_nat_helper cuseeme[MAX_PORTS];
11131 +static char cuseeme_names[MAX_PORTS][14];  /* cuseeme-65535 */
11132 +
11133 +static void fini(void)
11134 +{
11135 +       int i;
11136 +       
11137 +       for (i = 0 ; i < ports_c; i++) {
11138 +               DEBUGP("ip_nat_cuseeme: unregistering helper for port %d\n", ports[i]);
11139 +                      ip_nat_helper_unregister(&cuseeme[i]);
11140 +       }
11141 +}
11142 +
11143 +static int __init init(void)
11144 +{
11145 +       int i, ret = 0;
11146 +       char *tmpname;
11147 +
11148 +       if (!ports[0])
11149 +               ports[0] = CUSEEME_PORT;
11150 +               
11151 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11152 +               memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
11153 +
11154 +               cuseeme[i].tuple.dst.protonum = IPPROTO_UDP;
11155 +               cuseeme[i].tuple.dst.u.udp.port = htons(ports[i]);
11156 +               cuseeme[i].mask.dst.protonum = 0xFFFF;
11157 +               cuseeme[i].mask.dst.u.udp.port = 0xFFFF;
11158 +               cuseeme[i].help = cuseeme_nat_help;
11159 +               cuseeme[i].flags = IP_NAT_HELPER_F_STANDALONE + 
11160 +                                  IP_NAT_HELPER_F_ALWAYS; /* dunno if IP_NAT_HELPER_F_ALWAYS
11161 +                                                             is stricly needed... */
11162 +               cuseeme[i].me = THIS_MODULE;
11163 +               cuseeme[i].expect = NULL; /* cuseeme_nat_expected; */
11164 +                       
11165 +               tmpname = &cuseeme_names[i][0];
11166 +               if (ports[i] == CUSEEME_PORT)
11167 +                       sprintf(tmpname, "cuseeme");
11168 +               else
11169 +                       sprintf(tmpname, "cuseeme-%d", ports[i]);
11170 +               cuseeme[i].name = tmpname;
11171 +                       
11172 +               DEBUGP("ip_nat_cuseeme: registering helper for port %d: name %s\n",
11173 +                      ports[i], cuseeme[i].name);
11174 +               ret = ip_nat_helper_register(&cuseeme[i]);
11175 +                       
11176 +               if (ret) {
11177 +                       printk("ip_nat_cuseeme: unable to register helper for port %d\n",
11178 +                              ports[i]);
11179 +                       fini();
11180 +                       return ret;
11181 +               }
11182 +               ports_c++;
11183 +       }
11184 +       return ret;
11185 +}
11186 +       
11187 +module_init(init);
11188 +module_exit(fini);
11189 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_ftp.c linux-2.4.20/net/ipv4/netfilter/ip_nat_ftp.c
11190 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_ftp.c    Thu Nov 28 23:53:15 2002
11191 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_ftp.c        Wed Sep 24 09:16:17 2003
11192 @@ -84,7 +84,7 @@
11193                 mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
11194                 mr.range[0].min = mr.range[0].max
11195                         = ((union ip_conntrack_manip_proto)
11196 -                               { htons(exp_ftp_info->port) });
11197 +                               { .tcp = { htons(exp_ftp_info->port) } });
11198         }
11199         return ip_nat_setup_info(ct, &mr, hooknum);
11200  }
11201 @@ -306,9 +306,6 @@
11202                 ports[0] = FTP_PORT;
11203  
11204         for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
11205 -
11206 -               memset(&ftp[i], 0, sizeof(struct ip_nat_helper));
11207 -
11208                 ftp[i].tuple.dst.protonum = IPPROTO_TCP;
11209                 ftp[i].tuple.src.u.tcp.port = htons(ports[i]);
11210                 ftp[i].mask.dst.protonum = 0xFFFF;
11211 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_h323.c linux-2.4.20/net/ipv4/netfilter/ip_nat_h323.c
11212 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_h323.c   Thu Jan  1 00:00:00 1970
11213 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_h323.c       Wed Sep 24 09:17:43 2003
11214 @@ -0,0 +1,419 @@
11215 +/* 
11216 + * H.323 'brute force' extension for NAT alteration. 
11217 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
11218 + *
11219 + * Based on ip_masq_h323.c for 2.2 kernels from CoRiTel, Sofia project.
11220 + * (http://www.coritel.it/projects/sofia/nat.html)
11221 + * Uses Sampsa Ranta's excellent idea on using expectfn to 'bind'
11222 + * the unregistered helpers to the conntrack entries.
11223 + */
11224 +
11225 +
11226 +#include <linux/module.h>
11227 +#include <linux/netfilter.h>
11228 +#include <linux/ip.h>
11229 +#include <net/checksum.h>
11230 +#include <net/tcp.h>
11231 +
11232 +#include <linux/netfilter_ipv4/lockhelp.h>
11233 +#include <linux/netfilter_ipv4/ip_nat.h>
11234 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
11235 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
11236 +#include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
11237 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
11238 +#include <linux/netfilter_ipv4/ip_conntrack_h323.h>
11239 +
11240 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
11241 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
11242 +MODULE_LICENSE("GPL");
11243 +
11244 +DECLARE_LOCK_EXTERN(ip_h323_lock);
11245 +struct module *ip_nat_h323 = THIS_MODULE;
11246 +
11247 +#if 0
11248 +#define DEBUGP printk
11249 +#else
11250 +#define DEBUGP(format, args...)
11251 +#endif
11252 +
11253 +/* FIXME: Time out? --RR */
11254 +
11255 +static unsigned int 
11256 +h225_nat_expected(struct sk_buff **pskb,
11257 +                 unsigned int hooknum,
11258 +                 struct ip_conntrack *ct,
11259 +                 struct ip_nat_info *info);
11260 +
11261 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
11262 +                                 struct ip_conntrack_expect *exp,
11263 +                                 struct ip_nat_info *info,
11264 +                                 enum ip_conntrack_info ctinfo,
11265 +                                 unsigned int hooknum,
11266 +                                 struct sk_buff **pskb);
11267 +                 
11268 +static struct ip_nat_helper h245 = 
11269 +       { { NULL, NULL },
11270 +          "H.245",                             /* name */
11271 +         0,                                    /* flags */
11272 +         NULL,                                 /* module */
11273 +         { { 0, { 0 } },                       /* tuple */
11274 +           { 0, { 0 }, IPPROTO_TCP } },
11275 +         { { 0, { 0xFFFF } },                  /* mask */
11276 +           { 0, { 0 }, 0xFFFF } },
11277 +         h225_nat_help,                        /* helper */
11278 +         h225_nat_expected                     /* expectfn */
11279 +       };
11280 +
11281 +static unsigned int
11282 +h225_nat_expected(struct sk_buff **pskb,
11283 +                 unsigned int hooknum,
11284 +                 struct ip_conntrack *ct,
11285 +                 struct ip_nat_info *info)
11286 +{
11287 +       struct ip_nat_multi_range mr;
11288 +       u_int32_t newdstip, newsrcip, newip;
11289 +       u_int16_t port;
11290 +       struct ip_ct_h225_expect *exp_info;
11291 +       struct ip_ct_h225_master *master_info;
11292 +       struct ip_conntrack *master = master_ct(ct);
11293 +       unsigned int is_h225, ret;
11294 +       
11295 +       IP_NF_ASSERT(info);
11296 +       IP_NF_ASSERT(master);
11297 +
11298 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
11299 +
11300 +       DEBUGP("h225_nat_expected: We have a connection!\n");
11301 +       master_info = &ct->master->expectant->help.ct_h225_info;
11302 +       exp_info = &ct->master->help.exp_h225_info;
11303 +
11304 +       LOCK_BH(&ip_h323_lock);
11305 +
11306 +       DEBUGP("master: ");
11307 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
11308 +       DUMP_TUPLE(&master->tuplehash[IP_CT_DIR_REPLY].tuple);
11309 +       DEBUGP("conntrack: ");
11310 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
11311 +       if (exp_info->dir == IP_CT_DIR_ORIGINAL) {
11312 +               /* Make connection go to the client. */
11313 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
11314 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
11315 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to client)\n",
11316 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
11317 +       } else {
11318 +               /* Make the connection go to the server */
11319 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
11320 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
11321 +               DEBUGP("h225_nat_expected: %u.%u.%u.%u->%u.%u.%u.%u (to server)\n",
11322 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
11323 +       }
11324 +       port = exp_info->port;
11325 +       is_h225 = master_info->is_h225 == H225_PORT;
11326 +       UNLOCK_BH(&ip_h323_lock);
11327 +       
11328 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
11329 +               newip = newsrcip;
11330 +       else
11331 +               newip = newdstip;
11332 +
11333 +       DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
11334 +
11335 +       mr.rangesize = 1;
11336 +       /* We don't want to manip the per-protocol, just the IPs... */
11337 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
11338 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
11339 +
11340 +       /* ... unless we're doing a MANIP_DST, in which case, make
11341 +          sure we map to the correct port */
11342 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
11343 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
11344 +               mr.range[0].min = mr.range[0].max
11345 +                       = ((union ip_conntrack_manip_proto)
11346 +                               { .tcp = { port } });
11347 +       }
11348 +
11349 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
11350 +       
11351 +       if (is_h225) {
11352 +               DEBUGP("h225_nat_expected: H.225, setting NAT helper for %p\n", ct);
11353 +               /* NAT expectfn called with ip_nat_lock write-locked */
11354 +               info->helper = &h245;
11355 +       }
11356 +       return ret;
11357 +}
11358 +
11359 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
11360 +                                    struct sk_buff **pskb,
11361 +                                    enum ip_conntrack_info ctinfo)
11362 +{
11363 +       struct iphdr *iph = (*pskb)->nh.iph;
11364 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
11365 +       char *data = (char *) tcph + tcph->doff * 4;
11366 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
11367 +       u_int32_t datalen = tcplen - tcph->doff*4;
11368 +       struct ip_ct_h225_master *info = &ct->help.ct_h225_info; 
11369 +       u_int32_t newip;
11370 +       u_int16_t port;
11371 +       int i;
11372 +
11373 +       MUST_BE_LOCKED(&ip_h323_lock);
11374 +
11375 +       DEBUGP("h323_signal_address_fixup: %s %s\n",
11376 +               between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
11377 +                       ? "yes" : "no",
11378 +               between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
11379 +                       ? "yes" : "no");
11380 +       if (!(between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
11381 +               || between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)))
11382 +               return 1;
11383 +
11384 +       DEBUGP("h323_signal_address_fixup: offsets %u + 6  and %u + 6 in %u\n", 
11385 +               info->offset[IP_CT_DIR_ORIGINAL], 
11386 +               info->offset[IP_CT_DIR_REPLY],
11387 +               tcplen);
11388 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
11389 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
11390 +
11391 +       for (i = 0; i < IP_CT_DIR_MAX; i++) {
11392 +               DEBUGP("h323_signal_address_fixup: %s %s\n",
11393 +                       info->dir == IP_CT_DIR_ORIGINAL ? "original" : "reply",
11394 +                       i == IP_CT_DIR_ORIGINAL ? "caller" : "callee");
11395 +               if (!between(info->seq[i], ntohl(tcph->seq), 
11396 +                            ntohl(tcph->seq) + datalen))
11397 +                       continue;
11398 +               if (!between(info->seq[i] + 6, ntohl(tcph->seq),
11399 +                            ntohl(tcph->seq) + datalen)) {
11400 +                       /* Partial retransmisison. It's a cracker being funky. */
11401 +                       if (net_ratelimit()) {
11402 +                               printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
11403 +                                    info->seq[i],
11404 +                                    ntohl(tcph->seq),
11405 +                                    ntohl(tcph->seq) + datalen);
11406 +                       }
11407 +                       return 0;
11408 +               }
11409 +
11410 +               /* Change address inside packet to match way we're mapping
11411 +                  this connection. */
11412 +               if (i == IP_CT_DIR_ORIGINAL) {
11413 +                       newip = ct->tuplehash[!info->dir].tuple.dst.ip;
11414 +                       port = ct->tuplehash[!info->dir].tuple.dst.u.tcp.port;
11415 +               } else {
11416 +                       newip = ct->tuplehash[!info->dir].tuple.src.ip;
11417 +                       port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
11418 +               }
11419 +
11420 +               DEBUGP("h323_signal_address_fixup: orig %s IP:port %u.%u.%u.%u:%u\n", 
11421 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
11422 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
11423 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
11424 +
11425 +               /* Modify the packet */
11426 +               *(u_int32_t *)(data + info->offset[i]) = newip;
11427 +               *(u_int16_t *)(data + info->offset[i] + 4) = port;
11428 +       
11429 +               DEBUGP("h323_signal_address_fixup:  new %s IP:port %u.%u.%u.%u:%u\n", 
11430 +                       i == IP_CT_DIR_ORIGINAL ? "source" : "dest  ", 
11431 +                       NIPQUAD(*((u_int32_t *)(data + info->offset[i]))), 
11432 +                       ntohs(*((u_int16_t *)(data + info->offset[i] + 4))));
11433 +       }
11434 +
11435 +       /* fix checksum information */
11436 +
11437 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
11438 +                                    datalen, 0);
11439 +
11440 +       tcph->check = 0;
11441 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
11442 +                                  csum_partial((char *)tcph, tcph->doff*4,
11443 +                                          (*pskb)->csum));
11444 +       ip_send_check(iph);
11445 +
11446 +       return 1;
11447 +}
11448 +
11449 +static int h323_data_fixup(struct ip_ct_h225_expect *info,
11450 +                          struct ip_conntrack *ct,
11451 +                          struct sk_buff **pskb,
11452 +                          enum ip_conntrack_info ctinfo,
11453 +                          struct ip_conntrack_expect *expect)
11454 +{
11455 +       u_int32_t newip;
11456 +       u_int16_t port;
11457 +       struct ip_conntrack_tuple newtuple;
11458 +       struct iphdr *iph = (*pskb)->nh.iph;
11459 +       struct tcphdr *tcph = (void *)iph + iph->ihl*4;
11460 +       char *data = (char *) tcph + tcph->doff * 4;
11461 +       u_int32_t tcplen = (*pskb)->len - iph->ihl*4;
11462 +       struct ip_ct_h225_master *master_info = &ct->help.ct_h225_info;
11463 +       int is_h225;
11464 +
11465 +       MUST_BE_LOCKED(&ip_h323_lock);
11466 +       DEBUGP("h323_data_fixup: offset %u + 6 in %u\n", info->offset, tcplen);
11467 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
11468 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
11469 +
11470 +       if (!between(expect->seq + 6, ntohl(tcph->seq),
11471 +                   ntohl(tcph->seq) + tcplen - tcph->doff * 4)) {
11472 +               /* Partial retransmisison. It's a cracker being funky. */
11473 +               if (net_ratelimit()) {
11474 +                       printk("H.323_NAT: partial packet %u/6 in %u/%u\n",
11475 +                            expect->seq,
11476 +                            ntohl(tcph->seq),
11477 +                            ntohl(tcph->seq) + tcplen - tcph->doff * 4);
11478 +               }
11479 +               return 0;
11480 +       }
11481 +
11482 +       /* Change address inside packet to match way we're mapping
11483 +          this connection. */
11484 +       if (info->dir == IP_CT_DIR_REPLY) {
11485 +               /* Must be where client thinks server is */
11486 +               newip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
11487 +               /* Expect something from client->server */
11488 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
11489 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
11490 +       } else {
11491 +               /* Must be where server thinks client is */
11492 +               newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
11493 +               /* Expect something from server->client */
11494 +               newtuple.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
11495 +               newtuple.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
11496 +       }
11497 +
11498 +       is_h225 = (master_info->is_h225 == H225_PORT);
11499 +
11500 +       if (is_h225) {
11501 +               newtuple.dst.protonum = IPPROTO_TCP;
11502 +               newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
11503 +       } else {
11504 +               newtuple.dst.protonum = IPPROTO_UDP;
11505 +               newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
11506 +       }
11507 +       
11508 +       /* Try to get same port: if not, try to change it. */
11509 +       for (port = ntohs(info->port); port != 0; port++) {
11510 +               if (is_h225)
11511 +                       newtuple.dst.u.tcp.port = htons(port);
11512 +               else
11513 +                       newtuple.dst.u.udp.port = htons(port);
11514 +
11515 +               if (ip_conntrack_change_expect(expect, &newtuple) == 0)
11516 +                       break;
11517 +       }
11518 +       if (port == 0) {
11519 +               DEBUGP("h323_data_fixup: no free port found!\n");
11520 +               return 0;
11521 +       }
11522 +
11523 +       port = htons(port);
11524 +
11525 +       DEBUGP("h323_data_fixup: orig IP:port %u.%u.%u.%u:%u\n", 
11526 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
11527 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
11528 +
11529 +       /* Modify the packet */
11530 +       *(u_int32_t *)(data + info->offset) = newip;
11531 +       *(u_int16_t *)(data + info->offset + 4) = port;
11532 +       
11533 +       DEBUGP("h323_data_fixup: new IP:port %u.%u.%u.%u:%u\n", 
11534 +               NIPQUAD(*((u_int32_t *)(data + info->offset))), 
11535 +               ntohs(*((u_int16_t *)(data + info->offset + 4))));
11536 +
11537 +       /* fix checksum information  */
11538 +       /* FIXME: usually repeated multiple times in the case of H.245! */
11539 +
11540 +       (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
11541 +                                    tcplen - tcph->doff*4, 0);
11542 +
11543 +       tcph->check = 0;
11544 +       tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
11545 +                                  csum_partial((char *)tcph, tcph->doff*4,
11546 +                                          (*pskb)->csum));
11547 +       ip_send_check(iph);
11548 +
11549 +       return 1;
11550 +}
11551 +
11552 +static unsigned int h225_nat_help(struct ip_conntrack *ct,
11553 +                                 struct ip_conntrack_expect *exp,
11554 +                                 struct ip_nat_info *info,
11555 +                                 enum ip_conntrack_info ctinfo,
11556 +                                 unsigned int hooknum,
11557 +                                 struct sk_buff **pskb)
11558 +{
11559 +       int dir;
11560 +       struct ip_ct_h225_expect *exp_info;
11561 +       
11562 +       /* Only mangle things once: original direction in POST_ROUTING
11563 +          and reply direction on PRE_ROUTING. */
11564 +       dir = CTINFO2DIR(ctinfo);
11565 +       DEBUGP("nat_h323: dir %s at hook %s\n",
11566 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
11567 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
11568 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
11569 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
11570 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
11571 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
11572 +               DEBUGP("nat_h323: Not touching dir %s at hook %s\n",
11573 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
11574 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
11575 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
11576 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
11577 +               return NF_ACCEPT;
11578 +       }
11579 +
11580 +       if (!exp) {
11581 +               LOCK_BH(&ip_h323_lock);
11582 +               if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
11583 +                       UNLOCK_BH(&ip_h323_lock);
11584 +                       return NF_DROP;
11585 +               }
11586 +               UNLOCK_BH(&ip_h323_lock);
11587 +               return NF_ACCEPT;
11588 +       }
11589 +               
11590 +       exp_info = &exp->help.exp_h225_info;
11591 +
11592 +       LOCK_BH(&ip_h323_lock);
11593 +       if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
11594 +               UNLOCK_BH(&ip_h323_lock);
11595 +               return NF_DROP;
11596 +       }
11597 +       UNLOCK_BH(&ip_h323_lock);
11598 +
11599 +       return NF_ACCEPT;
11600 +}
11601 +
11602 +static struct ip_nat_helper h225 = 
11603 +       { { NULL, NULL },
11604 +         "H.225",                                      /* name */
11605 +         IP_NAT_HELPER_F_ALWAYS,                       /* flags */
11606 +         THIS_MODULE,                                  /* module */
11607 +         { { 0, { .tcp = { __constant_htons(H225_PORT) } } },  /* tuple */
11608 +           { 0, { 0 }, IPPROTO_TCP } },
11609 +         { { 0, { .tcp = { 0xFFFF } } },               /* mask */
11610 +           { 0, { 0 }, 0xFFFF } },
11611 +         h225_nat_help,                                /* helper */
11612 +         h225_nat_expected                             /* expectfn */
11613 +       };
11614 +
11615 +static int __init init(void)
11616 +{
11617 +       int ret;
11618 +       
11619 +       ret = ip_nat_helper_register(&h225);
11620 +
11621 +       if (ret != 0)
11622 +               printk("ip_nat_h323: cannot initialize the module!\n");
11623 +
11624 +       return ret;
11625 +}
11626 +
11627 +static void __exit fini(void)
11628 +{
11629 +       ip_nat_helper_unregister(&h225);
11630 +}
11631 +
11632 +module_init(init);
11633 +module_exit(fini);
11634 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_helper.c linux-2.4.20/net/ipv4/netfilter/ip_nat_helper.c
11635 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_helper.c Thu Nov 28 23:53:15 2002
11636 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_helper.c     Wed Sep 24 09:17:50 2003
11637 @@ -8,6 +8,9 @@
11638   *             - add support for SACK adjustment 
11639   *     14 Mar 2002 Harald Welte <laforge@gnumonks.org>:
11640   *             - merge SACK support into newnat API
11641 + *     16 Aug 2002 Brian J. Murrell <netfilter@interlinx.bc.ca>:
11642 + *             - make ip_nat_resize_packet more generic (TCP and UDP)
11643 + *             - add ip_nat_mangle_udp_packet
11644   */
11645  #include <linux/version.h>
11646  #include <linux/config.h>
11647 @@ -22,6 +25,7 @@
11648  #include <net/icmp.h>
11649  #include <net/ip.h>
11650  #include <net/tcp.h>
11651 +#include <net/udp.h>
11652  
11653  #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
11654  #define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
11655 @@ -51,18 +55,12 @@
11656                      int new_size)
11657  {
11658         struct iphdr *iph;
11659 -       struct tcphdr *tcph;
11660 -       void *data;
11661         int dir;
11662         struct ip_nat_seq *this_way, *other_way;
11663  
11664         DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
11665                 (*skb)->len, new_size);
11666  
11667 -       iph = (*skb)->nh.iph;
11668 -       tcph = (void *)iph + iph->ihl*4;
11669 -       data = (void *)tcph + tcph->doff*4;
11670 -
11671         dir = CTINFO2DIR(ctinfo);
11672  
11673         this_way = &ct->nat.info.seq[dir];
11674 @@ -84,37 +82,50 @@
11675         }
11676  
11677         iph = (*skb)->nh.iph;
11678 -       tcph = (void *)iph + iph->ihl*4;
11679 -       data = (void *)tcph + tcph->doff*4;
11680 +       if (iph->protocol == IPPROTO_TCP) {
11681 +               struct tcphdr *tcph = (void *)iph + iph->ihl*4;
11682  
11683 -       DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
11684 -       DUMP_OFFSET(this_way);
11685 +               DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
11686 +               DUMP_OFFSET(this_way);
11687  
11688 -       LOCK_BH(&ip_nat_seqofs_lock);
11689 +               LOCK_BH(&ip_nat_seqofs_lock);
11690  
11691 -       /* SYN adjust. If it's uninitialized, of this is after last 
11692 -        * correction, record it: we don't handle more than one 
11693 -        * adjustment in the window, but do deal with common case of a 
11694 -        * retransmit */
11695 -       if (this_way->offset_before == this_way->offset_after
11696 -           || before(this_way->correction_pos, ntohl(tcph->seq))) {
11697 -               this_way->correction_pos = ntohl(tcph->seq);
11698 -               this_way->offset_before = this_way->offset_after;
11699 -               this_way->offset_after = (int32_t)
11700 -                       this_way->offset_before + new_size - (*skb)->len;
11701 -       }
11702 +               /* SYN adjust. If it's uninitialized, of this is after last 
11703 +                * correction, record it: we don't handle more than one 
11704 +                * adjustment in the window, but do deal with common case of a 
11705 +                * retransmit */
11706 +               if (this_way->offset_before == this_way->offset_after
11707 +                   || before(this_way->correction_pos, ntohl(tcph->seq))) {
11708 +                       this_way->correction_pos = ntohl(tcph->seq);
11709 +                       this_way->offset_before = this_way->offset_after;
11710 +                       this_way->offset_after = (int32_t)
11711 +                               this_way->offset_before + new_size -
11712 +                               (*skb)->len;
11713 +               }
11714  
11715 -       UNLOCK_BH(&ip_nat_seqofs_lock);
11716 +               UNLOCK_BH(&ip_nat_seqofs_lock);
11717  
11718 -       DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
11719 -       DUMP_OFFSET(this_way);
11720 +               DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
11721 +               DUMP_OFFSET(this_way);
11722 +       }
11723         
11724         return 1;
11725  }
11726  
11727  
11728 -/* Generic function for mangling variable-length address changes inside
11729 - * NATed connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command in FTP).
11730 +/**
11731 + * ip_nat_mangle_tcp_packet - Mangle and potentially resize payload packet
11732 + * @skb: pointer to skb of packet on which we operate
11733 + * @ct: conntrack of the connection to which this packet belongs
11734 + * @ctinfo: conntrack_info of the connection to which this packet belongs
11735 + * @match_offset: offset in bytes where to-be-manipulated part starts
11736 + * @match_len: lenght of the to-be-manipulated part
11737 + * @rep_buffer: pointer to buffer containing replacement
11738 + * @rep_len: length of replacement
11739 + *
11740 + * Generic function for mangling fixed and variable-length changes inside
11741 + * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX command 
11742 + * in FTP).
11743   *
11744   * Takes care about all the nasty sequence number changes, checksumming,
11745   * skb enlargement, ...
11746 @@ -174,10 +185,11 @@
11747         tcph = (void *)iph + iph->ihl*4;
11748         data = (void *)tcph + tcph->doff*4;
11749  
11750 -       /* move post-replacement */
11751 -       memmove(data + match_offset + rep_len,
11752 -                data + match_offset + match_len,
11753 -                (*skb)->tail - (data + match_offset + match_len));
11754 +       if (rep_len != match_len)
11755 +               /* move post-replacement */
11756 +               memmove(data + match_offset + rep_len,
11757 +                       data + match_offset + match_len,
11758 +                       (*skb)->tail - (data + match_offset + match_len));
11759  
11760         /* insert data from buffer */
11761         memcpy(data + match_offset, rep_buffer, rep_len);
11762 @@ -207,6 +219,125 @@
11763  
11764         return 1;
11765  }
11766 +                       
11767 +/**
11768 + * ip_nat_mangle_udp_packet - Mangle and potentially resize payload packet
11769 + * @skb: pointer to skb of packet on which we operate
11770 + * @ct: conntrack of the connection to which this packet belongs
11771 + * @ctinfo: conntrack_info of the connection to which this packet belongs
11772 + * @match_offset: offset in bytes where to-be-manipulated part starts
11773 + * @match_len: lenght of the to-be-manipulated part
11774 + * @rep_buffer: pointer to buffer containing replacement
11775 + * @rep_len: length of replacement
11776 + *
11777 + * Generic function for mangling fixed and variable-length changes inside
11778 + * NATed TCP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
11779 + * commad in the Amanda protocol)
11780 + *
11781 + * Takes care about all the nasty sequence number changes, checksumming,
11782 + * skb enlargement, ...
11783 + *
11784 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
11785 + *
11786 + * */
11787 +
11788 +int 
11789 +ip_nat_mangle_udp_packet(struct sk_buff **skb,
11790 +                        struct ip_conntrack *ct,
11791 +                        enum ip_conntrack_info ctinfo,
11792 +                        unsigned int match_offset,
11793 +                        unsigned int match_len,
11794 +                        char *rep_buffer,
11795 +                        unsigned int rep_len)
11796 +{
11797 +       struct iphdr *iph = (*skb)->nh.iph;
11798 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
11799 +       unsigned char *data;
11800 +       u_int32_t udplen, newlen, newudplen;
11801 +
11802 +       udplen = (*skb)->len - iph->ihl*4;
11803 +       newudplen = udplen - match_len + rep_len;
11804 +       newlen = iph->ihl*4 + newudplen;
11805 +
11806 +       if (newlen > 65535) {
11807 +               if (net_ratelimit())
11808 +                       printk("ip_nat_mangle_udp_packet: nat'ed packet "
11809 +                               "exceeds maximum packet size\n");
11810 +               return 0;
11811 +       }
11812 +
11813 +       if ((*skb)->len != newlen) {
11814 +               if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) {
11815 +                       printk("resize_packet failed!!\n");
11816 +                       return 0;
11817 +               }
11818 +       }
11819 +
11820 +       /* Alexey says: if a hook changes _data_ ... it can break
11821 +          original packet sitting in tcp queue and this is fatal */
11822 +       if (skb_cloned(*skb)) {
11823 +               struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
11824 +               if (!nskb) {
11825 +                       if (net_ratelimit())
11826 +                               printk("Out of memory cloning TCP packet\n");
11827 +                       return 0;
11828 +               }
11829 +               /* Rest of kernel will get very unhappy if we pass it
11830 +                  a suddenly-orphaned skbuff */
11831 +               if ((*skb)->sk)
11832 +                       skb_set_owner_w(nskb, (*skb)->sk);
11833 +               kfree_skb(*skb);
11834 +               *skb = nskb;
11835 +       }
11836 +
11837 +       /* skb may be copied !! */
11838 +       iph = (*skb)->nh.iph;
11839 +       udph = (void *)iph + iph->ihl*4;
11840 +       data = (void *)udph + sizeof(struct udphdr);
11841 +
11842 +       if (rep_len != match_len)
11843 +               /* move post-replacement */
11844 +               memmove(data + match_offset + rep_len,
11845 +                       data + match_offset + match_len,
11846 +                       (*skb)->tail - (data + match_offset + match_len));
11847 +
11848 +       /* insert data from buffer */
11849 +       memcpy(data + match_offset, rep_buffer, rep_len);
11850 +
11851 +       /* update skb info */
11852 +       if (newlen > (*skb)->len) {
11853 +               DEBUGP("ip_nat_mangle_udp_packet: Extending packet by "
11854 +                       "%u to %u bytes\n", newlen - (*skb)->len, newlen);
11855 +               skb_put(*skb, newlen - (*skb)->len);
11856 +       } else {
11857 +               DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from "
11858 +                       "%u to %u bytes\n", (*skb)->len, newlen);
11859 +               skb_trim(*skb, newlen);
11860 +       }
11861 +
11862 +       /* update the length of the UDP and IP packets to the new values*/
11863 +       udph->len = htons((*skb)->len - iph->ihl*4);
11864 +       iph->tot_len = htons(newlen);
11865 +
11866 +       /* fix udp checksum if udp checksum was previously calculated */
11867 +       if ((*skb)->csum != 0) {
11868 +               (*skb)->csum = csum_partial((char *)udph +
11869 +                                           sizeof(struct udphdr),
11870 +                                           newudplen - sizeof(struct udphdr),
11871 +                                           0);
11872 +
11873 +               udph->check = 0;
11874 +               udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
11875 +                                               newudplen, IPPROTO_UDP,
11876 +                                               csum_partial((char *)udph,
11877 +                                                        sizeof(struct udphdr),
11878 +                                                       (*skb)->csum));
11879 +       }
11880 +
11881 +       ip_send_check(iph);
11882 +
11883 +       return 1;
11884 +}
11885  
11886  /* Adjust one found SACK option including checksum correction */
11887  static void
11888 @@ -255,54 +386,49 @@
11889  }
11890                         
11891  
11892 -/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */
11893 -static inline int
11894 +/* TCP SACK sequence number adjustment. */
11895 +static inline void
11896  ip_nat_sack_adjust(struct sk_buff *skb,
11897 -                       struct ip_conntrack *ct,
11898 -                       enum ip_conntrack_info ctinfo)
11899 +                  struct ip_conntrack *ct,
11900 +                  enum ip_conntrack_info ctinfo)
11901  {
11902 -       struct iphdr *iph;
11903         struct tcphdr *tcph;
11904 -       unsigned char *ptr;
11905 -       int length, dir, sack_adjusted = 0;
11906 +       unsigned char *ptr, *optend;
11907 +       unsigned int dir;
11908  
11909 -       iph = skb->nh.iph;
11910 -       tcph = (void *)iph + iph->ihl*4;
11911 -       length = (tcph->doff*4)-sizeof(struct tcphdr);
11912 +       tcph = (void *)skb->nh.iph + skb->nh.iph->ihl*4;
11913 +       optend = (unsigned char *)tcph + tcph->doff*4;
11914         ptr = (unsigned char *)(tcph+1);
11915  
11916         dir = CTINFO2DIR(ctinfo);
11917  
11918 -       while (length > 0) {
11919 -               int opcode = *ptr++;
11920 +       while (ptr < optend) {
11921 +               int opcode = ptr[0];
11922                 int opsize;
11923  
11924                 switch (opcode) {
11925                 case TCPOPT_EOL:
11926 -                       return !sack_adjusted;
11927 +                       return;
11928                 case TCPOPT_NOP:
11929 -                       length--;
11930 +                       ptr++;
11931                         continue;
11932                 default:
11933 -                       opsize = *ptr++;
11934 -                       if (opsize > length) /* no partial opts */
11935 -                               return !sack_adjusted;
11936 +                       opsize = ptr[1];
11937 +                        /* no partial opts */
11938 +                       if (ptr + opsize > optend || opsize < 2)
11939 +                               return;
11940                         if (opcode == TCPOPT_SACK) {
11941                                 /* found SACK */
11942                                 if((opsize >= (TCPOLEN_SACK_BASE
11943                                                +TCPOLEN_SACK_PERBLOCK)) &&
11944                                    !((opsize - TCPOLEN_SACK_BASE)
11945                                      % TCPOLEN_SACK_PERBLOCK))
11946 -                                       sack_adjust(tcph, ptr-2,
11947 +                                       sack_adjust(tcph, ptr,
11948                                                     &ct->nat.info.seq[!dir]);
11949 -                               
11950 -                               sack_adjusted = 1;
11951                         }
11952 -                       ptr += opsize-2;
11953 -                       length -= opsize;
11954 +                       ptr += opsize;
11955                 }
11956         }
11957 -       return !sack_adjusted;
11958  }
11959  
11960  /* TCP sequence number adjustment */
11961 @@ -363,6 +489,13 @@
11962  
11963  #define MODULE_MAX_NAMELEN             32
11964  
11965 +/**
11966 + * ip_nat_helper_register - Register NAT application helper
11967 + * @me: structure describing the helper
11968 + *
11969 + * This function is called by NAT application helpers to register
11970 + * themselves with the NAT core.
11971 + */
11972  int ip_nat_helper_register(struct ip_nat_helper *me)
11973  {
11974         int ret = 0;
11975 @@ -382,9 +515,9 @@
11976                         const char *tmp = me->me->name;
11977                         
11978                         if (strlen(tmp) + 6 > MODULE_MAX_NAMELEN) {
11979 -                               printk(__FUNCTION__ ": unable to "
11980 +                               printk("%s: unable to "
11981                                        "compute conntrack helper name "
11982 -                                      "from %s\n", tmp);
11983 +                                      "from %s\n", __FUNCTION__, tmp);
11984                                 return -EBUSY;
11985                         }
11986                         tmp += 6;
11987 @@ -430,6 +563,13 @@
11988         return ret;
11989  }
11990  
11991 +/**
11992 + * ip_nat_helper_unregister - Unregister NAT application helper
11993 + * @me: structure describing the helper
11994 + *
11995 + * This function is called by NAT application helpers to unregister
11996 + * themselves from the NAT core.
11997 + */
11998  void ip_nat_helper_unregister(struct ip_nat_helper *me)
11999  {
12000         int found = 0;
12001 @@ -467,7 +607,8 @@
12002                     && ct_helper->me) {
12003                         __MOD_DEC_USE_COUNT(ct_helper->me);
12004                 } else 
12005 -                       printk(__FUNCTION__ ": unable to decrement usage count"
12006 -                              " of conntrack helper %s\n", me->me->name);
12007 +                       printk("%s: unable to decrement usage count"
12008 +                              " of conntrack helper %s\n",
12009 +                              __FUNCTION__, me->me->name);
12010         }
12011  }
12012 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_irc.c linux-2.4.20/net/ipv4/netfilter/ip_nat_irc.c
12013 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_irc.c    Thu Nov 28 23:53:15 2002
12014 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_irc.c        Wed Sep 24 09:16:17 2003
12015 @@ -243,9 +243,6 @@
12016  
12017         for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
12018                 hlpr = &ip_nat_irc_helpers[i];
12019 -               memset(hlpr, 0,
12020 -                      sizeof(struct ip_nat_helper));
12021 -
12022                 hlpr->tuple.dst.protonum = IPPROTO_TCP;
12023                 hlpr->tuple.src.u.tcp.port = htons(ports[i]);
12024                 hlpr->mask.src.u.tcp.port = 0xFFFF;
12025 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_mms.c linux-2.4.20/net/ipv4/netfilter/ip_nat_mms.c
12026 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_mms.c    Thu Jan  1 00:00:00 1970
12027 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_mms.c        Wed Sep 24 09:17:48 2003
12028 @@ -0,0 +1,350 @@
12029 +/* MMS extension for TCP NAT alteration.
12030 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
12031 + * based on ip_nat_ftp.c and ip_nat_irc.c
12032 + *
12033 + * ip_nat_mms.c v0.3 2002-09-22
12034 + *
12035 + *      This program is free software; you can redistribute it and/or
12036 + *      modify it under the terms of the GNU General Public License
12037 + *      as published by the Free Software Foundation; either version
12038 + *      2 of the License, or (at your option) any later version.
12039 + *
12040 + *      Module load syntax:
12041 + *      insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
12042 + *
12043 + *      Please give the ports of all MMS servers You wish to connect to.
12044 + *      If you don't specify ports, the default will be TCP port 1755.
12045 + *
12046 + *      More info on MMS protocol, firewalls and NAT:
12047 + *      http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwmt/html/MMSFirewall.asp
12048 + *      http://www.microsoft.com/windows/windowsmedia/serve/firewall.asp
12049 + *
12050 + *      The SDP project people are reverse-engineering MMS:
12051 + *      http://get.to/sdp
12052 + */
12053 +
12054 +/* FIXME: issue with UDP & fragmentation with this URL: 
12055 +   http://www.cnn.com/video/world/2002/01/21/jb.shoe.bomb.cafe.cnn.low.asx 
12056 +   may be related to out-of-order first packets:
12057 +   basically the expectation is set up correctly, then the server sends
12058 +   a first UDP packet which is fragmented plus arrives out-of-order.
12059 +   the MASQUERADING firewall with ip_nat_mms loaded responds with
12060 +   an ICMP unreachable back to the server */
12061 +
12062 +#include <linux/module.h>
12063 +#include <linux/netfilter_ipv4.h>
12064 +#include <linux/ip.h>
12065 +#include <linux/tcp.h>
12066 +#include <net/tcp.h>
12067 +#include <linux/netfilter_ipv4/ip_nat.h>
12068 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
12069 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
12070 +#include <linux/netfilter_ipv4/ip_conntrack_mms.h>
12071 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
12072 +
12073 +#if 0 
12074 +#define DEBUGP printk
12075 +#define DUMP_BYTES(address, counter)                                \
12076 +({                                                                  \
12077 +       int temp_counter;                                           \
12078 +       for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
12079 +               DEBUGP("%u ", (u8)*(address+temp_counter));         \
12080 +       };                                                          \
12081 +       DEBUGP("\n");                                               \
12082 +})
12083 +#else
12084 +#define DEBUGP(format, args...)
12085 +#define DUMP_BYTES(address, counter)
12086 +#endif
12087 +
12088 +#define MAX_PORTS 8
12089 +static int ports[MAX_PORTS];
12090 +static int ports_c = 0;
12091 +
12092 +#ifdef MODULE_PARM
12093 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
12094 +#endif
12095 +
12096 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
12097 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
12098 +MODULE_LICENSE("GPL");
12099 +
12100 +DECLARE_LOCK_EXTERN(ip_mms_lock);
12101 +
12102 +/* FIXME: Time out? --RR */
12103 +
12104 +static int mms_data_fixup(const struct ip_ct_mms_expect *ct_mms_info,
12105 +                          struct ip_conntrack *ct,
12106 +                          struct sk_buff **pskb,
12107 +                          enum ip_conntrack_info ctinfo,
12108 +                          struct ip_conntrack_expect *expect)
12109 +{
12110 +       u_int32_t newip;
12111 +       struct ip_conntrack_tuple t;
12112 +       struct iphdr *iph = (*pskb)->nh.iph;
12113 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
12114 +       char *data = (char *)tcph + tcph->doff * 4;
12115 +       int i, j, k, port;
12116 +       u_int16_t mms_proto;
12117 +
12118 +       u_int32_t *mms_chunkLenLV    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLV_OFFSET);
12119 +       u_int32_t *mms_chunkLenLM    = (u_int32_t *)(data + MMS_SRV_CHUNKLENLM_OFFSET);
12120 +       u_int32_t *mms_messageLength = (u_int32_t *)(data + MMS_SRV_MESSAGELENGTH_OFFSET);
12121 +
12122 +       int zero_padding;
12123 +
12124 +       char buffer[28];         /* "\\255.255.255.255\UDP\65635" * 2 (for unicode) */
12125 +       char unicode_buffer[75]; /* 27*2 (unicode) + 20 + 1 */
12126 +       char proto_string[6];
12127 +       
12128 +       MUST_BE_LOCKED(&ip_mms_lock);
12129 +
12130 +       /* what was the protocol again ? */
12131 +       mms_proto = expect->tuple.dst.protonum;
12132 +       sprintf(proto_string, "%u", mms_proto);
12133 +       
12134 +       DEBUGP("ip_nat_mms: mms_data_fixup: info (seq %u + %u) in %u, proto %s\n",
12135 +              expect->seq, ct_mms_info->len, ntohl(tcph->seq),
12136 +              mms_proto == IPPROTO_UDP ? "UDP"
12137 +              : mms_proto == IPPROTO_TCP ? "TCP":proto_string);
12138 +       
12139 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
12140 +
12141 +       /* Alter conntrack's expectations. */
12142 +       t = expect->tuple;
12143 +       t.dst.ip = newip;
12144 +       for (port = ct_mms_info->port; port != 0; port++) {
12145 +               t.dst.u.tcp.port = htons(port);
12146 +               if (ip_conntrack_change_expect(expect, &t) == 0) {
12147 +                       DEBUGP("ip_nat_mms: mms_data_fixup: using port %d\n", port);
12148 +                       break;
12149 +               }
12150 +       }
12151 +       
12152 +       if(port == 0)
12153 +               return 0;
12154 +
12155 +       sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
12156 +               NIPQUAD(newip),
12157 +               expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
12158 +               : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
12159 +               port);
12160 +       DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
12161 +       
12162 +       memset(unicode_buffer, 0, sizeof(char)*75);
12163 +
12164 +       for (i=0; i<strlen(buffer); ++i)
12165 +               *(unicode_buffer+i*2)=*(buffer+i);
12166 +       
12167 +       DEBUGP("ip_nat_mms: mms_data_fixup: padding: %u len: %u\n", ct_mms_info->padding, ct_mms_info->len);
12168 +       DEBUGP("ip_nat_mms: mms_data_fixup: offset: %u\n", MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len);
12169 +       DUMP_BYTES(data+MMS_SRV_UNICODE_STRING_OFFSET, 60);
12170 +       
12171 +       /* add end of packet to it */
12172 +       for (j=0; j<ct_mms_info->padding; ++j) {
12173 +               DEBUGP("ip_nat_mms: mms_data_fixup: i=%u j=%u byte=%u\n", 
12174 +                      i, j, (u8)*(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j));
12175 +               *(unicode_buffer+i*2+j) = *(data+MMS_SRV_UNICODE_STRING_OFFSET+ct_mms_info->len+j);
12176 +       }
12177 +
12178 +       /* pad with zeroes at the end ? see explanation of weird math below */
12179 +       zero_padding = (8-(strlen(buffer)*2 + ct_mms_info->padding + 4)%8)%8;
12180 +       for (k=0; k<zero_padding; ++k)
12181 +               *(unicode_buffer+i*2+j+k)= (char)0;
12182 +       
12183 +       DEBUGP("ip_nat_mms: mms_data_fixup: zero_padding = %u\n", zero_padding);
12184 +       DEBUGP("ip_nat_mms: original=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
12185 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
12186 +       
12187 +       /* explanation, before I forget what I did:
12188 +          strlen(buffer)*2 + ct_mms_info->padding + 4 must be divisable by 8;
12189 +          divide by 8 and add 3 to compute the mms_chunkLenLM field,
12190 +          but note that things may have to be padded with zeroes to align by 8 
12191 +          bytes, hence we add 7 and divide by 8 to get the correct length */ 
12192 +       *mms_chunkLenLM    = (u_int32_t) (3+(strlen(buffer)*2+ct_mms_info->padding+11)/8);
12193 +       *mms_chunkLenLV    = *mms_chunkLenLM+2;
12194 +       *mms_messageLength = *mms_chunkLenLV*8;
12195 +       
12196 +       DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
12197 +              *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
12198 +       
12199 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
12200 +                                expect->seq - ntohl(tcph->seq),
12201 +                                ct_mms_info->len + ct_mms_info->padding, unicode_buffer,
12202 +                                strlen(buffer)*2 + ct_mms_info->padding + zero_padding);
12203 +       DUMP_BYTES(unicode_buffer, 60);
12204 +       
12205 +       return 1;
12206 +}
12207 +
12208 +static unsigned int
12209 +mms_nat_expected(struct sk_buff **pskb,
12210 +                 unsigned int hooknum,
12211 +                 struct ip_conntrack *ct,
12212 +                 struct ip_nat_info *info)
12213 +{
12214 +       struct ip_nat_multi_range mr;
12215 +       u_int32_t newdstip, newsrcip, newip;
12216 +
12217 +       struct ip_conntrack *master = master_ct(ct);
12218 +
12219 +       IP_NF_ASSERT(info);
12220 +       IP_NF_ASSERT(master);
12221 +
12222 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
12223 +
12224 +       DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
12225 +
12226 +       newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
12227 +       newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
12228 +       DEBUGP("ip_nat_mms: mms_nat_expected: hook %s: newsrc->newdst %u.%u.%u.%u->%u.%u.%u.%u\n",
12229 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
12230 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
12231 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
12232 +              NIPQUAD(newsrcip), NIPQUAD(newdstip));
12233 +
12234 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
12235 +               newip = newsrcip;
12236 +       else
12237 +               newip = newdstip;
12238 +
12239 +       DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
12240 +
12241 +       mr.rangesize = 1;
12242 +       /* We don't want to manip the per-protocol, just the IPs. */
12243 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
12244 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
12245 +
12246 +       return ip_nat_setup_info(ct, &mr, hooknum);
12247 +}
12248 +
12249 +
12250 +static unsigned int mms_nat_help(struct ip_conntrack *ct,
12251 +                        struct ip_conntrack_expect *exp,
12252 +                        struct ip_nat_info *info,
12253 +                        enum ip_conntrack_info ctinfo,
12254 +                        unsigned int hooknum,
12255 +                        struct sk_buff **pskb)
12256 +{
12257 +       struct iphdr *iph = (*pskb)->nh.iph;
12258 +       struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
12259 +       unsigned int datalen;
12260 +       int dir;
12261 +       struct ip_ct_mms_expect *ct_mms_info;
12262 +
12263 +       if (!exp)
12264 +               DEBUGP("ip_nat_mms: no exp!!");
12265 +
12266 +       ct_mms_info = &exp->help.exp_mms_info;
12267 +       
12268 +       /* Only mangle things once: original direction in POST_ROUTING
12269 +          and reply direction on PRE_ROUTING. */
12270 +       dir = CTINFO2DIR(ctinfo);
12271 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
12272 +           ||(hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
12273 +               DEBUGP("ip_nat_mms: mms_nat_help: not touching dir %s at hook %s\n",
12274 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
12275 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
12276 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
12277 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
12278 +               return NF_ACCEPT;
12279 +       }
12280 +       DEBUGP("ip_nat_mms: mms_nat_help: beyond not touching (dir %s at hook %s)\n",
12281 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
12282 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
12283 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
12284 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
12285 +       
12286 +       datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
12287 +       
12288 +       DEBUGP("ip_nat_mms: mms_nat_help: %u+%u=%u %u %u\n", exp->seq, ct_mms_info->len,
12289 +              exp->seq + ct_mms_info->len,
12290 +              ntohl(tcph->seq),
12291 +              ntohl(tcph->seq) + datalen);
12292 +       
12293 +       LOCK_BH(&ip_mms_lock);
12294 +       /* Check wether the whole IP/proto/port pattern is carried in the payload */
12295 +       if (between(exp->seq + ct_mms_info->len,
12296 +           ntohl(tcph->seq),
12297 +           ntohl(tcph->seq) + datalen)) {
12298 +               if (!mms_data_fixup(ct_mms_info, ct, pskb, ctinfo, exp)) {
12299 +                       UNLOCK_BH(&ip_mms_lock);
12300 +                       return NF_DROP;
12301 +               }
12302 +       } else {
12303 +               /* Half a match?  This means a partial retransmisison.
12304 +                  It's a cracker being funky. */
12305 +               if (net_ratelimit()) {
12306 +                       printk("ip_nat_mms: partial packet %u/%u in %u/%u\n",
12307 +                              exp->seq, ct_mms_info->len,
12308 +                              ntohl(tcph->seq),
12309 +                              ntohl(tcph->seq) + datalen);
12310 +               }
12311 +               UNLOCK_BH(&ip_mms_lock);
12312 +               return NF_DROP;
12313 +       }
12314 +       UNLOCK_BH(&ip_mms_lock);
12315 +       
12316 +       return NF_ACCEPT;
12317 +}
12318 +
12319 +static struct ip_nat_helper mms[MAX_PORTS];
12320 +static char mms_names[MAX_PORTS][10];
12321 +
12322 +/* Not __exit: called from init() */
12323 +static void fini(void)
12324 +{
12325 +       int i;
12326 +
12327 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
12328 +               DEBUGP("ip_nat_mms: unregistering helper for port %d\n", ports[i]);
12329 +               ip_nat_helper_unregister(&mms[i]);
12330 +       }
12331 +}
12332 +
12333 +static int __init init(void)
12334 +{
12335 +       int i, ret = 0;
12336 +       char *tmpname;
12337 +
12338 +       if (ports[0] == 0)
12339 +               ports[0] = MMS_PORT;
12340 +
12341 +       for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
12342 +
12343 +               memset(&mms[i], 0, sizeof(struct ip_nat_helper));
12344 +
12345 +               mms[i].tuple.dst.protonum = IPPROTO_TCP;
12346 +               mms[i].tuple.src.u.tcp.port = htons(ports[i]);
12347 +               mms[i].mask.dst.protonum = 0xFFFF;
12348 +               mms[i].mask.src.u.tcp.port = 0xFFFF;
12349 +               mms[i].help = mms_nat_help;
12350 +               mms[i].me = THIS_MODULE;
12351 +               mms[i].flags = 0;
12352 +               mms[i].expect = mms_nat_expected;
12353 +
12354 +               tmpname = &mms_names[i][0];
12355 +               if (ports[i] == MMS_PORT)
12356 +                       sprintf(tmpname, "mms");
12357 +               else
12358 +                       sprintf(tmpname, "mms-%d", i);
12359 +               mms[i].name = tmpname;
12360 +
12361 +               DEBUGP("ip_nat_mms: register helper for port %d\n",
12362 +                               ports[i]);
12363 +               ret = ip_nat_helper_register(&mms[i]);
12364 +
12365 +               if (ret) {
12366 +                       printk("ip_nat_mms: error registering "
12367 +                              "helper for port %d\n", ports[i]);
12368 +                       fini();
12369 +                       return ret;
12370 +               }
12371 +               ports_c++;
12372 +       }
12373 +
12374 +       return ret;
12375 +}
12376 +
12377 +module_init(init);
12378 +module_exit(fini);
12379 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_pptp.c linux-2.4.20/net/ipv4/netfilter/ip_nat_pptp.c
12380 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_pptp.c   Thu Jan  1 00:00:00 1970
12381 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_pptp.c       Wed Sep 24 09:17:55 2003
12382 @@ -0,0 +1,475 @@
12383 +/*
12384 + * ip_nat_pptp.c       - Version 1.5
12385 + *
12386 + * NAT support for PPTP (Point to Point Tunneling Protocol).
12387 + * PPTP is a a protocol for creating virtual private networks.
12388 + * It is a specification defined by Microsoft and some vendors
12389 + * working with Microsoft.  PPTP is built on top of a modified
12390 + * version of the Internet Generic Routing Encapsulation Protocol.
12391 + * GRE is defined in RFC 1701 and RFC 1702.  Documentation of
12392 + * PPTP can be found in RFC 2637
12393 + *
12394 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
12395 + *
12396 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
12397 + *
12398 + * TODO: - Support for multiple calls within one session
12399 + *        (needs netfilter newnat code)
12400 + *      - NAT to a unique tuple, not to TCP source port
12401 + *        (needs netfilter tuple reservation)
12402 + *
12403 + * Changes:
12404 + *     2002-02-10 - Version 1.3
12405 + *       - Use ip_nat_mangle_tcp_packet() because of cloned skb's
12406 + *        in local connections (Philip Craig <philipc@snapgear.com>)
12407 + *       - add checks for magicCookie and pptp version
12408 + *       - make argument list of pptp_{out,in}bound_packet() shorter
12409 + *       - move to C99 style initializers
12410 + *       - print version number at module loadtime
12411 + *     2003-09-22 - Version 1.5
12412 + *       - use SNATed tcp sourceport as callid, since we get called before
12413 + *         TCP header is mangled (Philip Craig <philipc@snapgear.com>)
12414 + * 
12415 + */
12416 +
12417 +#include <linux/config.h>
12418 +#include <linux/module.h>
12419 +#include <linux/ip.h>
12420 +#include <linux/tcp.h>
12421 +#include <net/tcp.h>
12422 +#include <linux/netfilter_ipv4/ip_nat.h>
12423 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
12424 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
12425 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
12426 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
12427 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
12428 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
12429 +
12430 +#define IP_NAT_PPTP_VERSION "1.5"
12431 +
12432 +MODULE_LICENSE("GPL");
12433 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
12434 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
12435 +
12436 +
12437 +#if 0
12438 +#include "ip_conntrack_pptp_priv.h"
12439 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
12440 +                                      ": " format, ## args)
12441 +#else
12442 +#define DEBUGP(format, args...)
12443 +#endif
12444 +
12445 +static unsigned int
12446 +pptp_nat_expected(struct sk_buff **pskb,
12447 +                 unsigned int hooknum,
12448 +                 struct ip_conntrack *ct,
12449 +                 struct ip_nat_info *info)
12450 +{
12451 +       struct ip_conntrack *master = master_ct(ct);
12452 +       struct ip_nat_multi_range mr;
12453 +       struct ip_ct_pptp_master *ct_pptp_info;
12454 +       struct ip_nat_pptp *nat_pptp_info;
12455 +       u_int32_t newip, newcid;
12456 +       int ret;
12457 +
12458 +       IP_NF_ASSERT(info);
12459 +       IP_NF_ASSERT(master);
12460 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
12461 +
12462 +       DEBUGP("we have a connection!\n");
12463 +
12464 +       LOCK_BH(&ip_pptp_lock);
12465 +       ct_pptp_info = &master->help.ct_pptp_info;
12466 +       nat_pptp_info = &master->nat.help.nat_pptp_info;
12467 +
12468 +       /* need to alter GRE tuple because conntrack expectfn() used 'wrong'
12469 +        * (unmanipulated) values */
12470 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
12471 +               DEBUGP("completing tuples with NAT info \n");
12472 +               /* we can do this, since we're unconfirmed */
12473 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
12474 +                       htonl(ct_pptp_info->pac_call_id)) {     
12475 +                       /* assume PNS->PAC */
12476 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
12477 +                               htonl(nat_pptp_info->pns_call_id);
12478 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
12479 +                               htonl(nat_pptp_info->pns_call_id);
12480 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
12481 +                       newcid = htonl(nat_pptp_info->pac_call_id);
12482 +               } else {
12483 +                       /* assume PAC->PNS */
12484 +                       ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.gre.key =
12485 +                               htonl(nat_pptp_info->pac_call_id);
12486 +                       ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.gre.key =
12487 +                               htonl(nat_pptp_info->pac_call_id);
12488 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
12489 +                       newcid = htonl(nat_pptp_info->pns_call_id);
12490 +               }
12491 +       } else {
12492 +               if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.gre.key ==
12493 +                       htonl(ct_pptp_info->pac_call_id)) {     
12494 +                       /* assume PNS->PAC */
12495 +                       newip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
12496 +                       newcid = htonl(ct_pptp_info->pns_call_id);
12497 +               }
12498 +               else {
12499 +                       /* assume PAC->PNS */
12500 +                       newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
12501 +                       newcid = htonl(ct_pptp_info->pac_call_id);
12502 +               }
12503 +       }
12504 +
12505 +       mr.rangesize = 1;
12506 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED;
12507 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
12508 +       mr.range[0].min = mr.range[0].max = 
12509 +               ((union ip_conntrack_manip_proto ) { newcid }); 
12510 +       DEBUGP("change ip to %u.%u.%u.%u\n", 
12511 +               NIPQUAD(newip));
12512 +       DEBUGP("change key to 0x%x\n", ntohl(newcid));
12513 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
12514 +
12515 +       UNLOCK_BH(&ip_pptp_lock);
12516 +
12517 +       return ret;
12518 +
12519 +}
12520 +
12521 +/* outbound packets == from PNS to PAC */
12522 +static inline unsigned int
12523 +pptp_outbound_pkt(struct sk_buff **pskb,
12524 +                 struct ip_conntrack *ct,
12525 +                 enum ip_conntrack_info ctinfo,
12526 +                 struct ip_conntrack_expect *exp)
12527 +
12528 +{
12529 +       struct iphdr *iph = (*pskb)->nh.iph;
12530 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
12531 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
12532 +                                       ((void *)tcph + tcph->doff*4);
12533 +
12534 +       struct PptpControlHeader *ctlh;
12535 +       union pptp_ctrl_union pptpReq;
12536 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
12537 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
12538 +
12539 +       u_int16_t msg, *cid = NULL, new_callid;
12540 +
12541 +       /* FIXME: size checks !!! */
12542 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
12543 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
12544 +
12545 +       new_callid = htons(ct_pptp_info->pns_call_id);
12546 +       
12547 +       switch (msg = ntohs(ctlh->messageType)) {
12548 +               case PPTP_OUT_CALL_REQUEST:
12549 +                       cid = &pptpReq.ocreq->callID;
12550 +                       /* FIXME: ideally we would want to reserve a call ID
12551 +                        * here.  current netfilter NAT core is not able to do
12552 +                        * this :( For now we use TCP source port. This breaks
12553 +                        * multiple calls within one control session */
12554 +
12555 +                       /* save original call ID in nat_info */
12556 +                       nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
12557 +
12558 +                       /* don't use tcph->source since we are at a DSTmanip
12559 +                        * hook (e.g. PREROUTING) and pkt is not mangled yet */
12560 +                       new_callid = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.tcp.port;
12561 +
12562 +                       /* save new call ID in ct info */
12563 +                       ct_pptp_info->pns_call_id = ntohs(new_callid);
12564 +                       break;
12565 +               case PPTP_IN_CALL_REPLY:
12566 +                       cid = &pptpReq.icreq->callID;
12567 +                       break;
12568 +               case PPTP_CALL_CLEAR_REQUEST:
12569 +                       cid = &pptpReq.clrreq->callID;
12570 +                       break;
12571 +               default:
12572 +                       DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
12573 +                             (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
12574 +                       /* fall through */
12575 +
12576 +               case PPTP_SET_LINK_INFO:
12577 +                       /* only need to NAT in case PAC is behind NAT box */
12578 +               case PPTP_START_SESSION_REQUEST:
12579 +               case PPTP_START_SESSION_REPLY:
12580 +               case PPTP_STOP_SESSION_REQUEST:
12581 +               case PPTP_STOP_SESSION_REPLY:
12582 +               case PPTP_ECHO_REQUEST:
12583 +               case PPTP_ECHO_REPLY:
12584 +                       /* no need to alter packet */
12585 +                       return NF_ACCEPT;
12586 +       }
12587 +
12588 +       IP_NF_ASSERT(cid);
12589 +
12590 +       DEBUGP("altering call id from 0x%04x to 0x%04x\n",
12591 +               ntohs(*cid), ntohs(new_callid));
12592 +
12593 +       /* mangle packet */
12594 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)cid - (void *)pptph,
12595 +                                sizeof(new_callid), (char *)&new_callid,
12596 +                                sizeof(new_callid));
12597 +
12598 +       return NF_ACCEPT;
12599 +}
12600 +
12601 +/* inbound packets == from PAC to PNS */
12602 +static inline unsigned int
12603 +pptp_inbound_pkt(struct sk_buff **pskb,
12604 +                struct ip_conntrack *ct,
12605 +                enum ip_conntrack_info ctinfo,
12606 +                struct ip_conntrack_expect *oldexp)
12607 +{
12608 +       struct iphdr *iph = (*pskb)->nh.iph;
12609 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
12610 +       struct pptp_pkt_hdr *pptph = (struct pptp_pkt_hdr *) 
12611 +                                       ((void *)tcph + tcph->doff*4);
12612 +
12613 +       struct PptpControlHeader *ctlh;
12614 +       union pptp_ctrl_union pptpReq;
12615 +       struct ip_ct_pptp_master *ct_pptp_info = &ct->help.ct_pptp_info;
12616 +       struct ip_nat_pptp *nat_pptp_info = &ct->nat.help.nat_pptp_info;
12617 +
12618 +       u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
12619 +       u_int32_t old_dst_ip;
12620 +
12621 +       struct ip_conntrack_tuple t, inv_t;
12622 +       struct ip_conntrack_tuple *orig_t, *reply_t;
12623 +
12624 +       /* FIXME: size checks !!! */
12625 +       ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
12626 +       pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
12627 +
12628 +       new_pcid = htons(nat_pptp_info->pns_call_id);
12629 +
12630 +       switch (msg = ntohs(ctlh->messageType)) {
12631 +       case PPTP_OUT_CALL_REPLY:
12632 +               pcid = &pptpReq.ocack->peersCallID;     
12633 +               cid = &pptpReq.ocack->callID;
12634 +               if (!oldexp) {
12635 +                       DEBUGP("outcall but no expectation\n");
12636 +                       break;
12637 +               }
12638 +               old_dst_ip = oldexp->tuple.dst.ip;
12639 +               t = oldexp->tuple;
12640 +               invert_tuplepr(&inv_t, &t);
12641 +
12642 +               /* save original PAC call ID in nat_info */
12643 +               nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
12644 +
12645 +               /* alter expectation */
12646 +               orig_t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
12647 +               reply_t = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
12648 +               if (t.src.ip == orig_t->src.ip && t.dst.ip == orig_t->dst.ip) {
12649 +                       /* expectation for PNS->PAC direction */
12650 +                       t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
12651 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
12652 +                       inv_t.src.ip = reply_t->src.ip;
12653 +                       inv_t.dst.ip = reply_t->dst.ip;
12654 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
12655 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
12656 +               } else {
12657 +                       /* expectation for PAC->PNS direction */
12658 +                       t.src.u.gre.key = htonl(nat_pptp_info->pac_call_id);
12659 +                       t.dst.u.gre.key = htonl(ct_pptp_info->pns_call_id);
12660 +                       inv_t.src.ip = orig_t->src.ip;
12661 +                       inv_t.dst.ip = orig_t->dst.ip;
12662 +                       inv_t.src.u.gre.key = htonl(nat_pptp_info->pns_call_id);
12663 +                       inv_t.dst.u.gre.key = htonl(ct_pptp_info->pac_call_id);
12664 +               }
12665 +
12666 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
12667 +                       DEBUGP("successfully changed expect\n");
12668 +               } else {
12669 +                       DEBUGP("can't change expect\n");
12670 +               }
12671 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_orig, &t);
12672 +               ip_ct_gre_keymap_change(oldexp->proto.gre.keymap_reply, &inv_t);
12673 +               break;
12674 +       case PPTP_IN_CALL_CONNECT:
12675 +               pcid = &pptpReq.iccon->peersCallID;
12676 +               if (!oldexp)
12677 +                       break;
12678 +               old_dst_ip = oldexp->tuple.dst.ip;
12679 +               t = oldexp->tuple;
12680 +
12681 +               /* alter expectation, no need for callID */
12682 +               if (t.dst.ip == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip) {
12683 +                       /* expectation for PNS->PAC direction */
12684 +                       t.src.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
12685 +               } else {
12686 +                       /* expectation for PAC->PNS direction */
12687 +                       t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
12688 +               }
12689 +
12690 +               if (!ip_conntrack_change_expect(oldexp, &t)) {
12691 +                       DEBUGP("successfully changed expect\n");
12692 +               } else {
12693 +                       DEBUGP("can't change expect\n");
12694 +               }
12695 +               break;
12696 +       case PPTP_IN_CALL_REQUEST:
12697 +               /* only need to nat in case PAC is behind NAT box */
12698 +               break;
12699 +       case PPTP_WAN_ERROR_NOTIFY:
12700 +               pcid = &pptpReq.wanerr->peersCallID;
12701 +               break;
12702 +       case PPTP_CALL_DISCONNECT_NOTIFY:
12703 +               pcid = &pptpReq.disc->callID;
12704 +               break;
12705 +
12706 +       default:
12707 +               DEBUGP("unknown inbound packet %s\n",
12708 +                       (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
12709 +               /* fall through */
12710 +
12711 +       case PPTP_START_SESSION_REQUEST:
12712 +       case PPTP_START_SESSION_REPLY:
12713 +       case PPTP_STOP_SESSION_REQUEST:
12714 +       case PPTP_STOP_SESSION_REPLY:
12715 +       case PPTP_ECHO_REQUEST:
12716 +       case PPTP_ECHO_REPLY:
12717 +               /* no need to alter packet */
12718 +               return NF_ACCEPT;
12719 +       }
12720 +
12721 +       /* mangle packet */
12722 +       IP_NF_ASSERT(pcid);
12723 +       DEBUGP("altering peer call id from 0x%04x to 0x%04x\n",
12724 +               ntohs(*pcid), ntohs(new_pcid));
12725 +       ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, (void *)pcid - (void *)pptph,
12726 +                                sizeof(new_pcid), (char *)&new_pcid, 
12727 +                                sizeof(new_pcid));
12728 +
12729 +       if (new_cid) {
12730 +               IP_NF_ASSERT(cid);
12731 +               DEBUGP("altering call id from 0x%04x to 0x%04x\n",
12732 +                       ntohs(*cid), ntohs(new_cid));
12733 +               ip_nat_mangle_tcp_packet(pskb, ct, ctinfo, 
12734 +                                        (void *)cid - (void *)pptph, 
12735 +                                        sizeof(new_cid), (char *)&new_cid, 
12736 +                                        sizeof(new_cid));
12737 +       }
12738 +
12739 +       /* great, at least we don't need to resize packets */
12740 +       return NF_ACCEPT;
12741 +}
12742 +
12743 +
12744 +static unsigned int tcp_help(struct ip_conntrack *ct,
12745 +                            struct ip_conntrack_expect *exp,
12746 +                            struct ip_nat_info *info,
12747 +                            enum ip_conntrack_info ctinfo,
12748 +                            unsigned int hooknum, struct sk_buff **pskb)
12749 +{
12750 +       struct iphdr *iph = (*pskb)->nh.iph;
12751 +       struct tcphdr *tcph = (void *) iph + iph->ihl*4;
12752 +       unsigned int datalen = (*pskb)->len - iph->ihl*4 - tcph->doff*4;
12753 +       struct pptp_pkt_hdr *pptph;
12754 +
12755 +       int dir;
12756 +
12757 +       DEBUGP("entering\n");
12758 +
12759 +       /* Only mangle things once: DST for original direction
12760 +          and SRC for reply direction. */
12761 +       dir = CTINFO2DIR(ctinfo);
12762 +       if (!((HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC
12763 +            && dir == IP_CT_DIR_ORIGINAL)
12764 +             || (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST
12765 +                 && dir == IP_CT_DIR_REPLY))) {
12766 +               DEBUGP("Not touching dir %s at hook %s\n",
12767 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
12768 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
12769 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
12770 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT"
12771 +                      : hooknum == NF_IP_LOCAL_IN ? "INPUT" : "???");
12772 +               return NF_ACCEPT;
12773 +       }
12774 +
12775 +       /* if packet is too small, just skip it */
12776 +       if (datalen < sizeof(struct pptp_pkt_hdr)+
12777 +                     sizeof(struct PptpControlHeader)) {
12778 +               DEBUGP("pptp packet too short\n");
12779 +               return NF_ACCEPT;       
12780 +       }
12781 +
12782 +       pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
12783 +
12784 +       /* if it's not a control message, we can't handle it */
12785 +       if (ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
12786 +           ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
12787 +               DEBUGP("not a pptp control packet\n");
12788 +               return NF_ACCEPT;
12789 +       }
12790 +
12791 +       LOCK_BH(&ip_pptp_lock);
12792 +
12793 +       if (dir == IP_CT_DIR_ORIGINAL) {
12794 +               /* reuqests sent by client to server (PNS->PAC) */
12795 +               pptp_outbound_pkt(pskb, ct, ctinfo, exp);
12796 +       } else {
12797 +               /* response from the server to the client (PAC->PNS) */
12798 +               pptp_inbound_pkt(pskb, ct, ctinfo, exp);
12799 +       }
12800 +
12801 +       UNLOCK_BH(&ip_pptp_lock);
12802 +
12803 +       return NF_ACCEPT;
12804 +}
12805 +
12806 +/* nat helper struct for control connection */
12807 +static struct ip_nat_helper pptp_tcp_helper = { 
12808 +       .list = { NULL, NULL },
12809 +       .name = "pptp", 
12810 +       .flags = IP_NAT_HELPER_F_ALWAYS, 
12811 +       .me = THIS_MODULE,
12812 +       .tuple = { .src = { .ip = 0, 
12813 +                           .u = { .tcp = { .port = 
12814 +                                       __constant_htons(PPTP_CONTROL_PORT) } 
12815 +                                } 
12816 +                         },
12817 +                  .dst = { .ip = 0, 
12818 +                           .u = { .all = 0 }, 
12819 +                           .protonum = IPPROTO_TCP 
12820 +                         } 
12821 +                },
12822 +
12823 +       .mask = { .src = { .ip = 0, 
12824 +                          .u = { .tcp = { .port = 0xFFFF } } 
12825 +                        },
12826 +                 .dst = { .ip = 0, 
12827 +                          .u = { .all = 0 }, 
12828 +                          .protonum = 0xFFFF 
12829 +                        } 
12830 +               },
12831 +       .help = tcp_help, 
12832 +       .expect = pptp_nat_expected 
12833 +};
12834 +
12835 +                         
12836 +static int __init init(void)
12837 +{
12838 +       DEBUGP("%s: registering NAT helper\n", __FILE__);
12839 +       if (ip_nat_helper_register(&pptp_tcp_helper)) {
12840 +               printk(KERN_ERR "Unable to register NAT application helper "
12841 +                               "for pptp\n");
12842 +               return -EIO;
12843 +       }
12844 +
12845 +       printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
12846 +       return 0;
12847 +}
12848 +
12849 +static void __exit fini(void)
12850 +{
12851 +       DEBUGP("cleanup_module\n" );
12852 +       ip_nat_helper_unregister(&pptp_tcp_helper);
12853 +       printk("ip_nat_pptp version %s unloaded\n", IP_NAT_PPTP_VERSION);
12854 +}
12855 +
12856 +module_init(init);
12857 +module_exit(fini);
12858 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_proto_gre.c linux-2.4.20/net/ipv4/netfilter/ip_nat_proto_gre.c
12859 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_proto_gre.c      Thu Jan  1 00:00:00 1970
12860 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_proto_gre.c  Wed Sep 24 09:17:55 2003
12861 @@ -0,0 +1,225 @@
12862 +/*
12863 + * ip_nat_proto_gre.c - Version 1.2
12864 + *
12865 + * NAT protocol helper module for GRE.
12866 + *
12867 + * GRE is a generic encapsulation protocol, which is generally not very
12868 + * suited for NAT, as it has no protocol-specific part as port numbers.
12869 + *
12870 + * It has an optional key field, which may help us distinguishing two 
12871 + * connections between the same two hosts.
12872 + *
12873 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784 
12874 + *
12875 + * PPTP is built on top of a modified version of GRE, and has a mandatory
12876 + * field called "CallID", which serves us for the same purpose as the key
12877 + * field in plain GRE.
12878 + *
12879 + * Documentation about PPTP can be found in RFC 2637
12880 + *
12881 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
12882 + *
12883 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
12884 + *
12885 + */
12886 +
12887 +#include <linux/config.h>
12888 +#include <linux/module.h>
12889 +#include <linux/ip.h>
12890 +#include <linux/netfilter_ipv4/ip_nat.h>
12891 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
12892 +#include <linux/netfilter_ipv4/ip_nat_protocol.h>
12893 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
12894 +
12895 +MODULE_LICENSE("GPL");
12896 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
12897 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
12898 +
12899 +#if 0
12900 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
12901 +                                      ": " format, ## args)
12902 +#else
12903 +#define DEBUGP(x, args...)
12904 +#endif
12905 +
12906 +/* is key in given range between min and max */
12907 +static int
12908 +gre_in_range(const struct ip_conntrack_tuple *tuple,
12909 +            enum ip_nat_manip_type maniptype,
12910 +            const union ip_conntrack_manip_proto *min,
12911 +            const union ip_conntrack_manip_proto *max)
12912 +{
12913 +       u_int32_t key;
12914 +
12915 +       if (maniptype == IP_NAT_MANIP_SRC)
12916 +               key = tuple->src.u.gre.key;
12917 +       else
12918 +               key = tuple->dst.u.gre.key;
12919 +
12920 +       return ntohl(key) >= ntohl(min->gre.key)
12921 +               && ntohl(key) <= ntohl(max->gre.key);
12922 +}
12923 +
12924 +/* generate unique tuple ... */
12925 +static int 
12926 +gre_unique_tuple(struct ip_conntrack_tuple *tuple,
12927 +                const struct ip_nat_range *range,
12928 +                enum ip_nat_manip_type maniptype,
12929 +                const struct ip_conntrack *conntrack)
12930 +{
12931 +       u_int32_t min, i, range_size;
12932 +       u_int32_t key = 0, *keyptr;
12933 +
12934 +       if (maniptype == IP_NAT_MANIP_SRC)
12935 +               keyptr = &tuple->src.u.gre.key;
12936 +       else
12937 +               keyptr = &tuple->dst.u.gre.key;
12938 +
12939 +       if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
12940 +
12941 +               switch (tuple->dst.u.gre.version) {
12942 +               case 0:
12943 +                       DEBUGP("NATing GRE version 0 (ct=%p)\n",
12944 +                               conntrack);
12945 +                       min = 1;
12946 +                       range_size = 0xffffffff;
12947 +                       break;
12948 +               case GRE_VERSION_PPTP:
12949 +                       DEBUGP("%p: NATing GRE PPTP\n", 
12950 +                               conntrack);
12951 +                       min = 1;
12952 +                       range_size = 0xffff;
12953 +                       break;
12954 +               default:
12955 +                       printk(KERN_WARNING "nat_gre: unknown GRE version\n");
12956 +                       return 0;
12957 +                       break;
12958 +               }
12959 +
12960 +       } else {
12961 +               min = ntohl(range->min.gre.key);
12962 +               range_size = ntohl(range->max.gre.key) - min + 1;
12963 +       }
12964 +
12965 +       DEBUGP("min = %u, range_size = %u\n", min, range_size); 
12966 +
12967 +       for (i = 0; i < range_size; i++, key++) {
12968 +               *keyptr = htonl(min + key % range_size);
12969 +               if (!ip_nat_used_tuple(tuple, conntrack))
12970 +                       return 1;
12971 +       }
12972 +
12973 +       DEBUGP("%p: no NAT mapping\n", conntrack);
12974 +
12975 +       return 0;
12976 +}
12977 +
12978 +/* manipulate a GRE packet according to maniptype */
12979 +static void 
12980 +gre_manip_pkt(struct iphdr *iph, size_t len, 
12981 +             const struct ip_conntrack_manip *manip,
12982 +             enum ip_nat_manip_type maniptype)
12983 +{
12984 +       struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
12985 +       struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;
12986 +
12987 +       /* we only have destination manip of a packet, since 'source key' 
12988 +        * is not present in the packet itself */
12989 +       if (maniptype == IP_NAT_MANIP_DST) {
12990 +               /* key manipulation is always dest */
12991 +               switch (greh->version) {
12992 +               case 0:
12993 +                       if (!greh->key) {
12994 +                               DEBUGP("can't nat GRE w/o key\n");
12995 +                               break;
12996 +                       }
12997 +                       if (greh->csum) {
12998 +                               /* FIXME: Never tested this code... */
12999 +                               *(gre_csum(greh)) = 
13000 +                                       ip_nat_cheat_check(~*(gre_key(greh)),
13001 +                                                       manip->u.gre.key,
13002 +                                                       *(gre_csum(greh)));
13003 +                       }
13004 +                       *(gre_key(greh)) = manip->u.gre.key;
13005 +                       break;
13006 +               case GRE_VERSION_PPTP:
13007 +                       DEBUGP("call_id -> 0x%04x\n", 
13008 +                               ntohl(manip->u.gre.key));
13009 +                       pgreh->call_id = htons(ntohl(manip->u.gre.key));
13010 +                       break;
13011 +               default:
13012 +                       DEBUGP("can't nat unknown GRE version\n");
13013 +                       break;
13014 +               }
13015 +       }
13016 +}
13017 +
13018 +/* print out a nat tuple */
13019 +static unsigned int 
13020 +gre_print(char *buffer, 
13021 +         const struct ip_conntrack_tuple *match,
13022 +         const struct ip_conntrack_tuple *mask)
13023 +{
13024 +       unsigned int len = 0;
13025 +
13026 +       if (mask->dst.u.gre.version)
13027 +               len += sprintf(buffer + len, "version=%d ",
13028 +                               ntohs(match->dst.u.gre.version));
13029 +
13030 +       if (mask->dst.u.gre.protocol)
13031 +               len += sprintf(buffer + len, "protocol=0x%x ",
13032 +                               ntohs(match->dst.u.gre.protocol));
13033 +
13034 +       if (mask->src.u.gre.key)
13035 +               len += sprintf(buffer + len, "srckey=0x%x ", 
13036 +                               ntohl(match->src.u.gre.key));
13037 +
13038 +       if (mask->dst.u.gre.key)
13039 +               len += sprintf(buffer + len, "dstkey=0x%x ",
13040 +                               ntohl(match->src.u.gre.key));
13041 +
13042 +       return len;
13043 +}
13044 +
13045 +/* print a range of keys */
13046 +static unsigned int 
13047 +gre_print_range(char *buffer, const struct ip_nat_range *range)
13048 +{
13049 +       if (range->min.gre.key != 0 
13050 +           || range->max.gre.key != 0xFFFF) {
13051 +               if (range->min.gre.key == range->max.gre.key)
13052 +                       return sprintf(buffer, "key 0x%x ",
13053 +                                       ntohl(range->min.gre.key));
13054 +               else
13055 +                       return sprintf(buffer, "keys 0x%u-0x%u ",
13056 +                                       ntohl(range->min.gre.key),
13057 +                                       ntohl(range->max.gre.key));
13058 +       } else
13059 +               return 0;
13060 +}
13061 +
13062 +/* nat helper struct */
13063 +static struct ip_nat_protocol gre = 
13064 +       { { NULL, NULL }, "GRE", IPPROTO_GRE,
13065 +         gre_manip_pkt,
13066 +         gre_in_range,
13067 +         gre_unique_tuple,
13068 +         gre_print,
13069 +         gre_print_range 
13070 +       };
13071 +                                 
13072 +static int __init init(void)
13073 +{
13074 +        if (ip_nat_protocol_register(&gre))
13075 +                return -EIO;
13076 +
13077 +        return 0;
13078 +}
13079 +
13080 +static void __exit fini(void)
13081 +{
13082 +        ip_nat_protocol_unregister(&gre);
13083 +}
13084 +
13085 +module_init(init);
13086 +module_exit(fini);
13087 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_quake3.c linux-2.4.20/net/ipv4/netfilter/ip_nat_quake3.c
13088 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_quake3.c Thu Jan  1 00:00:00 1970
13089 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_quake3.c     Wed Sep 24 09:17:58 2003
13090 @@ -0,0 +1,249 @@
13091 +/* Quake3 extension for UDP NAT alteration.
13092 + * (C) 2002 by Filip Sneppe <filip.sneppe@cronos.be>
13093 + * based on ip_nat_ftp.c and ip_nat_tftp.c
13094 + *
13095 + * ip_nat_quake3.c v0.0.3 2002-08-31
13096 + *
13097 + *      This program is free software; you can redistribute it and/or
13098 + *      modify it under the terms of the GNU General Public License
13099 + *      as published by the Free Software Foundation; either version
13100 + *      2 of the License, or (at your option) any later version.
13101 + *
13102 + *      Module load syntax:
13103 + *      insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
13104 + *
13105 + *      please give the ports of all Quake3 master servers You wish to
13106 + *      connect to. If you don't specify ports, the default will be UDP
13107 + *      port 27950.
13108 + *
13109 + *      Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
13110 + *
13111 + *      Notes: 
13112 + *      - If you're one of those people who would try anything to lower
13113 + *        latency while playing Quake (and who isn't :-) ), you may want to
13114 + *        consider not loading ip_nat_quake3 at all and just MASQUERADE all
13115 + *        outgoing UDP traffic.
13116 + *        This will make ip_conntrack_quake3 add the necessary expectations,
13117 + *        but there will be no overhead for client->server UDP streams. If
13118 + *        ip_nat_quake3 is loaded, quake3_nat_expected will be called per NAT
13119 + *        hook for every packet in the client->server UDP stream.
13120 + *      - Only SNAT/MASQUEARDE targets are useful for ip_nat_quake3.
13121 + *        The IP addresses in the master connection payload (=IP addresses
13122 + *        of Quake servers) have no relation with the master server so
13123 + *        DNAT'ing the master connection to a server should not change the
13124 + *        expected connections.
13125 + *      - Not tested due to lack of equipment:
13126 + *        - multiple Quake3 clients behind one MASQUERADE gateway
13127 + *        - what if Quake3 client is running on router too
13128 + */
13129 +
13130 +#include <linux/module.h>
13131 +#include <linux/netfilter_ipv4.h>
13132 +#include <linux/ip.h>
13133 +#include <linux/udp.h>
13134 +
13135 +#include <linux/netfilter.h>
13136 +#include <linux/netfilter_ipv4/ip_tables.h>
13137 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
13138 +#include <linux/netfilter_ipv4/ip_conntrack_quake3.h>
13139 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
13140 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
13141 +
13142 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
13143 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
13144 +MODULE_LICENSE("GPL");
13145 +
13146 +#define MAX_PORTS 8
13147 +
13148 +static int ports[MAX_PORTS];
13149 +static int ports_c = 0;
13150 +#ifdef MODULE_PARM
13151 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
13152 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
13153 +#endif
13154 +
13155 +/* Quake3 master server reply will add > 100 expectations per reply packet; when
13156 +   doing lots of printk's, klogd may not be able to read /proc/kmsg fast enough */
13157 +#if 0 
13158 +#define DEBUGP printk
13159 +#else
13160 +#define DEBUGP(format, args...)
13161 +#endif
13162 +
13163 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
13164 +
13165 +static unsigned int 
13166 +quake3_nat_help(struct ip_conntrack *ct,
13167 +                struct ip_conntrack_expect *exp,
13168 +                struct ip_nat_info *info,
13169 +                enum ip_conntrack_info ctinfo,
13170 +                unsigned int hooknum,
13171 +                struct sk_buff **pskb)
13172 +{
13173 +       struct iphdr *iph = (*pskb)->nh.iph;
13174 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
13175 +       struct ip_conntrack_tuple repl;
13176 +       int dir = CTINFO2DIR(ctinfo);
13177 +       int i;
13178 +       
13179 +       DEBUGP("ip_nat_quake3: quake3_nat_help, direction: %s hook: %s\n",
13180 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
13181 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13182 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13183 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???"
13184 +             );
13185 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
13186 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
13187 +       
13188 +       /* Only mangle things once: original direction in POST_ROUTING
13189 +          and reply direction on PRE_ROUTING. */
13190 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
13191 +           || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
13192 +               DEBUGP("ip_nat_quake3: Not touching dir %s at hook %s\n",
13193 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
13194 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13195 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13196 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????");
13197 +               return NF_ACCEPT;
13198 +       }
13199 +
13200 +       if (!exp) {
13201 +               DEBUGP("no conntrack expectation to modify\n");
13202 +               return NF_ACCEPT;
13203 +       }
13204 +
13205 +       if (strnicmp((const char *)udph + 12, quake3s_nat.pattern, quake3s_nat.plen) == 0) {
13206 +               for(i=31; /* 8 bytes UDP hdr, 4 bytes filler, 18 bytes "getserversResponse", 1 byte "\" */
13207 +                   i+6 < ntohs(udph->len);
13208 +                   i+=7) {
13209 +                       DEBUGP("ip_nat_quake3: adding server at offset %u/%u %u.%u.%u.%u:%u\n", 
13210 +                              i, ntohs(udph->len),
13211 +                              NIPQUAD( (u_int32_t) *( (u_int32_t *)( (int)udph + i ) ) ),
13212 +                              ntohs((__u16) *( (__u16 *)( (int)udph + i + 4 ) ) ) );
13213 +                       
13214 +                       memset(&repl, 0, sizeof(repl));
13215 +
13216 +                       repl.dst.protonum = IPPROTO_UDP;
13217 +                       repl.src.ip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
13218 +                       repl.dst.ip = *( (u_int32_t *)( (int)udph + i ) );
13219 +                       repl.dst.u.udp.port = (__u16) *( (__u16 *)( (int)udph + i + 4 )  );
13220 +                       
13221 +                       ip_conntrack_change_expect(exp, &repl);
13222 +               }
13223 +       }
13224 +       return NF_ACCEPT;
13225 +}
13226 +
13227 +static unsigned int 
13228 +quake3_nat_expected(struct sk_buff **pskb,
13229 +                    unsigned int hooknum,
13230 +                    struct ip_conntrack *ct, 
13231 +                    struct ip_nat_info *info) 
13232 +{
13233 +       const struct ip_conntrack *master = ct->master->expectant;
13234 +       struct ip_nat_multi_range mr;
13235 +       u_int32_t newsrcip, newdstip, newip;
13236 +#if 0 
13237 +       const struct ip_conntrack_tuple *repl =
13238 +               &master->tuplehash[IP_CT_DIR_REPLY].tuple;
13239 +       struct iphdr *iph = (*pskb)->nh.iph;
13240 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
13241 +#endif
13242 +
13243 +       DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
13244 +       DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
13245 +
13246 +       IP_NF_ASSERT(info);
13247 +       IP_NF_ASSERT(master);
13248 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
13249 +       
13250 +       newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
13251 +       newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
13252 +       
13253 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
13254 +               newip = newsrcip;
13255 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
13256 +                      "newsrc: %u.%u.%u.%u\n",
13257 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13258 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13259 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
13260 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
13261 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
13262 +                      NIPQUAD(newip));
13263 +               
13264 +       } else {
13265 +               newip = newdstip;
13266 +               DEBUGP("hook: %s orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
13267 +                      "newdst: %u.%u.%u.%u\n",
13268 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13269 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13270 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "????",
13271 +                      NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
13272 +                      NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
13273 +                      NIPQUAD(newip));
13274 +       }
13275 +       
13276 +       mr.rangesize = 1;
13277 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
13278 +       mr.range[0].min_ip = mr.range[0].max_ip = newip; 
13279 +
13280 +       return ip_nat_setup_info(ct,&mr,hooknum);
13281 +}
13282 +
13283 +static struct ip_nat_helper quake3[MAX_PORTS];
13284 +static char quake3_names[MAX_PORTS][13];  /* quake3-65535 */
13285 +
13286 +static void fini(void)
13287 +{
13288 +       int i;
13289 +       
13290 +       for (i = 0 ; i < ports_c; i++) {
13291 +               DEBUGP("ip_nat_quake3: unregistering helper for port %d\n", ports[i]);
13292 +                      ip_nat_helper_unregister(&quake3[i]);
13293 +       }
13294 +}
13295 +
13296 +static int __init init(void)
13297 +       {
13298 +               int i, ret = 0;
13299 +               char *tmpname;
13300 +
13301 +               if (!ports[0])
13302 +                       ports[0] = QUAKE3_MASTER_PORT;
13303 +               
13304 +               for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
13305 +                       memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
13306 +
13307 +                       quake3[i].tuple.dst.protonum = IPPROTO_UDP;
13308 +                       quake3[i].tuple.src.u.udp.port = htons(ports[i]);
13309 +                       quake3[i].mask.dst.protonum = 0xFFFF;
13310 +                       quake3[i].mask.src.u.udp.port = 0xFFFF;
13311 +                       quake3[i].help = quake3_nat_help;
13312 +                       quake3[i].flags = 0;
13313 +                       quake3[i].me = THIS_MODULE;
13314 +                       quake3[i].expect = quake3_nat_expected;
13315 +                       
13316 +                       tmpname = &quake3_names[i][0];
13317 +                       if (ports[i] == QUAKE3_MASTER_PORT)
13318 +                               sprintf(tmpname, "quake3");
13319 +                       else
13320 +                               sprintf(tmpname, "quake3-%d", i);
13321 +                       quake3[i].name = tmpname;
13322 +                       
13323 +                       DEBUGP("ip_nat_quake3: registering helper for port %d: name %s\n",
13324 +                              ports[i], quake3[i].name);
13325 +                       ret = ip_nat_helper_register(&quake3[i]);
13326 +                       
13327 +                       if (ret) {
13328 +                               printk("ip_nat_quake3: unable to register helper for port %d\n",
13329 +                                      ports[i]);
13330 +                               fini();
13331 +                               return ret;
13332 +                       }
13333 +                       ports_c++;
13334 +               }
13335 +               return ret;
13336 +       }
13337 +       
13338 +module_init(init);
13339 +module_exit(fini);
13340 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_rule.c linux-2.4.20/net/ipv4/netfilter/ip_nat_rule.c
13341 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_rule.c   Thu Nov 28 23:53:15 2002
13342 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_rule.c       Wed Sep 24 09:16:27 2003
13343 @@ -1,5 +1,4 @@
13344  /* Everything about the rules for NAT. */
13345 -#define __NO_VERSION__
13346  #include <linux/types.h>
13347  #include <linux/ip.h>
13348  #include <linux/netfilter.h>
13349 @@ -231,7 +230,7 @@
13350         return 1;
13351  }
13352  
13353 -static inline unsigned int
13354 +inline unsigned int
13355  alloc_null_binding(struct ip_conntrack *conntrack,
13356                    struct ip_nat_info *info,
13357                    unsigned int hooknum)
13358 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_snmp_basic.c linux-2.4.20/net/ipv4/netfilter/ip_nat_snmp_basic.c
13359 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_snmp_basic.c     Thu Nov 28 23:53:15 2002
13360 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_snmp_basic.c Wed Sep 24 09:16:21 2003
13361 @@ -53,9 +53,9 @@
13362  #include <linux/brlock.h>
13363  #include <linux/types.h>
13364  #include <linux/ip.h>
13365 +#include <net/checksum.h>
13366  #include <net/udp.h>
13367  #include <asm/uaccess.h>
13368 -#include <asm/checksum.h>
13369  
13370  
13371  
13372 @@ -1309,9 +1309,9 @@
13373         "snmp",
13374         IP_NAT_HELPER_F_STANDALONE,
13375         THIS_MODULE,
13376 -       { { 0, { __constant_htons(SNMP_PORT) } },
13377 +       { { 0, { .udp = { __constant_htons(SNMP_PORT) } } },
13378           { 0, { 0 }, IPPROTO_UDP } },
13379 -       { { 0, { 0xFFFF } },
13380 +       { { 0, { .udp = { 0xFFFF } } },
13381           { 0, { 0 }, 0xFFFF } },
13382         nat_help, NULL };
13383   
13384 @@ -1320,9 +1320,9 @@
13385         "snmp_trap",
13386         IP_NAT_HELPER_F_STANDALONE,
13387         THIS_MODULE,
13388 -       { { 0, { __constant_htons(SNMP_TRAP_PORT) } },
13389 +       { { 0, { .udp = { __constant_htons(SNMP_TRAP_PORT) } } },
13390           { 0, { 0 }, IPPROTO_UDP } },
13391 -       { { 0, { 0xFFFF } },
13392 +       { { 0, { .udp = { 0xFFFF } } },
13393           { 0, { 0 }, 0xFFFF } },
13394         nat_help, NULL };
13395  
13396 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_standalone.c linux-2.4.20/net/ipv4/netfilter/ip_nat_standalone.c
13397 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_standalone.c     Thu Nov 28 23:53:15 2002
13398 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_standalone.c Wed Sep 24 09:17:50 2003
13399 @@ -109,19 +109,12 @@
13400                 }
13401                 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
13402         case IP_CT_NEW:
13403 -#ifdef CONFIG_IP_NF_NAT_LOCAL
13404 -               /* LOCAL_IN hook doesn't have a chain and thus doesn't care
13405 -                * about new packets -HW */
13406 -               if (hooknum == NF_IP_LOCAL_IN)
13407 -                       return NF_ACCEPT;
13408 -#endif
13409                 info = &ct->nat.info;
13410  
13411                 WRITE_LOCK(&ip_nat_lock);
13412                 /* Seen it before?  This can happen for loopback, retrans,
13413                    or local packets.. */
13414                 if (!(info->initialized & (1 << maniptype))) {
13415 -                       int in_hashes = info->initialized;
13416                         unsigned int ret;
13417  
13418                         if (ct->master
13419 @@ -130,6 +123,13 @@
13420                                 ret = call_expect(master_ct(ct), pskb, 
13421                                                   hooknum, ct, info);
13422                         } else {
13423 +#ifdef CONFIG_IP_NF_NAT_LOCAL
13424 +                               /* LOCAL_IN hook doesn't have a chain!  */
13425 +                               if (hooknum == NF_IP_LOCAL_IN)
13426 +                                       ret = alloc_null_binding(ct, info,
13427 +                                                                hooknum);
13428 +                               else
13429 +#endif
13430                                 ret = ip_nat_rule_find(pskb, hooknum, in, out,
13431                                                        ct, info);
13432                         }
13433 @@ -138,13 +138,6 @@
13434                                 WRITE_UNLOCK(&ip_nat_lock);
13435                                 return ret;
13436                         }
13437 -
13438 -                       if (in_hashes) {
13439 -                               IP_NF_ASSERT(info->bysource.conntrack);
13440 -                               replace_in_hashes(ct, info);
13441 -                       } else {
13442 -                               place_in_hashes(ct, info);
13443 -                       }
13444                 } else
13445                         DEBUGP("Already setup manip %s for ct %p\n",
13446                                maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST",
13447 @@ -195,6 +188,7 @@
13448         return ip_nat_fn(hooknum, pskb, in, out, okfn);
13449  }
13450  
13451 +#ifdef CONFIG_IP_NF_NAT_LOCAL
13452  static unsigned int
13453  ip_nat_local_fn(unsigned int hooknum,
13454                 struct sk_buff **pskb,
13455 @@ -220,6 +214,7 @@
13456                 return ip_route_me_harder(pskb) == 0 ? ret : NF_DROP;
13457         return ret;
13458  }
13459 +#endif
13460  
13461  /* We must be after connection tracking and before packet filtering. */
13462  
13463 @@ -229,16 +224,23 @@
13464  /* After packet filtering, change source */
13465  static struct nf_hook_ops ip_nat_out_ops
13466  = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
13467 +
13468 +#ifdef CONFIG_IP_NF_NAT_LOCAL
13469  /* Before packet filtering, change destination */
13470  static struct nf_hook_ops ip_nat_local_out_ops
13471  = { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
13472 -
13473 -#ifdef CONFIG_IP_NF_NAT_LOCAL
13474 +/* After packet filtering, change source for reply packets of LOCAL_OUT DNAT */
13475  static struct nf_hook_ops ip_nat_local_in_ops
13476  = { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_IN, NF_IP_PRI_NAT_SRC };
13477  #endif
13478  
13479 -/* Protocol registration. */
13480 +/**
13481 + * ip_nat_protocol_register - Register a layer 4 protocol helper
13482 + * @proto: structure describing this helper
13483 + * 
13484 + * This function is called by NAT layer 4 protocol helpers to register
13485 + * themselvers with the NAT core.
13486 + */
13487  int ip_nat_protocol_register(struct ip_nat_protocol *proto)
13488  {
13489         int ret = 0;
13490 @@ -261,9 +263,16 @@
13491         return ret;
13492  }
13493  
13494 -/* Noone stores the protocol anywhere; simply delete it. */
13495 +/**
13496 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
13497 + * @proto: sturcture describing the helper
13498 + *
13499 + * This function is called by NAT layer 4 protocol helpers to
13500 + * unregister themselves from the NAT core.
13501 + */
13502  void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
13503  {
13504 +       /* Noone stores the protocol anywhere; simply delete it. */
13505         WRITE_LOCK(&ip_nat_lock);
13506         LIST_DELETE(&protos, proto);
13507         WRITE_UNLOCK(&ip_nat_lock);
13508 @@ -301,12 +310,12 @@
13509                 printk("ip_nat_init: can't register out hook.\n");
13510                 goto cleanup_inops;
13511         }
13512 +#ifdef CONFIG_IP_NF_NAT_LOCAL
13513         ret = nf_register_hook(&ip_nat_local_out_ops);
13514         if (ret < 0) {
13515                 printk("ip_nat_init: can't register local out hook.\n");
13516                 goto cleanup_outops;
13517         }
13518 -#ifdef CONFIG_IP_NF_NAT_LOCAL
13519         ret = nf_register_hook(&ip_nat_local_in_ops);
13520         if (ret < 0) {
13521                 printk("ip_nat_init: can't register local in hook.\n");
13522 @@ -323,9 +332,9 @@
13523  #ifdef CONFIG_IP_NF_NAT_LOCAL
13524         nf_unregister_hook(&ip_nat_local_in_ops);
13525   cleanup_localoutops:
13526 -#endif
13527         nf_unregister_hook(&ip_nat_local_out_ops);
13528   cleanup_outops:
13529 +#endif
13530         nf_unregister_hook(&ip_nat_out_ops);
13531   cleanup_inops:
13532         nf_unregister_hook(&ip_nat_in_ops);
13533 @@ -358,5 +367,6 @@
13534  EXPORT_SYMBOL(ip_nat_helper_unregister);
13535  EXPORT_SYMBOL(ip_nat_cheat_check);
13536  EXPORT_SYMBOL(ip_nat_mangle_tcp_packet);
13537 +EXPORT_SYMBOL(ip_nat_mangle_udp_packet);
13538  EXPORT_SYMBOL(ip_nat_used_tuple);
13539  MODULE_LICENSE("GPL");
13540 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_talk.c linux-2.4.20/net/ipv4/netfilter/ip_nat_talk.c
13541 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_talk.c   Thu Jan  1 00:00:00 1970
13542 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_talk.c       Wed Sep 24 09:18:08 2003
13543 @@ -0,0 +1,473 @@
13544 +/* 
13545 + * talk extension for UDP NAT alteration. 
13546 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
13547 + *
13548 + *      This program is free software; you can redistribute it and/or
13549 + *      modify it under the terms of the GNU General Public License
13550 + *      as published by the Free Software Foundation; either version
13551 + *      2 of the License, or (at your option) any later version.
13552 + **
13553 + *     Module load syntax:
13554 + *     insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
13555 + *
13556 + *             talk=[0|1]      disable|enable old talk support
13557 + *            ntalk=[0|1]      disable|enable ntalk support
13558 + *           ntalk2=[0|1]      disable|enable ntalk2 support
13559 + *
13560 + *     The default is talk=1 ntalk=1 ntalk2=1
13561 + *
13562 + *  
13563 + */
13564 +#include <linux/module.h>
13565 +#include <linux/netfilter_ipv4.h>
13566 +#include <linux/ip.h>
13567 +#include <linux/udp.h>
13568 +#include <linux/kernel.h>
13569 +#include <net/tcp.h>
13570 +#include <net/udp.h>
13571 +
13572 +#include <linux/netfilter_ipv4/ip_nat.h>
13573 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
13574 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
13575 +#include <linux/netfilter_ipv4/ip_conntrack_talk.h>
13576 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
13577 +
13578 +/* Default all talk protocols are supported */
13579 +static int talk   = 1;
13580 +static int ntalk  = 1;
13581 +static int ntalk2 = 1;
13582 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
13583 +MODULE_DESCRIPTION("talk network address translation module");
13584 +#ifdef MODULE_PARM
13585 +MODULE_PARM(talk, "i");
13586 +MODULE_PARM_DESC(talk, "support (old) talk protocol");
13587 +MODULE_PARM(ntalk, "i");
13588 +MODULE_PARM_DESC(ntalk, "support ntalk protocol");
13589 +MODULE_PARM(ntalk2, "i");
13590 +MODULE_PARM_DESC(ntalk2, "support ntalk2 protocol");
13591 +#endif
13592 +
13593 +#if 0
13594 +#define DEBUGP printk
13595 +#define IP_NAT_TALK_DEBUG
13596 +#else
13597 +#define DEBUGP(format, args...)
13598 +#endif
13599 +
13600 +/* FIXME: Time out? --RR */
13601 +
13602 +static int
13603 +mangle_packet(struct sk_buff **pskb,
13604 +             struct ip_conntrack *ct,
13605 +             u_int32_t newip,
13606 +             u_int16_t port,
13607 +             struct talk_addr *addr,
13608 +             struct talk_addr *ctl_addr)
13609 +{
13610 +       struct iphdr *iph = (*pskb)->nh.iph;
13611 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
13612 +       size_t udplen = (*pskb)->len - iph->ihl * 4;
13613 +
13614 +       /* Fortunately talk sends a structure with the address and
13615 +          port in it. The size of the packet won't change. */
13616 +
13617 +       if (ctl_addr == NULL) {
13618 +               /* response */
13619 +               if (addr->ta_addr == INADDR_ANY)
13620 +                       return 1;
13621 +               DEBUGP("ip_nat_talk_mangle_packet: response orig %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
13622 +                      NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
13623 +                      NIPQUAD(newip), ntohs(port));
13624 +               addr->ta_addr = newip;
13625 +               addr->ta_port = port;
13626 +       } else {
13627 +               /* message */
13628 +               if (addr->ta_addr != INADDR_ANY) {
13629 +                       /* Change address inside packet to match way we're mapping
13630 +                          this connection. */
13631 +                       DEBUGP("ip_nat_talk_mangle_packet: message orig addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
13632 +                              NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
13633 +                              NIPQUAD(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip), 
13634 +                              ntohs(addr->ta_port));
13635 +                       addr->ta_addr = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
13636 +               }
13637 +               DEBUGP("ip_nat_talk_mangle_packet: message orig ctl_addr %u.%u.%u.%u:%u, inserting %u.%u.%u.%u:%u\n", 
13638 +                      NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
13639 +                      NIPQUAD(newip), ntohs(port));
13640 +               ctl_addr->ta_addr = newip;
13641 +               ctl_addr->ta_port = port;
13642 +       }
13643 +
13644 +       /* Fix checksums */
13645 +       (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
13646 +       udph->check = 0;
13647 +       udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
13648 +                                       csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
13649 +               
13650 +       ip_send_check(iph);
13651 +       return 1;
13652 +}
13653 +
13654 +static int talk_help_msg(struct ip_conntrack *ct,
13655 +                        struct sk_buff **pskb,
13656 +                        u_char type,
13657 +                        struct talk_addr *addr,
13658 +                        struct talk_addr *ctl_addr)
13659 +{
13660 +       u_int32_t newip;
13661 +       u_int16_t port;
13662 +       
13663 +       unsigned int verdict = NF_ACCEPT;
13664 +
13665 +       DEBUGP("ip_nat_talk_help_msg: addr: %u.%u.%u.%u:%u, ctl_addr: %u.%u.%u.%u:%u, type %d\n",
13666 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
13667 +               NIPQUAD(ctl_addr->ta_addr), ntohs(ctl_addr->ta_port),
13668 +               type);
13669 +
13670 +       /* Change address inside packet to match way we're mapping
13671 +          this connection. */
13672 +       newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
13673 +       port  = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u.udp.port;
13674 +       DEBUGP("ip_nat_talk_help_msg: inserting: %u.%u.%u.%u:%u\n",
13675 +               NIPQUAD(newip), ntohs(port));
13676 +
13677 +       if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
13678 +               verdict = NF_DROP;
13679 +
13680 +       return verdict;
13681 +}
13682 +
13683 +static int talk_help_response(struct ip_conntrack *ct,
13684 +                             struct ip_conntrack_expect *exp,
13685 +                             struct sk_buff **pskb,
13686 +                             u_char type,
13687 +                             u_char answer,
13688 +                             struct talk_addr *addr)
13689 +{
13690 +       u_int32_t newip;
13691 +       u_int16_t port;
13692 +       struct ip_conntrack_tuple t;
13693 +       struct ip_ct_talk_expect *ct_talk_info;
13694 +
13695 +       DEBUGP("ip_nat_talk_help_response: addr: %u.%u.%u.%u:%u, type %d answer %d\n",
13696 +               NIPQUAD(addr->ta_addr), ntohs(addr->ta_port),
13697 +               type, answer);
13698 +       
13699 +       LOCK_BH(&ip_talk_lock);
13700 +       ct_talk_info = &exp->help.exp_talk_info;
13701 +
13702 +       if (!(answer == SUCCESS 
13703 +             && (type == LOOK_UP || type == ANNOUNCE)
13704 +             && exp != NULL)) {
13705 +               UNLOCK_BH(&ip_talk_lock);
13706 +               return NF_ACCEPT;
13707 +       }
13708 +               
13709 +       DEBUGP("ip_nat_talk_help_response: talkinfo port %u (%s)\n", 
13710 +               ntohs(ct_talk_info->port), 
13711 +               type == LOOK_UP ? "LOOK_UP" : "ANNOUNCE");
13712 +
13713 +       /* Change address inside packet to match way we're mapping
13714 +          this connection. */
13715 +       newip = ct->tuplehash[type == LOOK_UP ? IP_CT_DIR_ORIGINAL : 
13716 +                                               IP_CT_DIR_REPLY].tuple.dst.ip;
13717 +       /* We can read expect here without conntrack lock, since it's
13718 +          only set in ip_conntrack_talk , with ip_talk_lock held
13719 +          writable */ 
13720 +       t = exp->tuple;
13721 +       t.dst.ip = newip;
13722 +
13723 +       /* Try to get same port: if not, try to change it. */
13724 +       for (port = ntohs(ct_talk_info->port); port != 0; port++) {
13725 +               if (type == LOOK_UP)
13726 +                       t.dst.u.tcp.port = htons(port);
13727 +               else
13728 +                       t.dst.u.udp.port = htons(port);
13729 +
13730 +               if (ip_conntrack_change_expect(exp, &t) == 0) {
13731 +                       DEBUGP("ip_nat_talk_help_response: using %u.%u.%u.%u:%u\n", NIPQUAD(newip), port);
13732 +                       break;
13733 +               }
13734 +       }
13735 +       UNLOCK_BH(&ip_talk_lock);
13736 +
13737 +       if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
13738 +               return NF_DROP;
13739 +       
13740 +       return NF_ACCEPT;
13741 +}
13742 +
13743 +static unsigned int talk_help(struct ip_conntrack *ct,
13744 +                             struct ip_conntrack_expect *exp,
13745 +                             struct ip_nat_info *info,
13746 +                             enum ip_conntrack_info ctinfo,
13747 +                             unsigned int hooknum,
13748 +                             struct sk_buff **pskb,
13749 +                             int talk_port)
13750 +{
13751 +       struct iphdr *iph = (*pskb)->nh.iph;
13752 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
13753 +       unsigned int udplen = (*pskb)->len - iph->ihl * 4;
13754 +       char *data = (char *)udph + sizeof(struct udphdr);
13755 +       int dir;
13756 +
13757 +       /* Only mangle things once: original direction in POST_ROUTING
13758 +          and reply direction on PRE_ROUTING. */
13759 +       dir = CTINFO2DIR(ctinfo);
13760 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
13761 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) {
13762 +               DEBUGP("ip_nat_talk_help: Not touching dir %s at hook %s\n",
13763 +                      dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
13764 +                      hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13765 +                      : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13766 +                      : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???");
13767 +               return NF_ACCEPT;
13768 +       }
13769 +       DEBUGP("ip_nat_talk_help: dir %s at hook %s, %u.%u.%u.%u:%u->%u.%u.%u.%u:%u, talk port %d\n",
13770 +              dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
13771 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13772 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13773 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
13774 +              NIPQUAD(iph->saddr), ntohs(udph->source),
13775 +              NIPQUAD(iph->daddr), ntohs(udph->dest),
13776 +              talk_port);
13777 +
13778 +       /* Because conntrack does not drop packets, checking must be repeated here... */
13779 +       if (talk_port == TALK_PORT) {
13780 +               if (dir == IP_CT_DIR_ORIGINAL
13781 +                   && udplen == sizeof(struct udphdr) + sizeof(struct talk_msg))
13782 +                       return talk_help_msg(ct, pskb,
13783 +                                            ((struct talk_msg *)data)->type, 
13784 +                                            &(((struct talk_msg *)data)->addr),
13785 +                                            &(((struct talk_msg *)data)->ctl_addr));
13786 +               else if (dir == IP_CT_DIR_REPLY
13787 +                        && udplen == sizeof(struct udphdr) + sizeof(struct talk_response))
13788 +                       return talk_help_response(ct, exp, pskb,
13789 +                                                 ((struct talk_response *)data)->type, 
13790 +                                                 ((struct talk_response *)data)->answer,
13791 +                                                 &(((struct talk_response *)data)->addr));
13792 +               else {  
13793 +                       DEBUGP("ip_nat_talk_help: not talk %s, datalen %u != %u\n",
13794 +                              dir == IP_CT_DIR_ORIGINAL ? "message" : "response", 
13795 +                              (unsigned)udplen - sizeof(struct udphdr), 
13796 +                              dir == IP_CT_DIR_ORIGINAL ? sizeof(struct talk_msg) : sizeof(struct talk_response));
13797 +                       return NF_DROP;
13798 +               }
13799 +       } else {
13800 +               if (dir == IP_CT_DIR_ORIGINAL) {
13801 +                       if (ntalk
13802 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_msg)
13803 +                           && ((struct ntalk_msg *)data)->vers == NTALK_VERSION)
13804 +                               return talk_help_msg(ct, pskb,
13805 +                                                    ((struct ntalk_msg *)data)->type, 
13806 +                                                    &(((struct ntalk_msg *)data)->addr),
13807 +                                                    &(((struct ntalk_msg *)data)->ctl_addr));
13808 +                       else if (ntalk2
13809 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_msg)
13810 +                                && ((struct ntalk2_msg *)data)->vers == NTALK2_VERSION
13811 +                                && udplen == sizeof(struct udphdr) 
13812 +                                             + sizeof(struct ntalk2_msg) 
13813 +                                             + ((struct ntalk2_msg *)data)->extended)
13814 +                               return talk_help_msg(ct, pskb,
13815 +                                                    ((struct ntalk2_msg *)data)->type, 
13816 +                                                    &(((struct ntalk2_msg *)data)->addr),
13817 +                                                    &(((struct ntalk2_msg *)data)->ctl_addr));
13818 +                       else {
13819 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 message, datalen %u != %u or %u + max 256\n", 
13820 +                                      (unsigned)udplen - sizeof(struct udphdr), 
13821 +                                      sizeof(struct ntalk_msg), sizeof(struct ntalk2_msg));
13822 +                               return NF_DROP;
13823 +                       }
13824 +               } else {
13825 +                       if (ntalk
13826 +                           && udplen == sizeof(struct udphdr) + sizeof(struct ntalk_response)
13827 +                           && ((struct ntalk_response *)data)->vers == NTALK_VERSION)
13828 +                               return talk_help_response(ct, exp, pskb,
13829 +                                                         ((struct ntalk_response *)data)->type, 
13830 +                                                         ((struct ntalk_response *)data)->answer,
13831 +                                                         &(((struct ntalk_response *)data)->addr));
13832 +                       else if (ntalk2
13833 +                                && udplen >= sizeof(struct udphdr) + sizeof(struct ntalk2_response)
13834 +                                && ((struct ntalk2_response *)data)->vers == NTALK2_VERSION)
13835 +                               return talk_help_response(ct, exp, pskb,
13836 +                                                         ((struct ntalk2_response *)data)->type, 
13837 +                                                         ((struct ntalk2_response *)data)->answer,
13838 +                                                         &(((struct ntalk2_response *)data)->addr));
13839 +                       else {
13840 +                               DEBUGP("ip_nat_talk_help: not ntalk/ntalk2 response, datalen %u != %u or %u + max 256\n", 
13841 +                                      (unsigned)udplen - sizeof(struct udphdr), 
13842 +                                      sizeof(struct ntalk_response), sizeof(struct ntalk2_response));
13843 +                               return NF_DROP;
13844 +                       }
13845 +               }
13846 +       }
13847 +}
13848 +
13849 +static unsigned int help(struct ip_conntrack *ct,
13850 +                        struct ip_conntrack_expect *exp,
13851 +                        struct ip_nat_info *info,
13852 +                        enum ip_conntrack_info ctinfo,
13853 +                        unsigned int hooknum,
13854 +                        struct sk_buff **pskb)
13855 +{
13856 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
13857 +}
13858 +
13859 +static unsigned int nhelp(struct ip_conntrack *ct,
13860 +                         struct ip_conntrack_expect *exp,
13861 +                         struct ip_nat_info *info,
13862 +                         enum ip_conntrack_info ctinfo,
13863 +                         unsigned int hooknum,
13864 +                         struct sk_buff **pskb)
13865 +{
13866 +       return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
13867 +}
13868 +
13869 +static unsigned int
13870 +talk_nat_expected(struct sk_buff **pskb,
13871 +                 unsigned int hooknum,
13872 +                 struct ip_conntrack *ct,
13873 +                 struct ip_nat_info *info);
13874 +
13875 +static struct ip_nat_helper talk_helpers[2] = 
13876 +       { { { NULL, NULL },
13877 +            "talk",                                    /* name */
13878 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
13879 +            THIS_MODULE,                               /* module */
13880 +            { { 0, { .udp = { __constant_htons(TALK_PORT) } } }, /* tuple */
13881 +              { 0, { 0 }, IPPROTO_UDP } },
13882 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
13883 +              { 0, { 0 }, 0xFFFF } },
13884 +            help,                                      /* helper */
13885 +            talk_nat_expected },                       /* expectfn */
13886 +         { { NULL, NULL },
13887 +            "ntalk",                                   /* name */
13888 +            IP_NAT_HELPER_F_ALWAYS,                    /* flags */
13889 +            THIS_MODULE,                                       /* module */
13890 +            { { 0, { .udp = { __constant_htons(NTALK_PORT) } } }, /* tuple */
13891 +              { 0, { 0 }, IPPROTO_UDP } },
13892 +            { { 0, { .udp = { 0xFFFF } } },            /* mask */
13893 +              { 0, { 0 }, 0xFFFF } },
13894 +            nhelp,                                     /* helper */
13895 +            talk_nat_expected }                                /* expectfn */
13896 +       };
13897 +          
13898 +static unsigned int
13899 +talk_nat_expected(struct sk_buff **pskb,
13900 +                 unsigned int hooknum,
13901 +                 struct ip_conntrack *ct,
13902 +                 struct ip_nat_info *info)
13903 +{
13904 +       struct ip_nat_multi_range mr;
13905 +       u_int32_t newdstip, newsrcip, newip;
13906 +       u_int16_t port;
13907 +       unsigned int ret;
13908 +       
13909 +       struct ip_conntrack *master = master_ct(ct);
13910 +
13911 +       IP_NF_ASSERT(info);
13912 +       IP_NF_ASSERT(master);
13913 +
13914 +       IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
13915 +
13916 +       DEBUGP("ip_nat_talk_expected: We have a connection!\n");
13917 +
13918 +       LOCK_BH(&ip_talk_lock);
13919 +       port = ct->master->help.exp_talk_info.port;
13920 +       UNLOCK_BH(&ip_talk_lock);
13921 +
13922 +       DEBUGP("ip_nat_talk_expected: dir %s at hook %s, ct %p, master %p\n",
13923 +              CTINFO2DIR((*pskb)->nfct - ct->infos) == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY",
13924 +              hooknum == NF_IP_POST_ROUTING ? "POSTROUTING"
13925 +              : hooknum == NF_IP_PRE_ROUTING ? "PREROUTING"
13926 +              : hooknum == NF_IP_LOCAL_OUT ? "OUTPUT" : "???",
13927 +              ct, master);
13928 +
13929 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
13930 +               /* Callee client -> caller server */
13931 +#ifdef IP_NAT_TALK_DEBUG
13932 +               struct iphdr *iph = (*pskb)->nh.iph;
13933 +               struct udphdr *udph = (void *)iph + iph->ihl * 4;
13934 +
13935 +               DEBUGP("ip_nat_talk_expected: UDP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
13936 +                      NIPQUAD(iph->saddr), ntohs(udph->source),
13937 +                      NIPQUAD(iph->daddr), ntohs(udph->dest));
13938 +#endif
13939 +               newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
13940 +               newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
13941 +               DEBUGP("ip_nat_talk_expected: callee client -> caller server, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
13942 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
13943 +       } else {
13944 +               /* Callee client -> caller client */
13945 +#ifdef IP_NAT_TALK_DEBUG
13946 +               struct iphdr *iph = (*pskb)->nh.iph;
13947 +               struct tcphdr *tcph = (void *)iph + iph->ihl * 4;
13948 +
13949 +               DEBUGP("ip_nat_talk_expected: TCP %u.%u.%u.%u:%u->%u.%u.%u.%u:%u\n",
13950 +                      NIPQUAD(iph->saddr), ntohs(tcph->source),
13951 +                      NIPQUAD(iph->daddr), ntohs(tcph->dest));
13952 +#endif
13953 +               newdstip = master->tuplehash[IP_CT_DIR_REPLY].tuple.src.ip;
13954 +               newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
13955 +               DEBUGP("ip_nat_talk_expected: callee client -> caller client, newsrc: %u.%u.%u.%u, newdst: %u.%u.%u.%u\n",
13956 +                      NIPQUAD(newsrcip), NIPQUAD(newdstip));
13957 +       }
13958 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
13959 +               newip = newsrcip;
13960 +       else
13961 +               newip = newdstip;
13962 +
13963 +       DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
13964 +
13965 +       mr.rangesize = 1;
13966 +       /* We don't want to manip the per-protocol, just the IPs... */
13967 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
13968 +       mr.range[0].min_ip = mr.range[0].max_ip = newip;
13969 +       
13970 +       /* ... unless we're doing a MANIP_DST, in which case, make
13971 +          sure we map to the correct port */
13972 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_DST) {
13973 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
13974 +               mr.range[0].min = mr.range[0].max
13975 +                       = ((union ip_conntrack_manip_proto)
13976 +                               { .udp = { port } });
13977 +       }
13978 +       ret = ip_nat_setup_info(ct, &mr, hooknum);
13979 +
13980 +       if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum == IPPROTO_UDP) {
13981 +               DEBUGP("talk_expected: setting NAT helper for %p\n", ct);
13982 +               /* NAT expectfn called with ip_nat_lock write-locked */
13983 +               info->helper = &talk_helpers[htons(port) - TALK_PORT];
13984 +       }
13985 +       return ret;
13986 +}
13987 +
13988 +static int __init init(void)
13989 +{
13990 +       int ret = 0;
13991 +
13992 +       if (talk > 0) {
13993 +               ret = ip_nat_helper_register(&talk_helpers[0]);
13994 +
13995 +               if (ret != 0)
13996 +                       return ret;
13997 +       }
13998 +       if (ntalk > 0 || ntalk2 > 0) {
13999 +               ret = ip_nat_helper_register(&talk_helpers[1]);
14000 +
14001 +               if (ret != 0 && talk > 0)
14002 +                       ip_nat_helper_unregister(&talk_helpers[0]);
14003 +       }
14004 +       return ret;
14005 +}
14006 +
14007 +static void __exit fini(void)
14008 +{
14009 +       if (talk > 0)
14010 +               ip_nat_helper_unregister(&talk_helpers[0]);
14011 +       if (ntalk > 0 || ntalk2 > 0)
14012 +               ip_nat_helper_unregister(&talk_helpers[1]);
14013 +}
14014 +
14015 +module_init(init);
14016 +module_exit(fini);
14017 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_nat_tftp.c linux-2.4.20/net/ipv4/netfilter/ip_nat_tftp.c
14018 --- linux-2.4.20.org/net/ipv4/netfilter/ip_nat_tftp.c   Thu Jan  1 00:00:00 1970
14019 +++ linux-2.4.20/net/ipv4/netfilter/ip_nat_tftp.c       Wed Sep 24 09:16:24 2003
14020 @@ -0,0 +1,195 @@
14021 +/*
14022 + * Licensed under GNU GPL version 2 Copyright Magnus Boden <mb@ozaba.mine.nu>
14023 + * Version: 0.0.7
14024 + *
14025 + * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
14026 + *     - Port to newnat API
14027 + *
14028 + * This module currently supports DNAT:
14029 + * iptables -t nat -A PREROUTING -d x.x.x.x -j DNAT --to-dest x.x.x.y
14030 + *
14031 + * and SNAT:
14032 + * iptables -t nat -A POSTROUTING { -j MASQUERADE , -j SNAT --to-source x.x.x.x }
14033 + *
14034 + * It has not been tested with
14035 + * -j SNAT --to-source x.x.x.x-x.x.x.y since I only have one external ip
14036 + * If you do test this please let me know if it works or not.
14037 + *
14038 + */
14039 +
14040 +#include <linux/module.h>
14041 +#include <linux/netfilter_ipv4.h>
14042 +#include <linux/ip.h>
14043 +#include <linux/udp.h>
14044 +
14045 +#include <linux/netfilter.h>
14046 +#include <linux/netfilter_ipv4/ip_tables.h>
14047 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
14048 +#include <linux/netfilter_ipv4/ip_conntrack_tftp.h>
14049 +#include <linux/netfilter_ipv4/ip_nat_helper.h>
14050 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
14051 +
14052 +MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
14053 +MODULE_DESCRIPTION("Netfilter NAT helper for tftp");
14054 +MODULE_LICENSE("GPL");
14055 +
14056 +#define MAX_PORTS 8
14057 +
14058 +static int ports[MAX_PORTS];
14059 +static int ports_c = 0;
14060 +#ifdef MODULE_PARM
14061 +MODULE_PARM(ports,"1-" __MODULE_STRING(MAX_PORTS) "i");
14062 +MODULE_PARM_DESC(ports, "port numbers of tftp servers");
14063 +#endif
14064 +
14065 +#if 0
14066 +#define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ": " \
14067 +                                      format, ## args)
14068 +#else
14069 +#define DEBUGP(format, args...)
14070 +#endif
14071 +static unsigned int 
14072 +tftp_nat_help(struct ip_conntrack *ct,
14073 +             struct ip_conntrack_expect *exp,
14074 +             struct ip_nat_info *info,
14075 +             enum ip_conntrack_info ctinfo,
14076 +             unsigned int hooknum,
14077 +             struct sk_buff **pskb)
14078 +{
14079 +       int dir = CTINFO2DIR(ctinfo);
14080 +       struct iphdr *iph = (*pskb)->nh.iph;
14081 +       struct udphdr *udph = (void *)iph + iph->ihl * 4;
14082 +       struct tftphdr *tftph = (void *)udph + 8;
14083 +       struct ip_conntrack_tuple repl;
14084 +
14085 +       if (!((hooknum == NF_IP_POST_ROUTING && dir == IP_CT_DIR_ORIGINAL)
14086 +             || (hooknum == NF_IP_PRE_ROUTING && dir == IP_CT_DIR_REPLY))) 
14087 +               return NF_ACCEPT;
14088 +
14089 +       if (!exp) {
14090 +               DEBUGP("no conntrack expectation to modify\n");
14091 +               return NF_ACCEPT;
14092 +       }
14093 +
14094 +       switch (ntohs(tftph->opcode)) {
14095 +       /* RRQ and WRQ works the same way */
14096 +       case TFTP_OPCODE_READ:
14097 +       case TFTP_OPCODE_WRITE:
14098 +               repl = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
14099 +               DEBUGP("");
14100 +               DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
14101 +               DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
14102 +               DEBUGP("expecting: ");
14103 +               DUMP_TUPLE(&repl);
14104 +               DUMP_TUPLE(&exp->mask);
14105 +               ip_conntrack_change_expect(exp, &repl);
14106 +               break;
14107 +       default:
14108 +               DEBUGP("Unknown opcode\n");
14109 +       }               
14110 +
14111 +       return NF_ACCEPT;
14112 +}
14113 +
14114 +static unsigned int 
14115 +tftp_nat_expected(struct sk_buff **pskb,
14116 +                 unsigned int hooknum,
14117 +                 struct ip_conntrack *ct, 
14118 +                 struct ip_nat_info *info) 
14119 +{
14120 +       const struct ip_conntrack *master = ct->master->expectant;
14121 +       const struct ip_conntrack_tuple *orig = 
14122 +                       &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
14123 +       struct ip_nat_multi_range mr;
14124 +#if 0
14125 +       const struct ip_conntrack_tuple *repl =
14126 +                       &master->tuplehash[IP_CT_DIR_REPLY].tuple;
14127 +       struct iphdr *iph = (*pskb)->nh.iph;
14128 +       struct udphdr *udph = (void *)iph + iph->ihl*4;
14129 +#endif
14130 +
14131 +       IP_NF_ASSERT(info);
14132 +       IP_NF_ASSERT(master);
14133 +       IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
14134 +
14135 +       mr.rangesize = 1;
14136 +       mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
14137 +
14138 +       if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC) {
14139 +               mr.range[0].min_ip = mr.range[0].max_ip = orig->dst.ip; 
14140 +               DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
14141 +                       "newsrc: %u.%u.%u.%u\n",
14142 +                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
14143 +                       NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
14144 +                       NIPQUAD(orig->dst.ip));
14145 +       } else {
14146 +               mr.range[0].min_ip = mr.range[0].max_ip = orig->src.ip;
14147 +               mr.range[0].min.udp.port = mr.range[0].max.udp.port = 
14148 +                                                       orig->src.u.udp.port;
14149 +               mr.range[0].flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
14150 +
14151 +               DEBUGP("orig: %u.%u.%u.%u:%u <-> %u.%u.%u.%u:%u "
14152 +                       "newdst: %u.%u.%u.%u:%u\n",
14153 +                        NIPQUAD((*pskb)->nh.iph->saddr), ntohs(udph->source),
14154 +                        NIPQUAD((*pskb)->nh.iph->daddr), ntohs(udph->dest),
14155 +                        NIPQUAD(orig->src.ip), ntohs(orig->src.u.udp.port));
14156 +       }
14157 +
14158 +       return ip_nat_setup_info(ct,&mr,hooknum);
14159 +}
14160 +
14161 +static struct ip_nat_helper tftp[MAX_PORTS];
14162 +static char tftp_names[MAX_PORTS][10];
14163 +
14164 +static void fini(void)
14165 +{
14166 +       int i;
14167 +
14168 +       for (i = 0 ; i < ports_c; i++) {
14169 +               DEBUGP("unregistering helper for port %d\n", ports[i]);
14170 +               ip_nat_helper_unregister(&tftp[i]);
14171 +       }
14172 +}
14173 +
14174 +static int __init init(void)
14175 +{
14176 +       int i, ret = 0;
14177 +       char *tmpname;
14178 +
14179 +       if (!ports[0])
14180 +               ports[0] = TFTP_PORT;
14181 +
14182 +       for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
14183 +               tftp[i].tuple.dst.protonum = IPPROTO_UDP;
14184 +               tftp[i].tuple.src.u.udp.port = htons(ports[i]);
14185 +               tftp[i].mask.dst.protonum = 0xFFFF;
14186 +               tftp[i].mask.src.u.udp.port = 0xFFFF;
14187 +               tftp[i].help = tftp_nat_help;
14188 +               tftp[i].flags = 0;
14189 +               tftp[i].me = THIS_MODULE;
14190 +               tftp[i].expect = tftp_nat_expected;
14191 +
14192 +               tmpname = &tftp_names[i][0];
14193 +               if (ports[i] == TFTP_PORT)
14194 +                       sprintf(tmpname, "tftp");
14195 +               else
14196 +                       sprintf(tmpname, "tftp-%d", i);
14197 +               tftp[i].name = tmpname;
14198 +               
14199 +               DEBUGP("ip_nat_tftp: registering for port %d: name %s\n",
14200 +                       ports[i], tftp[i].name);
14201 +               ret = ip_nat_helper_register(&tftp[i]);
14202 +
14203 +               if (ret) {
14204 +                       printk("ip_nat_tftp: unable to register for port %d\n",
14205 +                               ports[i]);
14206 +                       fini();
14207 +                       return ret;
14208 +               }
14209 +               ports_c++;
14210 +       }
14211 +       return ret;
14212 +}
14213 +
14214 +module_init(init);
14215 +module_exit(fini);
14216 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_pool.c linux-2.4.20/net/ipv4/netfilter/ip_pool.c
14217 --- linux-2.4.20.org/net/ipv4/netfilter/ip_pool.c       Thu Jan  1 00:00:00 1970
14218 +++ linux-2.4.20/net/ipv4/netfilter/ip_pool.c   Wed Sep 24 09:16:59 2003
14219 @@ -0,0 +1,332 @@
14220 +/* Kernel module for IP pool management */
14221 +
14222 +#include <linux/module.h>
14223 +#include <linux/ip.h>
14224 +#include <linux/skbuff.h>
14225 +#include <linux/netfilter_ipv4/ip_tables.h>
14226 +#include <linux/netfilter_ipv4/ip_pool.h>
14227 +#include <linux/errno.h>
14228 +#include <asm/uaccess.h>
14229 +#include <asm/bitops.h>
14230 +#include <linux/interrupt.h>
14231 +#include <linux/spinlock.h>
14232 +
14233 +#if 0
14234 +#define DP printk
14235 +#else
14236 +#define DP(format, args...)
14237 +#endif
14238 +
14239 +MODULE_LICENSE("GPL");
14240 +
14241 +#define NR_POOL 16
14242 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
14243 +
14244 +struct ip_pool {
14245 +       u_int32_t first_ip;     /* host byte order, included in range */
14246 +       u_int32_t last_ip;      /* host byte order, included in range */
14247 +       void *members;          /* the bitmap proper */
14248 +       int nr_use;             /* total nr. of tests through this */
14249 +       int nr_match;           /* total nr. of matches through this */
14250 +       rwlock_t lock;
14251 +};
14252 +
14253 +static struct ip_pool *POOL;
14254 +
14255 +static inline struct ip_pool *lookup(ip_pool_t index)
14256 +{
14257 +       if (index < 0 || index >= nr_pool) {
14258 +               DP("ip_pool:lookup: bad index %d\n", index);
14259 +               return 0;
14260 +       }
14261 +       return POOL+index;
14262 +}
14263 +
14264 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
14265 +{
14266 +        struct ip_pool *pool = lookup(index);
14267 +       int res = 0;
14268 +
14269 +       if (!pool || !pool->members)
14270 +               return 0;
14271 +       read_lock_bh(&pool->lock);
14272 +       if (pool->members) {
14273 +               if (addr >= pool->first_ip && addr <= pool->last_ip) {
14274 +                       addr -= pool->first_ip;
14275 +                       if (test_bit(addr, pool->members)) {
14276 +                               res = 1;
14277 +#ifdef CONFIG_IP_POOL_STATISTICS
14278 +                               pool->nr_match++;
14279 +#endif
14280 +                       }
14281 +               }
14282 +#ifdef CONFIG_IP_POOL_STATISTICS
14283 +               pool->nr_use++;
14284 +#endif
14285 +       }
14286 +       read_unlock_bh(&pool->lock);
14287 +       return res;
14288 +}
14289 +
14290 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
14291 +{
14292 +       struct ip_pool *pool;
14293 +       int res = -1;
14294 +
14295 +       pool = lookup(index);
14296 +       if (    !pool || !pool->members
14297 +            || addr < pool->first_ip || addr > pool->last_ip)
14298 +               return -1;
14299 +       read_lock_bh(&pool->lock);
14300 +       if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
14301 +               addr -= pool->first_ip;
14302 +               res = isdel
14303 +                       ? (0 != test_and_clear_bit(addr, pool->members))
14304 +                       : (0 != test_and_set_bit(addr, pool->members));
14305 +       }
14306 +       read_unlock_bh(&pool->lock);
14307 +       return res;
14308 +}
14309 +
14310 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
14311 +{
14312 +       int res = pool_change(index,addr,isdel);
14313 +
14314 +       if (!isdel) res = !res;
14315 +       return res;
14316 +}
14317 +
14318 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
14319 +{
14320 +       return 4*((((b-a+8)/8)+3)/4);
14321 +}
14322 +
14323 +static inline int poolbytes(ip_pool_t index)
14324 +{
14325 +       struct ip_pool *pool = lookup(index);
14326 +
14327 +       return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
14328 +}
14329 +
14330 +static int setpool(
14331 +       struct sock *sk,
14332 +       int optval,
14333 +       void *user,
14334 +       unsigned int len
14335 +) {
14336 +       struct ip_pool_request req;
14337 +
14338 +       DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
14339 +       if (!capable(CAP_NET_ADMIN))
14340 +               return -EPERM;
14341 +       if (optval != SO_IP_POOL)
14342 +               return -EBADF;
14343 +       if (len != sizeof(req))
14344 +               return -EINVAL;
14345 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
14346 +               return -EFAULT;
14347 +       printk("obsolete op - upgrade your ippool(8) utility.\n");
14348 +       return -EINVAL;
14349 +}
14350 +
14351 +static int getpool(
14352 +       struct sock *sk,
14353 +       int optval,
14354 +       void *user,
14355 +       int *len
14356 +) {
14357 +       struct ip_pool_request req;
14358 +       struct ip_pool *pool;
14359 +       ip_pool_t i;
14360 +       int newbytes;
14361 +       void *newmembers;
14362 +       int res;
14363 +
14364 +       DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
14365 +       if (!capable(CAP_NET_ADMIN))
14366 +               return -EINVAL;
14367 +       if (optval != SO_IP_POOL)
14368 +               return -EINVAL;
14369 +       if (*len != sizeof(req)) {
14370 +               return -EFAULT;
14371 +       }
14372 +       if (copy_from_user(&req, user, sizeof(req)) != 0)
14373 +               return -EFAULT;
14374 +       DP("ip_pool:getpool op=%d, index=%d\n", req.op, req.index);
14375 +       if (req.op < IP_POOL_BAD001) {
14376 +               printk("obsolete op - upgrade your ippool(8) utility.\n");
14377 +               return -EFAULT;
14378 +       }
14379 +       switch(req.op) {
14380 +       case IP_POOL_HIGH_NR:
14381 +               DP("ip_pool HIGH_NR\n");
14382 +               req.index = IP_POOL_NONE;
14383 +               for (i=0; i<nr_pool; i++)
14384 +                       if (POOL[i].members)
14385 +                               req.index = i;
14386 +               return copy_to_user(user, &req, sizeof(req));
14387 +       case IP_POOL_LOOKUP:
14388 +               DP("ip_pool LOOKUP\n");
14389 +               pool = lookup(req.index);
14390 +               if (!pool)
14391 +                       return -EINVAL;
14392 +               if (!pool->members)
14393 +                       return -EBADF;
14394 +               req.addr = htonl(pool->first_ip);
14395 +               req.addr2 = htonl(pool->last_ip);
14396 +               return copy_to_user(user, &req, sizeof(req));
14397 +       case IP_POOL_USAGE:
14398 +               DP("ip_pool USE\n");
14399 +               pool = lookup(req.index);
14400 +               if (!pool)
14401 +                       return -EINVAL;
14402 +               if (!pool->members)
14403 +                       return -EBADF;
14404 +               req.addr = pool->nr_use;
14405 +               req.addr2 = pool->nr_match;
14406 +               return copy_to_user(user, &req, sizeof(req));
14407 +       case IP_POOL_TEST_ADDR:
14408 +               DP("ip_pool TEST 0x%08x\n", req.addr);
14409 +               pool = lookup(req.index);
14410 +               if (!pool)
14411 +                       return -EINVAL;
14412 +               res = 0;
14413 +               read_lock_bh(&pool->lock);
14414 +               if (!pool->members) {
14415 +                       DP("ip_pool TEST_ADDR no members in pool\n");
14416 +                       res = -EBADF;
14417 +                       goto unlock_and_return_res;
14418 +               }
14419 +               req.addr = ntohl(req.addr);
14420 +               if (req.addr < pool->first_ip) {
14421 +                       DP("ip_pool TEST_ADDR address < pool bounds\n");
14422 +                       res = -ERANGE;
14423 +                       goto unlock_and_return_res;
14424 +               }
14425 +               if (req.addr > pool->last_ip) {
14426 +                       DP("ip_pool TEST_ADDR address > pool bounds\n");
14427 +                       res = -ERANGE;
14428 +                       goto unlock_and_return_res;
14429 +               }
14430 +               req.addr = (0 != test_bit((req.addr - pool->first_ip),
14431 +                                       pool->members));
14432 +               read_unlock_bh(&pool->lock);
14433 +               return copy_to_user(user, &req, sizeof(req));
14434 +       case IP_POOL_FLUSH:
14435 +               DP("ip_pool FLUSH not yet implemented.\n");
14436 +               return -EBUSY;
14437 +       case IP_POOL_DESTROY:
14438 +               DP("ip_pool DESTROY not yet implemented.\n");
14439 +               return -EBUSY;
14440 +       case IP_POOL_INIT:
14441 +               DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
14442 +               pool = lookup(req.index);
14443 +               if (!pool)
14444 +                       return -EINVAL;
14445 +               req.addr = ntohl(req.addr);
14446 +               req.addr2 = ntohl(req.addr2);
14447 +               if (req.addr > req.addr2) {
14448 +                       DP("ip_pool INIT bad ip range\n");
14449 +                       return -EINVAL;
14450 +               }
14451 +               newbytes = bitmap_bytes(req.addr, req.addr2);
14452 +               newmembers = kmalloc(newbytes, GFP_KERNEL);
14453 +               if (!newmembers) {
14454 +                       DP("ip_pool INIT out of mem for %d bytes\n", newbytes);
14455 +                       return -ENOMEM;
14456 +               }
14457 +               memset(newmembers, 0, newbytes);
14458 +               write_lock_bh(&pool->lock);
14459 +               if (pool->members) {
14460 +                       DP("ip_pool INIT pool %d exists\n", req.index);
14461 +                       kfree(newmembers);
14462 +                       res = -EBUSY;
14463 +                       goto unlock_and_return_res;
14464 +               }
14465 +               pool->first_ip = req.addr;
14466 +               pool->last_ip = req.addr2;
14467 +               pool->nr_use = 0;
14468 +               pool->nr_match = 0;
14469 +               pool->members = newmembers;
14470 +               write_unlock_bh(&pool->lock);
14471 +               return 0;
14472 +       case IP_POOL_ADD_ADDR:
14473 +               DP("ip_pool ADD_ADDR 0x%08x\n", req.addr);
14474 +               req.addr = pool_change(req.index, ntohl(req.addr), 0);
14475 +               return copy_to_user(user, &req, sizeof(req));
14476 +       case IP_POOL_DEL_ADDR:
14477 +               DP("ip_pool DEL_ADDR 0x%08x\n", req.addr);
14478 +               req.addr = pool_change(req.index, ntohl(req.addr), 1);
14479 +               return copy_to_user(user, &req, sizeof(req));
14480 +       default:
14481 +               DP("ip_pool:getpool bad op %d\n", req.op);
14482 +               return -EINVAL;
14483 +       }
14484 +       return -EINVAL;
14485 +
14486 +unlock_and_return_res:
14487 +       if (pool)
14488 +               read_unlock_bh(&pool->lock);
14489 +       return res;
14490 +}
14491 +
14492 +static struct nf_sockopt_ops so_pool
14493 += { { NULL, NULL }, PF_INET,
14494 +    SO_IP_POOL, SO_IP_POOL+1, &setpool,
14495 +    SO_IP_POOL, SO_IP_POOL+1, &getpool,
14496 +    0, NULL };
14497 +
14498 +MODULE_PARM(nr_pool, "i");
14499 +
14500 +static int __init init(void)
14501 +{
14502 +       ip_pool_t i;
14503 +       int res;
14504 +
14505 +       if (nr_pool < 1) {
14506 +               printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
14507 +               return -EINVAL;
14508 +       }
14509 +       POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
14510 +       if (!POOL) {
14511 +               printk("ip_pool module init: out of memory for nr_pool %d\n",
14512 +                       nr_pool);
14513 +               return -ENOMEM;
14514 +       }
14515 +       for (i=0; i<nr_pool; i++) {
14516 +               POOL[i].first_ip = 0;
14517 +               POOL[i].last_ip = 0;
14518 +               POOL[i].members = 0;
14519 +               POOL[i].nr_use = 0;
14520 +               POOL[i].nr_match = 0;
14521 +               POOL[i].lock = RW_LOCK_UNLOCKED;
14522 +       }
14523 +       res = nf_register_sockopt(&so_pool);
14524 +       DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
14525 +       if (res != 0) {
14526 +               kfree(POOL);
14527 +               POOL = 0;
14528 +       }
14529 +       return res;
14530 +}
14531 +
14532 +static void __exit fini(void)
14533 +{
14534 +       ip_pool_t i;
14535 +
14536 +       DP("ip_pool:fini BYEBYE\n");
14537 +       nf_unregister_sockopt(&so_pool);
14538 +       for (i=0; i<nr_pool; i++) {
14539 +               if (POOL[i].members) {
14540 +                       kfree(POOL[i].members);
14541 +                       POOL[i].members = 0;
14542 +               }
14543 +       }
14544 +       kfree(POOL);
14545 +       POOL = 0;
14546 +       DP("ip_pool:fini these are the famous last words\n");
14547 +       return;
14548 +}
14549 +
14550 +module_init(init);
14551 +module_exit(fini);
14552 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_queue.c linux-2.4.20/net/ipv4/netfilter/ip_queue.c
14553 --- linux-2.4.20.org/net/ipv4/netfilter/ip_queue.c      Thu Nov 28 23:53:15 2002
14554 +++ linux-2.4.20/net/ipv4/netfilter/ip_queue.c  Wed Sep 24 09:16:14 2003
14555 @@ -300,8 +300,9 @@
14556         write_lock_bh(&queue_lock);
14557         
14558         if (!peer_pid)
14559 -               goto err_out_unlock;
14560 +               goto err_out_free_nskb; 
14561  
14562 +       /* netlink_unicast will either free the nskb or attach it to a socket */ 
14563         status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
14564         if (status < 0)
14565                 goto err_out_unlock;
14566 @@ -312,6 +313,9 @@
14567  
14568         write_unlock_bh(&queue_lock);
14569         return status;
14570 +
14571 +err_out_free_nskb:
14572 +       kfree_skb(nskb); 
14573         
14574  err_out_unlock:
14575         write_unlock_bh(&queue_lock);
14576 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ip_tables.c linux-2.4.20/net/ipv4/netfilter/ip_tables.c
14577 --- linux-2.4.20.org/net/ipv4/netfilter/ip_tables.c     Thu Nov 28 23:53:15 2002
14578 +++ linux-2.4.20/net/ipv4/netfilter/ip_tables.c Wed Sep 24 09:18:12 2003
14579 @@ -4,6 +4,10 @@
14580   * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
14581   * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
14582   *
14583 + *  6 Mar 2002 Robert Olsson <robban@robtex.com>
14584 + * 17 Apr 2003 Chris  Wilson <chris@netservers.co.uk>
14585 + *     - mark_source_chains speedup for complex chains
14586 + *
14587   * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
14588   *     - increase module usage count as soon as we have rules inside
14589   *       a table
14590 @@ -24,6 +28,17 @@
14591  #include <linux/proc_fs.h>
14592  
14593  #include <linux/netfilter_ipv4/ip_tables.h>
14594 +#include <linux/netfilter_ipv4/ip_logging.h>
14595 +
14596 +#ifdef CONFIG_IP_NF_TARGET_TRACE_NEEDED
14597 +static const char *hooknames[] = { 
14598 +       [NF_IP_PRE_ROUTING] "PREROUTING",
14599 +       [NF_IP_LOCAL_IN] "INPUT",
14600 +       [NF_IP_FORWARD] "FORWARD",
14601 +       [NF_IP_LOCAL_OUT] "OUTPUT",
14602 +       [NF_IP_POST_ROUTING] "POSTROUTING",
14603 +};
14604 +#endif
14605  
14606  /*#define DEBUG_IP_FIREWALL*/
14607  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
14608 @@ -68,13 +83,12 @@
14609  #define inline
14610  #endif
14611  
14612 -/* Locking is simple: we assume at worst case there will be one packet
14613 -   in user context and one from bottom halves (or soft irq if Alexey's
14614 -   softnet patch was applied).
14615 -
14616 +/*
14617     We keep a set of rules for each CPU, so we can avoid write-locking
14618 -   them; doing a readlock_bh() stops packets coming through if we're
14619 -   in user context.
14620 +   them in the softirq when updating the counters and therefore
14621 +   only need to read-lock in the softirq; doing a write_lock_bh() in user
14622 +   context stops packets coming through and allows user context to read
14623 +   the counters or update the rules.
14624  
14625     To be cache friendly on SMP, we arrange them like so:
14626     [ n-entries ]
14627 @@ -251,6 +265,39 @@
14628         return (struct ipt_entry *)(base + offset);
14629  }
14630  
14631 +static inline int
14632 +get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
14633 +                     char **chainname, u_int16_t *rulenum)
14634 +{
14635 +       struct ipt_entry_target *t;
14636 +
14637 +       (*rulenum)++;
14638 +
14639 +       if (s == e)
14640 +               return 1;
14641 +
14642 +       t = ipt_get_target(s);
14643 +       if (strcmp(t->u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
14644 +               *chainname = t->data;
14645 +               (*rulenum) = 0;
14646 +       }
14647 +       
14648 +       return 0;
14649 +}
14650 +
14651 +/* All zeroes == unconditional rule. */
14652 +static inline int
14653 +unconditional(const struct ipt_ip *ip)
14654 +{
14655 +       unsigned int i;
14656 +
14657 +       for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
14658 +               if (((__u32 *)ip)[i])
14659 +                       return 0;
14660 +
14661 +       return 1;
14662 +}
14663 +
14664  /* Returns one of the generic firewall policies, like NF_ACCEPT. */
14665  unsigned int
14666  ipt_do_table(struct sk_buff **pskb,
14667 @@ -326,6 +373,27 @@
14668  
14669                         t = ipt_get_target(e);
14670                         IP_NF_ASSERT(t->u.kernel.target);
14671 +#ifdef CONFIG_IP_NF_TARGET_TRACE_NEEDED
14672 +                       /* The packet traced and the rule isn't an unconditional return/END. */
14673 +                       if (((*pskb)->nfcache & NFC_TRACE)
14674 +                           && !(e->target_offset == sizeof(struct ipt_entry)
14675 +                                && (strcmp(t->u.kernel.target->name,
14676 +                                      IPT_STANDARD_TARGET) == 0)
14677 +                                && !t->u.kernel.target->target
14678 +                                && ((struct ipt_standard_target *)t)->verdict < 0
14679 +                                && unconditional(&e->ip))) {
14680 +                               char *chainname = (char *) hooknames[hook];
14681 +                               u_int16_t rulenum = 0;
14682 +                               
14683 +                               IPT_ENTRY_ITERATE(get_entry(table_base, table->private->hook_entry[hook]),
14684 +                                                 table->private->size,
14685 +                                                 get_chainname_rulenum,
14686 +                                                 e, &chainname, &rulenum);
14687 +                                                 
14688 +                               nf_log_ip_packet(pskb, hook, in, out, "TRACE: %s/%s/%u ",
14689 +                                                table->name, chainname, rulenum);
14690 +                       }
14691 +#endif
14692                         /* Standard target? */
14693                         if (!t->u.kernel.target->target) {
14694                                 int v;
14695 @@ -482,19 +550,6 @@
14696         return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
14697  }
14698  
14699 -/* All zeroes == unconditional rule. */
14700 -static inline int
14701 -unconditional(const struct ipt_ip *ip)
14702 -{
14703 -       unsigned int i;
14704 -
14705 -       for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
14706 -               if (((__u32 *)ip)[i])
14707 -                       return 0;
14708 -
14709 -       return 1;
14710 -}
14711 -
14712  /* Figures out from what hook each rule can be called: returns 0 if
14713     there are loops.  Puts hook bitmask in comefrom. */
14714  static int
14715 @@ -502,6 +557,9 @@
14716  {
14717         unsigned int hook;
14718  
14719 +       /* keep track of where we have been: */
14720 +       unsigned char *been = vmalloc(newinfo->size);
14721 +
14722         /* No recursion; use packet counter to save back ptrs (reset
14723            to 0 as we leave), and comefrom to save source hook bitmask */
14724         for (hook = 0; hook < NF_IP_NUMHOOKS; hook++) {
14725 @@ -514,6 +572,7 @@
14726  
14727                 /* Set initial back pointer. */
14728                 e->counters.pcnt = pos;
14729 +               memset(been, 0, newinfo->size);
14730  
14731                 for (;;) {
14732                         struct ipt_standard_target *t
14733 @@ -522,6 +581,7 @@
14734                         if (e->comefrom & (1 << NF_IP_NUMHOOKS)) {
14735                                 printk("iptables: loop hook %u pos %u %08X.\n",
14736                                        hook, pos, e->comefrom);
14737 +                               vfree(been);
14738                                 return 0;
14739                         }
14740                         e->comefrom
14741 @@ -569,10 +629,14 @@
14742                         } else {
14743                                 int newpos = t->verdict;
14744  
14745 -                               if (strcmp(t->target.u.user.name,
14746 +                               if ( (pos < 0 || pos >= newinfo->size
14747 +                                     || !been[pos]) 
14748 +                                   && strcmp(t->target.u.user.name,
14749                                            IPT_STANDARD_TARGET) == 0
14750                                     && newpos >= 0) {
14751                                         /* This a jump; chase it. */
14752 +                                       if (pos >= 0 && pos < newinfo->size)
14753 +                                               been[pos]++;
14754                                         duprintf("Jump rule %u -> %u\n",
14755                                                  pos, newpos);
14756                                 } else {
14757 @@ -588,6 +652,7 @@
14758                 next:
14759                 duprintf("Finished chain %u\n", hook);
14760         }
14761 +       vfree(been);
14762         return 1;
14763  }
14764  
14765 @@ -1630,7 +1695,7 @@
14766                      u_int8_t type, u_int8_t code,
14767                      int invert)
14768  {
14769 -       return (type == test_type && code >= min_code && code <= max_code)
14770 +       return ((test_type == 0xFF) || (type == test_type && code >= min_code && code <= max_code))
14771                 ^ invert;
14772  }
14773  
14774 @@ -1699,14 +1764,15 @@
14775  = { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
14776  
14777  #ifdef CONFIG_PROC_FS
14778 -static inline int print_name(const struct ipt_table *t,
14779 +static inline int print_name(const char *i,
14780                              off_t start_offset, char *buffer, int length,
14781                              off_t *pos, unsigned int *count)
14782  {
14783         if ((*count)++ >= start_offset) {
14784                 unsigned int namelen;
14785  
14786 -               namelen = sprintf(buffer + *pos, "%s\n", t->name);
14787 +               namelen = sprintf(buffer + *pos, "%s\n",
14788 +                                 i + sizeof(struct list_head));
14789                 if (*pos + namelen > length) {
14790                         /* Stop iterating */
14791                         return 1;
14792 @@ -1724,7 +1790,7 @@
14793         if (down_interruptible(&ipt_mutex) != 0)
14794                 return 0;
14795  
14796 -       LIST_FIND(&ipt_tables, print_name, struct ipt_table *,
14797 +       LIST_FIND(&ipt_tables, print_name, void *,
14798                   offset, buffer, length, &pos, &count);
14799  
14800         up(&ipt_mutex);
14801 @@ -1733,6 +1799,46 @@
14802         *start=(char *)((unsigned long)count-offset);
14803         return pos;
14804  }
14805 +
14806 +static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
14807 +{
14808 +       off_t pos = 0;
14809 +       unsigned int count = 0;
14810 +
14811 +       if (down_interruptible(&ipt_mutex) != 0)
14812 +               return 0;
14813 +
14814 +       LIST_FIND(&ipt_target, print_name, void *,
14815 +                 offset, buffer, length, &pos, &count);
14816 +       
14817 +       up(&ipt_mutex);
14818 +
14819 +       *start = (char *)((unsigned long)count - offset);
14820 +       return pos;
14821 +}
14822 +
14823 +static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
14824 +{
14825 +       off_t pos = 0;
14826 +       unsigned int count = 0;
14827 +
14828 +       if (down_interruptible(&ipt_mutex) != 0)
14829 +               return 0;
14830 +       
14831 +       LIST_FIND(&ipt_match, print_name, void *,
14832 +                 offset, buffer, length, &pos, &count);
14833 +
14834 +       up(&ipt_mutex);
14835 +
14836 +       *start = (char *)((unsigned long)count - offset);
14837 +       return pos;
14838 +}
14839 +
14840 +static struct { char *name; get_info_t *get_info; } ipt_proc_entry[] =
14841 +{ { "ip_tables_names", ipt_get_tables },
14842 +  { "ip_tables_targets", ipt_get_targets },
14843 +  { "ip_tables_matches", ipt_get_matches },
14844 +  { NULL, NULL} };
14845  #endif /*CONFIG_PROC_FS*/
14846  
14847  static int __init init(void)
14848 @@ -1758,13 +1864,19 @@
14849  #ifdef CONFIG_PROC_FS
14850         {
14851         struct proc_dir_entry *proc;
14852 +       int i;
14853  
14854 -       proc = proc_net_create("ip_tables_names", 0, ipt_get_tables);
14855 -       if (!proc) {
14856 -               nf_unregister_sockopt(&ipt_sockopts);
14857 -               return -ENOMEM;
14858 +       for (i = 0; ipt_proc_entry[i].name; i++) {
14859 +               proc = proc_net_create(ipt_proc_entry[i].name, 0,
14860 +                                      ipt_proc_entry[i].get_info);
14861 +               if (!proc) {
14862 +                       while (--i >= 0)
14863 +                               proc_net_remove(ipt_proc_entry[i].name);
14864 +                       nf_unregister_sockopt(&ipt_sockopts);
14865 +                       return -ENOMEM;
14866 +               }
14867 +               proc->owner = THIS_MODULE;
14868         }
14869 -       proc->owner = THIS_MODULE;
14870         }
14871  #endif
14872  
14873 @@ -1776,7 +1888,11 @@
14874  {
14875         nf_unregister_sockopt(&ipt_sockopts);
14876  #ifdef CONFIG_PROC_FS
14877 -       proc_net_remove("ip_tables_names");
14878 +       {
14879 +       int i;
14880 +       for (i = 0; ipt_proc_entry[i].name; i++)
14881 +               proc_net_remove(ipt_proc_entry[i].name);
14882 +       }
14883  #endif
14884  }
14885  
14886 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipchains_core.c linux-2.4.20/net/ipv4/netfilter/ipchains_core.c
14887 --- linux-2.4.20.org/net/ipv4/netfilter/ipchains_core.c Thu Nov 28 23:53:15 2002
14888 +++ linux-2.4.20/net/ipv4/netfilter/ipchains_core.c     Wed Sep 24 09:16:14 2003
14889 @@ -1566,16 +1566,8 @@
14890  
14891  /* File offset is actually in records, not bytes. */
14892  static int ip_chain_procinfo(char *buffer, char **start,
14893 -                            off_t offset, int length
14894 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14895 -                            , int reset
14896 -#endif
14897 -       )
14898 +                            off_t offset, int length)
14899  {
14900 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14901 -       /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
14902 -       int reset = 0;
14903 -#endif
14904         struct ip_chain *i;
14905         struct ip_fwkernel *j = ip_fw_chains->chain;
14906         unsigned long flags;
14907 @@ -1612,9 +1604,6 @@
14908                                 len = last_len;
14909                                 goto outside;
14910                         }
14911 -                       else if (reset)
14912 -                               memset(j->counters, 0,
14913 -                                      sizeof(struct ip_counters)*NUM_SLOTS);
14914                 }
14915         }
14916  outside:
14917 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipfwadm_core.c linux-2.4.20/net/ipv4/netfilter/ipfwadm_core.c
14918 --- linux-2.4.20.org/net/ipv4/netfilter/ipfwadm_core.c  Wed Sep 24 08:52:55 2003
14919 +++ linux-2.4.20/net/ipv4/netfilter/ipfwadm_core.c      Wed Sep 24 09:16:14 2003
14920 @@ -1108,9 +1108,8 @@
14921  #endif /* CONFIG_IP_FIREWALL */
14922  
14923  #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
14924 -
14925  static int ip_chain_procinfo(int stage, char *buffer, char **start,
14926 -                            off_t offset, int length, int reset)
14927 +                            off_t offset, int length)
14928  {
14929         off_t pos=0, begin=0;
14930         struct ip_fw *i;
14931 @@ -1181,12 +1180,6 @@
14932                         len = last_len;
14933                         break;
14934                 }
14935 -               else if(reset)
14936 -               {
14937 -                       /* This needs to be done at this specific place! */
14938 -                       i->fw_pcnt=0L;
14939 -                       i->fw_bcnt=0L;
14940 -               }
14941                 last_len = len;
14942                 i=i->fw_next;
14943         }
14944 @@ -1200,69 +1193,30 @@
14945  #endif
14946  
14947  #ifdef CONFIG_IP_ACCT
14948 -
14949  static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
14950 -                           int length
14951 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14952 -                           , int reset
14953 -#endif
14954 -       )
14955 +                           int length)
14956  {
14957 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14958 -       /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
14959 -       int reset = 0;
14960 -#endif
14961 -       return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length,
14962 -                                reset);
14963 +       return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length);
14964  }
14965 -
14966  #endif
14967  
14968  #ifdef CONFIG_IP_FIREWALL
14969 -
14970  static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
14971 -                             int length
14972 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14973 -                            , int reset
14974 -#endif
14975 -       )
14976 +                             int length)
14977  {
14978 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14979 -       /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
14980 -       int reset = 0;
14981 -#endif
14982 -       return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length,
14983 -                                reset);
14984 +       return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length);
14985  }
14986  
14987  static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
14988 -                             int length
14989 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14990 -                           , int reset
14991 -#endif
14992 -       )
14993 +                             int length)
14994  {
14995 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14996 -       /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
14997 -       int reset = 0;
14998 -#endif
14999 -       return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length,
15000 -                                reset);
15001 +       return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length);
15002  }
15003  
15004  static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
15005 -                             int length
15006 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
15007 -                           , int reset
15008 -#endif
15009 -       )
15010 +                             int length)
15011  {
15012 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
15013 -       /* FIXME: No more `atomic' read and reset.  Wonderful 8-( --RR */
15014 -       int reset = 0;
15015 -#endif
15016 -       return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length,
15017 -                                reset);
15018 +       return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length);
15019  }
15020  #endif
15021  
15022 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_CLASSIFY.c linux-2.4.20/net/ipv4/netfilter/ipt_CLASSIFY.c
15023 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_CLASSIFY.c  Thu Jan  1 00:00:00 1970
15024 +++ linux-2.4.20/net/ipv4/netfilter/ipt_CLASSIFY.c      Wed Sep 24 09:17:14 2003
15025 @@ -0,0 +1,82 @@
15026 +/*
15027 + * This is a module which is used for setting the skb->priority field
15028 + * of an skb for qdisc classification.
15029 + */
15030 +
15031 +#include <linux/module.h>
15032 +#include <linux/skbuff.h>
15033 +#include <linux/ip.h>
15034 +#include <net/checksum.h>
15035 +
15036 +#include <linux/netfilter_ipv4/ip_tables.h>
15037 +#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
15038 +
15039 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
15040 +MODULE_LICENSE("GPL");
15041 +MODULE_DESCRIPTION("iptables qdisc classification target module");
15042 +
15043 +static unsigned int
15044 +target(struct sk_buff **pskb,
15045 +       unsigned int hooknum,
15046 +       const struct net_device *in,
15047 +       const struct net_device *out,
15048 +       const void *targinfo,
15049 +       void *userinfo)
15050 +{
15051 +       const struct ipt_classify_target_info *clinfo = targinfo;
15052 +
15053 +       if((*pskb)->priority != clinfo->priority) {
15054 +               (*pskb)->priority = clinfo->priority;
15055 +               (*pskb)->nfcache |= NFC_ALTERED;
15056 +       }
15057 +
15058 +       return IPT_CONTINUE;
15059 +}
15060 +
15061 +static int
15062 +checkentry(const char *tablename,
15063 +           const struct ipt_entry *e,
15064 +           void *targinfo,
15065 +           unsigned int targinfosize,
15066 +           unsigned int hook_mask)
15067 +{
15068 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
15069 +               printk(KERN_ERR "CLASSIFY: invalid size (%u != %u).\n",
15070 +                      targinfosize,
15071 +                      IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
15072 +               return 0;
15073 +       }
15074 +       
15075 +       if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
15076 +               printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
15077 +               return 0;
15078 +       }
15079 +
15080 +       if (strcmp(tablename, "mangle") != 0) {
15081 +               printk(KERN_WARNING "CLASSIFY: can only be called from "
15082 +                                   "\"mangle\" table, not \"%s\".\n",
15083 +                                   tablename);
15084 +               return 0;
15085 +       }
15086 +
15087 +       return 1;
15088 +}
15089 +
15090 +static struct ipt_target ipt_classify_reg
15091 += { { NULL, NULL }, "CLASSIFY", target, checkentry, NULL, THIS_MODULE };
15092 +
15093 +static int __init init(void)
15094 +{
15095 +       if (ipt_register_target(&ipt_classify_reg))
15096 +               return -EINVAL;
15097 +
15098 +       return 0;
15099 +}
15100 +
15101 +static void __exit fini(void)
15102 +{
15103 +       ipt_unregister_target(&ipt_classify_reg);
15104 +}
15105 +
15106 +module_init(init);
15107 +module_exit(fini);
15108 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_CONNMARK.c linux-2.4.20/net/ipv4/netfilter/ipt_CONNMARK.c
15109 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_CONNMARK.c  Thu Jan  1 00:00:00 1970
15110 +++ linux-2.4.20/net/ipv4/netfilter/ipt_CONNMARK.c      Wed Sep 24 09:17:17 2003
15111 @@ -0,0 +1,87 @@
15112 +/* This is a module which is used for setting/remembering the mark field of
15113 + * an connection, or optionally restore it to the skb
15114 + */
15115 +#include <linux/module.h>
15116 +#include <linux/skbuff.h>
15117 +#include <linux/ip.h>
15118 +#include <net/checksum.h>
15119 +
15120 +#include <linux/netfilter_ipv4/ip_tables.h>
15121 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
15122 +#include <linux/netfilter_ipv4/ip_conntrack.h>
15123 +
15124 +static unsigned int
15125 +target(struct sk_buff **pskb,
15126 +       unsigned int hooknum,
15127 +       const struct net_device *in,
15128 +       const struct net_device *out,
15129 +       const void *targinfo,
15130 +       void *userinfo)
15131 +{
15132 +       const struct ipt_connmark_target_info *markinfo = targinfo;
15133 +
15134 +       enum ip_conntrack_info ctinfo;
15135 +       struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
15136 +       if (ct) {
15137 +           switch(markinfo->mode) {
15138 +           case IPT_CONNMARK_SET:
15139 +               ct->mark = markinfo->mark;
15140 +               break;
15141 +           case IPT_CONNMARK_SAVE:
15142 +               ct->mark = (*pskb)->nfmark;
15143 +               break;
15144 +           case IPT_CONNMARK_RESTORE:
15145 +               if (ct->mark != (*pskb)->nfmark) {
15146 +                   (*pskb)->nfmark = ct->mark;
15147 +                   (*pskb)->nfcache |= NFC_ALTERED;
15148 +               }
15149 +               break;
15150 +           }
15151 +       }
15152 +
15153 +       return IPT_CONTINUE;
15154 +}
15155 +
15156 +static int
15157 +checkentry(const char *tablename,
15158 +          const struct ipt_entry *e,
15159 +           void *targinfo,
15160 +           unsigned int targinfosize,
15161 +           unsigned int hook_mask)
15162 +{
15163 +       struct ipt_connmark_target_info *matchinfo = targinfo;
15164 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_connmark_target_info))) {
15165 +               printk(KERN_WARNING "CONNMARK: targinfosize %u != %Zu\n",
15166 +                      targinfosize,
15167 +                      IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
15168 +               return 0;
15169 +       }
15170 +
15171 +       if (matchinfo->mode == IPT_CONNMARK_RESTORE) {
15172 +           if (strcmp(tablename, "mangle") != 0) {
15173 +                   printk(KERN_WARNING "CONNMARK: restore can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15174 +                   return 0;
15175 +           }
15176 +       }
15177 +
15178 +       return 1;
15179 +}
15180 +
15181 +static struct ipt_target ipt_connmark_reg
15182 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
15183 +
15184 +static int __init init(void)
15185 +{
15186 +       if (ipt_register_target(&ipt_connmark_reg))
15187 +               return -EINVAL;
15188 +
15189 +       return 0;
15190 +}
15191 +
15192 +static void __exit fini(void)
15193 +{
15194 +       ipt_unregister_target(&ipt_connmark_reg);
15195 +}
15196 +
15197 +module_init(init);
15198 +module_exit(fini);
15199 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_ECN.c linux-2.4.20/net/ipv4/netfilter/ipt_ECN.c
15200 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_ECN.c       Thu Nov 28 23:53:15 2002
15201 +++ linux-2.4.20/net/ipv4/netfilter/ipt_ECN.c   Wed Sep 24 09:16:14 2003
15202 @@ -87,8 +87,8 @@
15203         }
15204         
15205         if (diffs[0] != *tcpflags) {
15206 -               diffs[0] = htons(diffs[0]) ^ 0xFFFF;
15207 -               diffs[1] = htons(*tcpflags);
15208 +               diffs[0] = diffs[0] ^ 0xFFFF;
15209 +               diffs[1] = *tcpflags;
15210                 tcph->check = csum_fold(csum_partial((char *)diffs,
15211                                                     sizeof(diffs),
15212                                                     tcph->check^0xFFFF));
15213 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_IMQ.c linux-2.4.20/net/ipv4/netfilter/ipt_IMQ.c
15214 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_IMQ.c       Thu Jan  1 00:00:00 1970
15215 +++ linux-2.4.20/net/ipv4/netfilter/ipt_IMQ.c   Wed Sep 24 09:17:19 2003
15216 @@ -0,0 +1,78 @@
15217 +/* This target marks packets to be enqueued to an imq device */
15218 +#include <linux/module.h>
15219 +#include <linux/skbuff.h>
15220 +#include <linux/netfilter_ipv4/ip_tables.h>
15221 +#include <linux/netfilter_ipv4/ipt_IMQ.h>
15222 +#include <linux/imq.h>
15223 +
15224 +static unsigned int imq_target(struct sk_buff **pskb,
15225 +                              unsigned int hooknum,
15226 +                              const struct net_device *in,
15227 +                              const struct net_device *out,
15228 +                              const void *targinfo,
15229 +                              void *userinfo)
15230 +{
15231 +       struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
15232 +
15233 +       (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
15234 +       (*pskb)->nfcache |= NFC_ALTERED;
15235 +
15236 +       return IPT_CONTINUE;
15237 +}
15238 +
15239 +static int imq_checkentry(const char *tablename,
15240 +                         const struct ipt_entry *e,
15241 +                         void *targinfo,
15242 +                         unsigned int targinfosize,
15243 +                         unsigned int hook_mask)
15244 +{
15245 +       struct ipt_imq_info *mr;
15246 +
15247 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
15248 +               printk(KERN_WARNING "IMQ: invalid targinfosize\n");
15249 +               return 0;
15250 +       }
15251 +       mr = (struct ipt_imq_info*)targinfo;
15252 +
15253 +       if (strcmp(tablename, "mangle") != 0) {
15254 +               printk(KERN_WARNING
15255 +                      "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
15256 +                      tablename);
15257 +               return 0;
15258 +       }
15259 +       
15260 +       if (mr->todev > IMQ_MAX_DEVS) {
15261 +               printk(KERN_WARNING
15262 +                      "IMQ: invalid device specified, highest is %u\n",
15263 +                      IMQ_MAX_DEVS);
15264 +               return 0;
15265 +       }
15266 +       
15267 +       return 1;
15268 +}
15269 +
15270 +static struct ipt_target ipt_imq_reg = {
15271 +       { NULL, NULL},
15272 +       "IMQ",
15273 +       imq_target,
15274 +       imq_checkentry,
15275 +       NULL,
15276 +       THIS_MODULE
15277 +};
15278 +
15279 +static int __init init(void)
15280 +{
15281 +       if (ipt_register_target(&ipt_imq_reg))
15282 +               return -EINVAL;
15283 +
15284 +       return 0;
15285 +}
15286 +
15287 +static void __exit fini(void)
15288 +{
15289 +       ipt_unregister_target(&ipt_imq_reg);
15290 +}
15291 +
15292 +module_init(init);
15293 +module_exit(fini);
15294 +MODULE_LICENSE("GPL");
15295 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_IPMARK.c linux-2.4.20/net/ipv4/netfilter/ipt_IPMARK.c
15296 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_IPMARK.c    Thu Jan  1 00:00:00 1970
15297 +++ linux-2.4.20/net/ipv4/netfilter/ipt_IPMARK.c        Wed Sep 24 09:17:23 2003
15298 @@ -0,0 +1,88 @@
15299 +/* This is a module which is used for setting the NFMARK field of an skb. */
15300 +#include <linux/module.h>
15301 +#include <linux/skbuff.h>
15302 +#include <linux/ip.h>
15303 +#include <net/checksum.h>
15304 +
15305 +#include <linux/netfilter_ipv4/ip_tables.h>
15306 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
15307 +
15308 +MODULE_AUTHOR("Grzegorz Janoszka <Grzegorz.Janoszka@pro.onet.pl>");
15309 +MODULE_DESCRIPTION("IP tables IPMARK: mark based on ip address");
15310 +MODULE_LICENSE("GPL");
15311 +
15312 +static unsigned int
15313 +target(struct sk_buff **pskb,
15314 +       unsigned int hooknum,
15315 +       const struct net_device *in,
15316 +       const struct net_device *out,
15317 +       const void *targinfo,
15318 +       void *userinfo)
15319 +{
15320 +       const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
15321 +
15322 +       struct iphdr *iph = (*pskb)->nh.iph;
15323 +
15324 +       unsigned long mark;
15325 +       char *a, t;
15326 +
15327 +       if(ipmarkinfo->addr == IPT_IPMARK_SRC)
15328 +         mark = (unsigned long) iph->saddr;
15329 +       else
15330 +         mark = (unsigned long) iph->daddr;
15331 +
15332 +// mark has ip address in little indian, we have to change the byte order:
15333 +       a = (char *) &mark;
15334 +       t = *a; *a=*(a+3); *(a+3)=t;
15335 +       t=*(a+1); *(a+1)=*(a+2); *(a+2)=t;
15336 +
15337 +       mark &= ipmarkinfo->andmask;
15338 +       mark |= ipmarkinfo->ormask;
15339 +       
15340 +       if((*pskb)->nfmark != mark) {
15341 +               (*pskb)->nfmark = mark;
15342 +               (*pskb)->nfcache |= NFC_ALTERED;
15343 +       }
15344 +       return IPT_CONTINUE;
15345 +}
15346 +
15347 +static int
15348 +checkentry(const char *tablename,
15349 +          const struct ipt_entry *e,
15350 +           void *targinfo,
15351 +           unsigned int targinfosize,
15352 +           unsigned int hook_mask)
15353 +{
15354 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
15355 +               printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
15356 +                      targinfosize,
15357 +                      IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
15358 +               return 0;
15359 +       }
15360 +
15361 +       if (strcmp(tablename, "mangle") != 0) {
15362 +               printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15363 +               return 0;
15364 +       }
15365 +
15366 +       return 1;
15367 +}
15368 +
15369 +static struct ipt_target ipt_ipmark_reg
15370 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
15371 +
15372 +static int __init init(void)
15373 +{
15374 +       if (ipt_register_target(&ipt_ipmark_reg))
15375 +               return -EINVAL;
15376 +
15377 +       return 0;
15378 +}
15379 +
15380 +static void __exit fini(void)
15381 +{
15382 +       ipt_unregister_target(&ipt_ipmark_reg);
15383 +}
15384 +
15385 +module_init(init);
15386 +module_exit(fini);
15387 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c linux-2.4.20/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c
15388 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c     Thu Jan  1 00:00:00 1970
15389 +++ linux-2.4.20/net/ipv4/netfilter/ipt_IPV4OPTSSTRIP.c Wed Sep 24 09:16:30 2003
15390 @@ -0,0 +1,84 @@
15391 +/**
15392 + * Strip all IP options in the IP packet header.
15393 + *
15394 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
15395 + * This software is distributed under GNU GPL v2, 1991
15396 + */
15397 +
15398 +#include <linux/module.h>
15399 +#include <linux/skbuff.h>
15400 +#include <linux/ip.h>
15401 +#include <net/checksum.h>
15402 +
15403 +#include <linux/netfilter_ipv4/ip_tables.h>
15404 +
15405 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15406 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
15407 +MODULE_LICENSE("GPL");
15408 +
15409 +static unsigned int
15410 +target(struct sk_buff **pskb,
15411 +       unsigned int hooknum,
15412 +       const struct net_device *in,
15413 +       const struct net_device *out,
15414 +       const void *targinfo,
15415 +       void *userinfo)
15416 +{
15417 +       struct iphdr *iph = (*pskb)->nh.iph;
15418 +       struct sk_buff *skb = (*pskb);
15419 +       struct ip_options * opt;
15420 +       unsigned char * optiph = skb->nh.raw;
15421 +       int l = ((struct ip_options *)(&(IPCB(skb)->opt)))->optlen;
15422 +       
15423 +
15424 +       /* if no options in packet then nothing to clear. */
15425 +       if (iph->ihl * 4 == sizeof(struct iphdr))
15426 +               return IPT_CONTINUE;
15427 +
15428 +       /* else clear all options */
15429 +       memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
15430 +       memset(optiph+sizeof(struct iphdr), IPOPT_NOOP, l);
15431 +       opt = &(IPCB(skb)->opt);
15432 +       opt->is_data = 0;
15433 +       opt->optlen = l;
15434 +
15435 +       skb->nfcache |= NFC_ALTERED;
15436 +
15437 +        return IPT_CONTINUE;
15438 +}
15439 +
15440 +static int
15441 +checkentry(const char *tablename,
15442 +          const struct ipt_entry *e,
15443 +           void *targinfo,
15444 +           unsigned int targinfosize,
15445 +           unsigned int hook_mask)
15446 +{
15447 +       if (strcmp(tablename, "mangle")) {
15448 +               printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15449 +               return 0;
15450 +       }
15451 +       /* nothing else to check because no parameters */
15452 +       return 1;
15453 +}
15454 +
15455 +static struct ipt_target ipt_ipv4optsstrip_reg
15456 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
15457 +
15458 +static int __init init(void)
15459 +{
15460 +       if (ipt_register_target(&ipt_ipv4optsstrip_reg))
15461 +               return -EINVAL;
15462 +       printk("ipt_IPV4OPTSSTRIP loaded\n");
15463 +
15464 +       return 0;
15465 +}
15466 +
15467 +static void __exit fini(void)
15468 +{
15469 +       ipt_unregister_target(&ipt_ipv4optsstrip_reg);
15470 +       printk("ipt_IPV4OPTSSTRIP unloaded\n");
15471 +}
15472 +
15473 +module_init(init);
15474 +module_exit(fini);
15475 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_LOG.c linux-2.4.20/net/ipv4/netfilter/ipt_LOG.c
15476 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_LOG.c       Mon Feb 25 19:38:14 2002
15477 +++ linux-2.4.20/net/ipv4/netfilter/ipt_LOG.c   Wed Sep 24 09:16:23 2003
15478 @@ -3,16 +3,20 @@
15479   */
15480  #include <linux/module.h>
15481  #include <linux/skbuff.h>
15482 -#include <linux/ip.h>
15483  #include <linux/spinlock.h>
15484 +#include <linux/ip.h>
15485  #include <net/icmp.h>
15486  #include <net/udp.h>
15487  #include <net/tcp.h>
15488 -#include <linux/netfilter_ipv4/ip_tables.h>
15489 -
15490 -struct in_device;
15491  #include <net/route.h>
15492 +
15493 +#include <linux/netfilter_ipv4/ip_tables.h>
15494  #include <linux/netfilter_ipv4/ipt_LOG.h>
15495 +#include <linux/netfilter_ipv4/ip_logging.h>
15496 +
15497 +static unsigned int nflog = 1;
15498 +MODULE_PARM(nflog, "i");
15499 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
15500  
15501  #if 0
15502  #define DEBUGP printk
15503 @@ -20,10 +24,20 @@
15504  #define DEBUGP(format, args...)
15505  #endif
15506  
15507 +/* FIXME: move to ip.h like in 2.5 */
15508 +struct ahhdr {
15509 +       __u8    nexthdr;
15510 +       __u8    hdrlen;
15511 +       __u16   reserved;
15512 +       __u32   spi;
15513 +       __u32   seq_no;
15514 +};
15515 +
15516  struct esphdr {
15517         __u32   spi;
15518 -}; /* FIXME evil kludge */
15519 -        
15520 +       __u32   seq_no;
15521 +};
15522 +
15523  /* Use lock to serialize, so printks don't overlap */
15524  static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
15525  
15526 @@ -58,7 +72,8 @@
15527                 printk("FRAG:%u ", ntohs(iph->frag_off) & IP_OFFSET);
15528  
15529         if ((info->logflags & IPT_LOG_IPOPT)
15530 -           && iph->ihl * 4 != sizeof(struct iphdr)) {
15531 +           && iph->ihl * 4 != sizeof(struct iphdr)
15532 +           && iph->ihl * 4 >= datalen) {
15533                 unsigned int i;
15534  
15535                 /* Max length: 127 "OPT (" 15*4*2chars ") " */
15536 @@ -230,13 +245,30 @@
15537                 break;
15538         }
15539         /* Max Length */
15540 -       case IPPROTO_AH:
15541 +       case IPPROTO_AH: {
15542 +               struct ahhdr *ah = protoh;
15543 +
15544 +               /* Max length: 9 "PROTO=AH " */
15545 +               printk("PROTO=AH ");
15546 +
15547 +               if (ntohs(iph->frag_off) & IP_OFFSET)
15548 +                       break;
15549 +
15550 +               /* Max length: 25 "INCOMPLETE [65535 bytes] " */
15551 +               if (datalen < sizeof (*ah)) {
15552 +                       printk("INCOMPLETE [%u bytes] ", datalen);
15553 +                       break;
15554 +               }
15555 +
15556 +               /* Length: 15 "SPI=0xF1234567 " */
15557 +               printk("SPI=0x%x ", ntohl(ah->spi) );
15558 +               break;
15559 +       }
15560         case IPPROTO_ESP: {
15561                 struct esphdr *esph = protoh;
15562 -               int esp= (iph->protocol==IPPROTO_ESP);
15563  
15564                 /* Max length: 10 "PROTO=ESP " */
15565 -               printk("PROTO=%s ",esp? "ESP" : "AH");
15566 +               printk("PROTO=ESP ");
15567  
15568                 if (ntohs(iph->frag_off) & IP_OFFSET)
15569                         break;
15570 @@ -270,23 +302,21 @@
15571         /* maxlen = 230+   91  + 230 + 252 = 803 */
15572  }
15573  
15574 -static unsigned int
15575 -ipt_log_target(struct sk_buff **pskb,
15576 +static void
15577 +ipt_log_packet(struct sk_buff **pskb,
15578                unsigned int hooknum,
15579                const struct net_device *in,
15580                const struct net_device *out,
15581 -              const void *targinfo,
15582 -              void *userinfo)
15583 +              const struct ipt_log_info *loginfo,
15584 +              const char *level_string,
15585 +              const char *prefix)
15586  {
15587         struct iphdr *iph = (*pskb)->nh.iph;
15588 -       const struct ipt_log_info *loginfo = targinfo;
15589 -       char level_string[4] = "< >";
15590  
15591 -       level_string[1] = '0' + (loginfo->level % 8);
15592         spin_lock_bh(&log_lock);
15593         printk(level_string);
15594         printk("%sIN=%s OUT=%s ",
15595 -              loginfo->prefix,
15596 +              prefix == NULL ? loginfo->prefix : prefix,
15597                in ? in->name : "",
15598                out ? out->name : "");
15599         if (in && !out) {
15600 @@ -306,10 +336,59 @@
15601         dump_packet(loginfo, iph, (*pskb)->len, 1);
15602         printk("\n");
15603         spin_unlock_bh(&log_lock);
15604 +}
15605 +
15606 +static unsigned int
15607 +ipt_log_target(struct sk_buff **pskb,
15608 +              unsigned int hooknum,
15609 +              const struct net_device *in,
15610 +              const struct net_device *out,
15611 +              const void *targinfo,
15612 +              void *userinfo)
15613 +{
15614 +       const struct ipt_log_info *loginfo = targinfo;
15615 +       char level_string[4] = "< >";
15616 +
15617 +       level_string[1] = '0' + (loginfo->level % 8);
15618 +       ipt_log_packet(pskb, hooknum, in, out, loginfo, level_string, NULL);
15619  
15620         return IPT_CONTINUE;
15621  }
15622  
15623 +static void
15624 +ip_log_packet_fn(struct sk_buff **pskb,
15625 +                unsigned int hooknum,
15626 +                const struct net_device *in,
15627 +                const struct net_device *out,
15628 +                const char *prefix)
15629 +{
15630 +       struct ipt_log_info loginfo = { 
15631 +               .level = 0, 
15632 +               .logflags = IPT_LOG_MASK, 
15633 +               .prefix = "" 
15634 +       };
15635 +
15636 +       ipt_log_packet(pskb, hooknum, in, out, &loginfo, KERN_WARNING, prefix);
15637 +}
15638 +
15639 +static void
15640 +ip_log_fn(char *pfh, size_t len,
15641 +         const char *prefix)
15642 +{
15643 +       struct iphdr *iph = (struct iphdr *)pfh;
15644 +       struct ipt_log_info loginfo = { 
15645 +               .level = 0, 
15646 +               .logflags = IPT_LOG_MASK, 
15647 +               .prefix = "",
15648 +       };
15649 +
15650 +       spin_lock_bh(&log_lock);
15651 +       printk(KERN_WARNING "%s", prefix);
15652 +       dump_packet(&loginfo, iph, len, 1);
15653 +       printk("\n");
15654 +       spin_unlock_bh(&log_lock);
15655 +}
15656 +
15657  static int ipt_log_checkentry(const char *tablename,
15658                               const struct ipt_entry *e,
15659                               void *targinfo,
15660 @@ -341,17 +420,23 @@
15661  static struct ipt_target ipt_log_reg
15662  = { { NULL, NULL }, "LOG", ipt_log_target, ipt_log_checkentry, NULL, 
15663      THIS_MODULE };
15664 +static struct nf_logging_t ip_logging_fn
15665 += { ip_log_packet_fn, ip_log_fn };
15666  
15667  static int __init init(void)
15668  {
15669         if (ipt_register_target(&ipt_log_reg))
15670                 return -EINVAL;
15671 -
15672 +       if (nflog)
15673 +               nf_ip_log_register(&ip_logging_fn);
15674 +       
15675         return 0;
15676  }
15677  
15678  static void __exit fini(void)
15679  {
15680 +       if (nflog)
15681 +               nf_ip_log_unregister(&ip_logging_fn);
15682         ipt_unregister_target(&ipt_log_reg);
15683  }
15684  
15685 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_MASQUERADE.c linux-2.4.20/net/ipv4/netfilter/ipt_MASQUERADE.c
15686 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_MASQUERADE.c        Sun Sep 30 19:26:08 2001
15687 +++ linux-2.4.20/net/ipv4/netfilter/ipt_MASQUERADE.c    Wed Sep 24 09:16:25 2003
15688 @@ -87,13 +87,21 @@
15689         key.dst = (*pskb)->nh.iph->daddr;
15690         key.src = 0; /* Unknown: that's what we're trying to establish */
15691         key.tos = RT_TOS((*pskb)->nh.iph->tos)|RTO_CONN;
15692 -       key.oif = out->ifindex;
15693 +       key.oif = 0;
15694  #ifdef CONFIG_IP_ROUTE_FWMARK
15695         key.fwmark = (*pskb)->nfmark;
15696  #endif
15697         if (ip_route_output_key(&rt, &key) != 0) {
15698 -               /* Shouldn't happen */
15699 -               printk("MASQUERADE: No route: Rusty's brain broke!\n");
15700 +                /* Funky routing can do this. */
15701 +                if (net_ratelimit())
15702 +                        printk("MASQUERADE:"
15703 +                               " No route: Rusty's brain broke!\n");
15704 +                return NF_DROP;
15705 +        }
15706 +        if (rt->u.dst.dev != out) {
15707 +                if (net_ratelimit())
15708 +                        printk("MASQUERADE:"
15709 +                               " Route sent us somewhere else.\n");
15710                 return NF_DROP;
15711         }
15712  
15713 @@ -116,63 +124,37 @@
15714  }
15715  
15716  static inline int
15717 -device_cmp(const struct ip_conntrack *i, void *ifindex)
15718 +device_cmp(const struct ip_conntrack *i, void *_ina)
15719  {
15720 -       int ret;
15721 +       int ret = 0;
15722 +       struct in_ifaddr *ina = _ina;
15723  
15724         READ_LOCK(&masq_lock);
15725 -       ret = (i->nat.masq_index == (int)(long)ifindex);
15726 +       /* If it's masquerading out this interface with a different address,
15727 +        * or we don't know the new address of this interface. */
15728 +       if (i->nat.masq_index == ina->ifa_dev->dev->ifindex
15729 +           && i->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != ina->ifa_address)
15730 +               ret = 1;
15731         READ_UNLOCK(&masq_lock);
15732  
15733         return ret;
15734  }
15735  
15736 -static int masq_device_event(struct notifier_block *this,
15737 -                            unsigned long event,
15738 -                            void *ptr)
15739 -{
15740 -       struct net_device *dev = ptr;
15741 -
15742 -       if (event == NETDEV_DOWN) {
15743 -               /* Device was downed.  Search entire table for
15744 -                  conntracks which were associated with that device,
15745 -                  and forget them. */
15746 -               IP_NF_ASSERT(dev->ifindex != 0);
15747 -
15748 -               ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
15749 -       }
15750 -
15751 -       return NOTIFY_DONE;
15752 -}
15753 -
15754  static int masq_inet_event(struct notifier_block *this,
15755                            unsigned long event,
15756                            void *ptr)
15757  {
15758 -       struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
15759 -
15760 -       if (event == NETDEV_DOWN) {
15761 -               /* IP address was deleted.  Search entire table for
15762 -                  conntracks which were associated with that device,
15763 -                  and forget them. */
15764 -               IP_NF_ASSERT(dev->ifindex != 0);
15765 -
15766 -               ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
15767 -       }
15768 +       /* For some configurations, interfaces often come back with
15769 +        * the same address.  If not, clean up old conntrack
15770 +        * entries. */
15771 +       if (event == NETDEV_UP)
15772 +               ip_ct_selective_cleanup(device_cmp, ptr);
15773  
15774         return NOTIFY_DONE;
15775  }
15776  
15777 -static struct notifier_block masq_dev_notifier = {
15778 -       masq_device_event,
15779 -       NULL,
15780 -       0
15781 -};
15782 -
15783  static struct notifier_block masq_inet_notifier = {
15784 -       masq_inet_event,
15785 -       NULL,
15786 -       0
15787 +       .notifier_call = masq_inet_event
15788  };
15789  
15790  static struct ipt_target masquerade
15791 @@ -185,12 +167,9 @@
15792  
15793         ret = ipt_register_target(&masquerade);
15794  
15795 -       if (ret == 0) {
15796 -               /* Register for device down reports */
15797 -               register_netdevice_notifier(&masq_dev_notifier);
15798 +       if (ret == 0)
15799                 /* Register IP address change reports */
15800                 register_inetaddr_notifier(&masq_inet_notifier);
15801 -       }
15802  
15803         return ret;
15804  }
15805 @@ -198,7 +177,6 @@
15806  static void __exit fini(void)
15807  {
15808         ipt_unregister_target(&masquerade);
15809 -       unregister_netdevice_notifier(&masq_dev_notifier);
15810         unregister_inetaddr_notifier(&masq_inet_notifier);      
15811  }
15812  
15813 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_MIRROR.c linux-2.4.20/net/ipv4/netfilter/ipt_MIRROR.c
15814 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_MIRROR.c    Fri Dec 21 17:42:05 2001
15815 +++ linux-2.4.20/net/ipv4/netfilter/ipt_MIRROR.c        Wed Sep 24 09:16:17 2003
15816 @@ -32,7 +32,6 @@
15817  #include <linux/netfilter_ipv4/ip_tables.h>
15818  #include <linux/netdevice.h>
15819  #include <linux/route.h>
15820 -struct in_device;
15821  #include <net/route.h>
15822  
15823  #if 0
15824 @@ -41,31 +40,47 @@
15825  #define DEBUGP(format, args...)
15826  #endif
15827  
15828 -static int route_mirror(struct sk_buff *skb)
15829 +static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
15830  {
15831          struct iphdr *iph = skb->nh.iph;
15832 +       struct dst_entry *odst;
15833 +       struct rt_key key = {};
15834         struct rtable *rt;
15835  
15836 -       /* Backwards */
15837 -       if (ip_route_output(&rt, iph->saddr, iph->daddr,
15838 -                           RT_TOS(iph->tos) | RTO_CONN,
15839 -                           0)) {
15840 -               return 0;
15841 +       if (local) {
15842 +               key.dst = iph->saddr;
15843 +               key.src = iph->daddr;
15844 +               key.tos = RT_TOS(iph->tos);
15845 +
15846 +               if (ip_route_output_key(&rt, &key) != 0)
15847 +                       return NULL;
15848 +       } else {
15849 +               /* non-local src, find valid iif to satisfy
15850 +                * rp-filter when calling ip_route_input. */
15851 +               key.dst = iph->daddr;
15852 +               if (ip_route_output_key(&rt, &key) != 0)
15853 +                       return NULL;
15854 +
15855 +               odst = skb->dst;
15856 +               if (ip_route_input(skb, iph->saddr, iph->daddr,
15857 +                                  RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
15858 +                       dst_release(&rt->u.dst);
15859 +                       return NULL;
15860 +               }
15861 +               dst_release(&rt->u.dst);
15862 +               rt = (struct rtable *)skb->dst;
15863 +               skb->dst = odst;
15864         }
15865  
15866 -       /* check if the interface we are leaving by is the same as the
15867 -           one we arrived on */
15868 -       if (skb->dev == rt->u.dst.dev) {
15869 -               /* Drop old route. */
15870 -               dst_release(skb->dst);
15871 -               skb->dst = &rt->u.dst;
15872 -               return 1;
15873 +       if (rt->u.dst.error) {
15874 +               dst_release(&rt->u.dst);
15875 +               rt = NULL;
15876         }
15877 -       return 0;
15878 +
15879 +       return rt;
15880  }
15881  
15882 -static void
15883 -ip_rewrite(struct sk_buff *skb)
15884 +static inline void ip_rewrite(struct sk_buff *skb)
15885  {
15886         struct iphdr *iph = skb->nh.iph;
15887         u32 odaddr = iph->saddr;
15888 @@ -105,32 +120,48 @@
15889                                       const void *targinfo,
15890                                       void *userinfo)
15891  {
15892 -       if (((*pskb)->dst != NULL) &&
15893 -           route_mirror(*pskb)) {
15894 -
15895 -               ip_rewrite(*pskb);
15896 +       struct rtable *rt;
15897 +       struct sk_buff *nskb;
15898 +       unsigned int hh_len;
15899  
15900 -               /* If we are not at FORWARD hook (INPUT/PREROUTING),
15901 -                * the TTL isn't decreased by the IP stack */
15902 -               if (hooknum != NF_IP_FORWARD) {
15903 -                       struct iphdr *iph = (*pskb)->nh.iph;
15904 -                       if (iph->ttl <= 1) {
15905 -                               /* this will traverse normal stack, and 
15906 -                                * thus call conntrack on the icmp packet */
15907 -                               icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
15908 -                                         ICMP_EXC_TTL, 0);
15909 -                               return NF_DROP;
15910 -                       }
15911 -                       ip_decrease_ttl(iph);
15912 +       /* If we are not at FORWARD hook (INPUT/PREROUTING),
15913 +        * the TTL isn't decreased by the IP stack */
15914 +       if (hooknum != NF_IP_FORWARD) {
15915 +               struct iphdr *iph = (*pskb)->nh.iph;
15916 +               if (iph->ttl <= 1) {
15917 +                       /* this will traverse normal stack, and 
15918 +                        * thus call conntrack on the icmp packet */
15919 +                       icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
15920 +                                 ICMP_EXC_TTL, 0);
15921 +                       return NF_DROP;
15922                 }
15923 +               ip_decrease_ttl(iph);
15924 +       }
15925  
15926 -               /* Don't let conntrack code see this packet:
15927 -                   it will think we are starting a new
15928 -                   connection! --RR */
15929 -               ip_direct_send(*pskb);
15930 +       if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
15931 +               return NF_DROP;
15932  
15933 -               return NF_STOLEN;
15934 +       hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
15935 +
15936 +       /* Copy skb (even if skb is about to be dropped, we can't just
15937 +        * clone it because there may be other things, such as tcpdump,
15938 +        * interested in it). We also need to expand headroom in case
15939 +        * hh_len of incoming interface < hh_len of outgoing interface */
15940 +       nskb = skb_copy_expand(*pskb, hh_len, skb_tailroom(*pskb), GFP_ATOMIC);
15941 +       if (nskb == NULL) {
15942 +               dst_release(&rt->u.dst);
15943 +               return NF_DROP;
15944         }
15945 +
15946 +       dst_release(nskb->dst);
15947 +       nskb->dst = &rt->u.dst;
15948 +
15949 +       ip_rewrite(nskb);
15950 +       /* Don't let conntrack code see this packet:
15951 +           it will think we are starting a new
15952 +           connection! --RR */
15953 +       ip_direct_send(nskb);
15954 +
15955         return NF_DROP;
15956  }
15957  
15958 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_NETLINK.c linux-2.4.20/net/ipv4/netfilter/ipt_NETLINK.c
15959 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_NETLINK.c   Thu Jan  1 00:00:00 1970
15960 +++ linux-2.4.20/net/ipv4/netfilter/ipt_NETLINK.c       Wed Sep 24 09:16:32 2003
15961 @@ -0,0 +1,119 @@
15962 +#include <linux/module.h>
15963 +#include <linux/version.h>
15964 +#include <linux/config.h>
15965 +#include <linux/socket.h>
15966 +#include <linux/skbuff.h>
15967 +#include <linux/kernel.h>
15968 +#include <linux/netlink.h>
15969 +#include <linux/netdevice.h>
15970 +#include <linux/mm.h>
15971 +#include <linux/socket.h>
15972 +#include <linux/netfilter_ipv4/ip_tables.h>
15973 +#include <linux/netfilter_ipv4/ipt_NETLINK.h>
15974 +#include <net/sock.h>
15975 +
15976 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
15977 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
15978 +MODULE_LICENSE("GPL");
15979 +
15980 +#if 0
15981 +#define DEBUGP printk
15982 +#else
15983 +#define DEBUGP(format, args...)
15984 +#endif
15985 +
15986 +static struct sock *ipfwsk;
15987 +
15988 +static unsigned int ipt_netlink_target(struct sk_buff **pskb,
15989 +                                   unsigned int hooknum,
15990 +                                   const struct net_device *in,
15991 +                                   const struct net_device *out,
15992 +                                   const void *targinfo, void *userinfo)
15993 +{
15994 +       struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
15995 +       struct iphdr *ip = (*pskb)->nh.iph;
15996 +       struct sk_buff *outskb;
15997 +       struct netlink_t nlhdr;
15998 +       size_t len=0;
15999 +
16000 +       /* Allocate a socket buffer */
16001 +       if ( MASK(nld->flags, USE_SIZE) )
16002 +               len = nld->size+sizeof(nlhdr);
16003 +       else
16004 +               len = ntohs(ip->tot_len)+sizeof(nlhdr); 
16005 +
16006 +       outskb=alloc_skb(len, GFP_ATOMIC);
16007 +
16008 +       if (outskb) {
16009 +               nlhdr.len=len;
16010 +               
16011 +               if ( MASK(nld->flags, USE_MARK) )
16012 +                       nlhdr.mark=(*pskb)->nfmark=nld->mark;
16013 +               else
16014 +                       nlhdr.mark=(*pskb)->nfmark;
16015 +               
16016 +               if ( in && in->name ) {
16017 +                       strncpy((char *)&nlhdr.iface, in->name, IFNAMSIZ);
16018 +               }else if ( out && out->name ){
16019 +                       strncpy((char *)&nlhdr.iface, out->name, IFNAMSIZ);
16020 +               }
16021 +
16022 +               skb_put(outskb, len);
16023 +               memcpy(outskb->data, &nlhdr, sizeof(nlhdr));
16024 +               memcpy((outskb->data)+sizeof(nlhdr), ip, len-sizeof(nlhdr));
16025 +               netlink_broadcast(ipfwsk, outskb, 0, ~0, GFP_ATOMIC);
16026 +       }else{
16027 +               if (net_ratelimit())
16028 +                       printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
16029 +       }
16030 +
16031 +       if ( MASK(nld->flags, USE_DROP) )
16032 +               return NF_DROP;
16033 +
16034 +       return IPT_CONTINUE;
16035 +}
16036 +
16037 +static int ipt_netlink_checkentry(const char *tablename,
16038 +                              const struct ipt_entry *e,
16039 +                              void *targinfo,
16040 +                              unsigned int targinfosize,
16041 +                              unsigned int hookmask)
16042 +{
16043 +       //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
16044 +
16045 +       return 1;
16046 +}
16047 +
16048 +static struct ipt_target ipt_netlink_reg = { 
16049 +       {NULL, NULL},
16050 +       "NETLINK",
16051 +       ipt_netlink_target,
16052 +       ipt_netlink_checkentry,
16053 +       NULL,
16054 +       THIS_MODULE
16055 +};
16056 +
16057 +static int __init init(void)
16058 +{
16059 +       DEBUGP("ipt_NETLINK: init module\n");   
16060 +
16061 +       if (ipt_register_target(&ipt_netlink_reg) != 0) {
16062 +               return -EINVAL;
16063 +       }
16064 +
16065 +       if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
16066 +               return -EINVAL;
16067 +       }
16068 +
16069 +       return 0;
16070 +}
16071 +
16072 +static void __exit fini(void)
16073 +{
16074 +       DEBUGP("ipt_NETLINK: cleanup_module\n");
16075 +       ipt_unregister_target(&ipt_netlink_reg);
16076 +       if(ipfwsk->socket) sock_release(ipfwsk->socket);
16077 +}
16078 +
16079 +module_init(init);
16080 +module_exit(fini);
16081 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_NETMAP.c linux-2.4.20/net/ipv4/netfilter/ipt_NETMAP.c
16082 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_NETMAP.c    Thu Jan  1 00:00:00 1970
16083 +++ linux-2.4.20/net/ipv4/netfilter/ipt_NETMAP.c        Wed Sep 24 09:16:34 2003
16084 @@ -0,0 +1,109 @@
16085 +/* NETMAP - static NAT mapping of IP network addresses (1:1).
16086 +   The mapping can be applied to source (POSTROUTING),
16087 +   destination (PREROUTING), or both (with separate rules).
16088 +
16089 +   Author: Svenning Soerensen <svenning@post5.tele.dk>
16090 +*/
16091 +
16092 +#include <linux/config.h>
16093 +#include <linux/ip.h>
16094 +#include <linux/module.h>
16095 +#include <linux/netdevice.h>
16096 +#include <linux/netfilter.h>
16097 +#include <linux/netfilter_ipv4.h>
16098 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
16099 +
16100 +#define MODULENAME "NETMAP"
16101 +MODULE_LICENSE("GPL");
16102 +MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
16103 +MODULE_DESCRIPTION("iptables 1:1 NAT mapping of IP networks target");
16104 +
16105 +#if 0
16106 +#define DEBUGP printk
16107 +#else
16108 +#define DEBUGP(format, args...)
16109 +#endif
16110 +
16111 +static int
16112 +check(const char *tablename,
16113 +      const struct ipt_entry *e,
16114 +      void *targinfo,
16115 +      unsigned int targinfosize,
16116 +      unsigned int hook_mask)
16117 +{
16118 +       const struct ip_nat_multi_range *mr = targinfo;
16119 +
16120 +       if (strcmp(tablename, "nat") != 0) {
16121 +               DEBUGP(MODULENAME":check: bad table `%s'.\n", tablename);
16122 +               return 0;
16123 +       }
16124 +       if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
16125 +               DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
16126 +               return 0;
16127 +       }
16128 +       if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING))) {
16129 +               DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
16130 +               return 0;
16131 +       }
16132 +       if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
16133 +               DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
16134 +               return 0;
16135 +       }
16136 +       if (mr->rangesize != 1) {
16137 +               DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
16138 +               return 0;
16139 +       }
16140 +       return 1;
16141 +}
16142 +
16143 +static unsigned int
16144 +target(struct sk_buff **pskb,
16145 +       unsigned int hooknum,
16146 +       const struct net_device *in,
16147 +       const struct net_device *out,
16148 +       const void *targinfo,
16149 +       void *userinfo)
16150 +{
16151 +       struct ip_conntrack *ct;
16152 +       enum ip_conntrack_info ctinfo;
16153 +       u_int32_t new_ip, netmask;
16154 +       const struct ip_nat_multi_range *mr = targinfo;
16155 +       struct ip_nat_multi_range newrange;
16156 +
16157 +       IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
16158 +                    || hooknum == NF_IP_POST_ROUTING);
16159 +       ct = ip_conntrack_get(*pskb, &ctinfo);
16160 +
16161 +       netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
16162 +
16163 +       if (hooknum == NF_IP_PRE_ROUTING)
16164 +               new_ip = (*pskb)->nh.iph->daddr & ~netmask;
16165 +       else
16166 +               new_ip = (*pskb)->nh.iph->saddr & ~netmask;
16167 +       new_ip |= mr->range[0].min_ip & netmask;
16168 +
16169 +       newrange = ((struct ip_nat_multi_range)
16170 +       { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
16171 +                new_ip, new_ip,
16172 +                mr->range[0].min, mr->range[0].max } } });
16173 +
16174 +       /* Hand modified range to generic setup. */
16175 +       return ip_nat_setup_info(ct, &newrange, hooknum);
16176 +}
16177 +
16178 +static struct ipt_target target_module
16179 += { { NULL, NULL }, MODULENAME, target, check, NULL,
16180 +    THIS_MODULE };
16181 +
16182 +static int __init init(void)
16183 +{
16184 +       return ipt_register_target(&target_module);
16185 +}
16186 +
16187 +static void __exit fini(void)
16188 +{
16189 +       ipt_unregister_target(&target_module);
16190 +}
16191 +
16192 +module_init(init);
16193 +module_exit(fini);
16194 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_NOTRACK.c linux-2.4.20/net/ipv4/netfilter/ipt_NOTRACK.c
16195 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_NOTRACK.c   Thu Jan  1 00:00:00 1970
16196 +++ linux-2.4.20/net/ipv4/netfilter/ipt_NOTRACK.c       Wed Sep 24 09:18:12 2003
16197 @@ -0,0 +1,83 @@
16198 +/* This is a module which is used for setting up fake conntracks
16199 + * on packets so that they are not seen by the conntrack/NAT code.
16200 + */
16201 +#include <linux/module.h>
16202 +#include <linux/skbuff.h>
16203 +
16204 +#include <linux/netfilter_ipv4/ip_tables.h>
16205 +#include <linux/netfilter_ipv4/ip_conntrack.h>
16206 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
16207 +#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
16208 +
16209 +static unsigned int
16210 +target(struct sk_buff **pskb,
16211 +       unsigned int hooknum,
16212 +       const struct net_device *in,
16213 +       const struct net_device *out,
16214 +       const void *targinfo,
16215 +       void *userinfo)
16216 +{
16217 +       struct ip_conntrack_protocol *proto;
16218 +       struct ip_conntrack_tuple tuple;
16219 +
16220 +       if ((*pskb)->nfct != NULL)
16221 +               return IPT_CONTINUE;
16222 +
16223 +       proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
16224 +
16225 +       if (ip_conntrack_get_tuple((*pskb)->nh.iph, (*pskb)->len, 
16226 +                     &tuple, proto)
16227 +           && !ip_conntrack_tuple_taken(&tuple, NULL)) {
16228 +               (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
16229 +               nf_conntrack_get((*pskb)->nfct);
16230 +       }
16231 +
16232 +       return IPT_CONTINUE;
16233 +}
16234 +
16235 +static int
16236 +checkentry(const char *tablename,
16237 +          const struct ipt_entry *e,
16238 +           void *targinfo,
16239 +           unsigned int targinfosize,
16240 +           unsigned int hook_mask)
16241 +{
16242 +       if (targinfosize != 0) {
16243 +               printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
16244 +                      targinfosize);
16245 +               return 0;
16246 +       }
16247 +
16248 +       if (strcmp(tablename, "raw") != 0) {
16249 +               printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
16250 +               return 0;
16251 +       }
16252 +
16253 +       return 1;
16254 +}
16255 +
16256 +static struct ipt_target ipt_notrack_reg = { 
16257 +       .list = { NULL, NULL }, 
16258 +       .name = "NOTRACK", 
16259 +       .target = target, 
16260 +       .checkentry = checkentry, 
16261 +       .destroy = NULL, 
16262 +       .me = THIS_MODULE 
16263 +};
16264 +
16265 +static int __init init(void)
16266 +{
16267 +       if (ipt_register_target(&ipt_notrack_reg))
16268 +               return -EINVAL;
16269 +
16270 +       return 0;
16271 +}
16272 +
16273 +static void __exit fini(void)
16274 +{
16275 +       ipt_unregister_target(&ipt_notrack_reg);
16276 +}
16277 +
16278 +module_init(init);
16279 +module_exit(fini);
16280 +MODULE_LICENSE("GPL");
16281 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_POOL.c linux-2.4.20/net/ipv4/netfilter/ipt_POOL.c
16282 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_POOL.c      Thu Jan  1 00:00:00 1970
16283 +++ linux-2.4.20/net/ipv4/netfilter/ipt_POOL.c  Wed Sep 24 09:16:59 2003
16284 @@ -0,0 +1,116 @@
16285 +/* ipt_POOL.c - netfilter target to manipulate IP pools
16286 + *
16287 + * This target can be used almost everywhere. It acts on some specified
16288 + * IP pool, adding or deleting some IP address in the pool. The address
16289 + * can be either the source (--addsrc, --delsrc), or destination (--add/deldst)
16290 + * of the packet under inspection.
16291 + *
16292 + * The target normally returns IPT_CONTINUE.
16293 + */
16294 +
16295 +#include <linux/types.h>
16296 +#include <linux/ip.h>
16297 +#include <linux/timer.h>
16298 +#include <linux/module.h>
16299 +#include <linux/netfilter.h>
16300 +#include <linux/netdevice.h>
16301 +#include <linux/if.h>
16302 +#include <linux/inetdevice.h>
16303 +#include <net/protocol.h>
16304 +#include <net/checksum.h>
16305 +#include <linux/netfilter_ipv4.h>
16306 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
16307 +#include <linux/netfilter_ipv4/ipt_pool.h>
16308 +
16309 +#if 0
16310 +#define DEBUGP printk
16311 +#else
16312 +#define DEBUGP(format, args...)
16313 +#endif
16314 +
16315 +/*** NOTE NOTE NOTE NOTE ***
16316 +**
16317 +** By sheer luck, I get away with using the "struct ipt_pool_info", as defined
16318 +** in <linux/netfilter_ipv4/ipt_pool.h>, both as the match and target info.
16319 +** Here, in the target implementation, ipt_pool_info.src, if not IP_POOL_NONE,
16320 +** is modified for the source IP address of the packet under inspection.
16321 +** The same way, the ipt_pool_info.dst pool is modified for the destination.
16322 +**
16323 +** The address is added to the pool normally. However, if IPT_POOL_DEL_dir
16324 +** flag is set in ipt_pool_info.flags, the address is deleted from the pool.
16325 +**
16326 +** If a modification was done to the pool, we possibly return ACCEPT or DROP,
16327 +** if the right IPT_POOL_MOD_dir_ACCEPT or _MOD_dir_DROP flags are set.
16328 +** The IPT_POOL_INV_MOD_dir flag inverts the sense of the check (i.e. the
16329 +** ACCEPT and DROP flags are evaluated when the pool was not modified.)
16330 +*/
16331 +
16332 +static int
16333 +do_check(const char *tablename,
16334 +              const struct ipt_entry *e,
16335 +              void *targinfo,
16336 +              unsigned int targinfosize,
16337 +              unsigned int hook_mask)
16338 +{
16339 +       const struct ipt_pool_info *ipi = targinfo;
16340 +
16341 +       if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
16342 +               DEBUGP("POOL_check: size %u.\n", targinfosize);
16343 +               return 0;
16344 +       }
16345 +       DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
16346 +       return 1;
16347 +}
16348 +
16349 +static unsigned int
16350 +do_target(struct sk_buff **pskb,
16351 +               unsigned int hooknum,
16352 +               const struct net_device *in,
16353 +               const struct net_device *out,
16354 +               const void *targinfo,
16355 +               void *userinfo)
16356 +{
16357 +       const struct ipt_pool_info *ipi = targinfo;
16358 +       int modified;
16359 +       unsigned int verdict = IPT_CONTINUE;
16360 +
16361 +       if (ipi->src != IP_POOL_NONE) {
16362 +               modified = ip_pool_mod(ipi->src, ntohl((*pskb)->nh.iph->saddr),
16363 +                                       ipi->flags & IPT_POOL_DEL_SRC);
16364 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_SRC)) {
16365 +                       if (ipi->flags & IPT_POOL_MOD_SRC_ACCEPT)
16366 +                               verdict = NF_ACCEPT;
16367 +                       else if (ipi->flags & IPT_POOL_MOD_SRC_DROP)
16368 +                               verdict = NF_DROP;
16369 +               }
16370 +       }
16371 +       if (verdict == IPT_CONTINUE && ipi->dst != IP_POOL_NONE) {
16372 +               modified = ip_pool_mod(ipi->dst, ntohl((*pskb)->nh.iph->daddr),
16373 +                                       ipi->flags & IPT_POOL_DEL_DST);
16374 +               if (!!modified ^ !!(ipi->flags & IPT_POOL_INV_MOD_DST)) {
16375 +                       if (ipi->flags & IPT_POOL_MOD_DST_ACCEPT)
16376 +                               verdict = NF_ACCEPT;
16377 +                       else if (ipi->flags & IPT_POOL_MOD_DST_DROP)
16378 +                               verdict = NF_DROP;
16379 +               }
16380 +       }
16381 +       return verdict;
16382 +}
16383 +
16384 +static struct ipt_target pool_reg
16385 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
16386 +
16387 +static int __init init(void)
16388 +{
16389 +       DEBUGP("init ipt_POOL\n");
16390 +       return ipt_register_target(&pool_reg);
16391 +}
16392 +
16393 +static void __exit fini(void)
16394 +{
16395 +       DEBUGP("fini ipt_POOL\n");
16396 +       ipt_unregister_target(&pool_reg);
16397 +}
16398 +
16399 +module_init(init);
16400 +module_exit(fini);
16401 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_REJECT.c linux-2.4.20/net/ipv4/netfilter/ipt_REJECT.c
16402 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_REJECT.c    Thu Nov 28 23:53:15 2002
16403 +++ linux-2.4.20/net/ipv4/netfilter/ipt_REJECT.c        Wed Sep 24 09:18:09 2003
16404 @@ -1,15 +1,18 @@
16405  /*
16406   * This is a module which is used for rejecting packets.
16407   * Added support for customized reject packets (Jozsef Kadlecsik).
16408 + * Added support for ICMP type-3-code-13 (Maciej Soltysiak). [RFC 1812]
16409 + * Added support for fake source IP in icmp-unreach (Fabrice MARIE & Guillaume MORIN).
16410   */
16411  #include <linux/config.h>
16412  #include <linux/module.h>
16413  #include <linux/skbuff.h>
16414  #include <linux/ip.h>
16415 +#include <linux/udp.h>
16416 +#include <linux/icmp.h>
16417  #include <net/icmp.h>
16418  #include <net/ip.h>
16419  #include <net/tcp.h>
16420 -struct in_device;
16421  #include <net/route.h>
16422  #include <linux/netfilter_ipv4/ip_tables.h>
16423  #include <linux/netfilter_ipv4/ipt_REJECT.h>
16424 @@ -32,8 +35,49 @@
16425                 attach(new_skb, nfct);
16426  }
16427  
16428 +static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
16429 +{
16430 +       struct iphdr *iph = skb->nh.iph;
16431 +       struct dst_entry *odst;
16432 +       struct rt_key key = {};
16433 +       struct rtable *rt;
16434 +
16435 +       if (hook != NF_IP_FORWARD) {
16436 +               key.dst = iph->saddr;
16437 +               if (hook == NF_IP_LOCAL_IN)
16438 +                       key.src = iph->daddr;
16439 +               key.tos = RT_TOS(iph->tos);
16440 +
16441 +               if (ip_route_output_key(&rt, &key) != 0)
16442 +                       return NULL;
16443 +       } else {
16444 +               /* non-local src, find valid iif to satisfy
16445 +                * rp-filter when calling ip_route_input. */
16446 +               key.dst = iph->daddr;
16447 +               if (ip_route_output_key(&rt, &key) != 0)
16448 +                       return NULL;
16449 +
16450 +               odst = skb->dst;
16451 +               if (ip_route_input(skb, iph->saddr, iph->daddr,
16452 +                                  RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
16453 +                       dst_release(&rt->u.dst);
16454 +                       return NULL;
16455 +               }
16456 +               dst_release(&rt->u.dst);
16457 +               rt = (struct rtable *)skb->dst;
16458 +               skb->dst = odst;
16459 +       }
16460 +
16461 +       if (rt->u.dst.error) {
16462 +               dst_release(&rt->u.dst);
16463 +               rt = NULL;
16464 +       }
16465 +
16466 +       return rt;
16467 +}
16468 +
16469  /* Send RST reply */
16470 -static void send_reset(struct sk_buff *oldskb, int local)
16471 +static void send_reset(struct sk_buff *oldskb, int hook)
16472  {
16473         struct sk_buff *nskb;
16474         struct tcphdr *otcph, *tcph;
16475 @@ -42,6 +86,7 @@
16476         u_int16_t tmp_port;
16477         u_int32_t tmp_addr;
16478         int needs_ack;
16479 +       int hh_len;
16480  
16481         /* IP header checks: fragment, too short. */
16482         if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
16483 @@ -61,12 +106,25 @@
16484                          csum_partial((char *)otcph, otcplen, 0)) != 0)
16485                 return;
16486  
16487 +       if ((rt = route_reverse(oldskb, hook)) == NULL)
16488 +               return;
16489 +
16490 +       hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
16491 +
16492 +
16493         /* Copy skb (even if skb is about to be dropped, we can't just
16494             clone it because there may be other things, such as tcpdump,
16495 -           interested in it) */
16496 -       nskb = skb_copy(oldskb, GFP_ATOMIC);
16497 -       if (!nskb)
16498 +           interested in it). We also need to expand headroom in case
16499 +          hh_len of incoming interface < hh_len of outgoing interface */
16500 +       nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb),
16501 +                              GFP_ATOMIC);
16502 +       if (!nskb) {
16503 +               dst_release(&rt->u.dst);
16504                 return;
16505 +       }
16506 +
16507 +       dst_release(nskb->dst);
16508 +       nskb->dst = &rt->u.dst;
16509  
16510         /* This packet will not be the same as the other: clear nf fields */
16511         nf_conntrack_put(nskb->nfct);
16512 @@ -130,16 +188,6 @@
16513         nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
16514                                            nskb->nh.iph->ihl);
16515  
16516 -       /* Routing: if not headed for us, route won't like source */
16517 -       if (ip_route_output(&rt, nskb->nh.iph->daddr,
16518 -                           local ? nskb->nh.iph->saddr : 0,
16519 -                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
16520 -                           0) != 0)
16521 -               goto free_nskb;
16522 -
16523 -       dst_release(nskb->dst);
16524 -       nskb->dst = &rt->u.dst;
16525 -
16526         /* "Never happens" */
16527         if (nskb->len > nskb->dst->pmtu)
16528                 goto free_nskb;
16529 @@ -154,12 +202,13 @@
16530         kfree_skb(nskb);
16531  }
16532  
16533 -static void send_unreach(struct sk_buff *skb_in, int code)
16534 +static void send_unreach(struct sk_buff *skb_in, int code, u_int8_t fake_source_address)
16535  {
16536         struct iphdr *iph;
16537 +       struct udphdr *udph;
16538         struct icmphdr *icmph;
16539         struct sk_buff *nskb;
16540 -       u32 saddr;
16541 +       u32 saddr,packet_daddr;
16542         u8 tos;
16543         int hh_len, length;
16544         struct rtable *rt = (struct rtable*)skb_in->dst;
16545 @@ -186,6 +235,19 @@
16546         if (iph->frag_off&htons(IP_OFFSET))
16547                 return;
16548  
16549 +       /* if UDP checksum is set, verify it's correct */
16550 +       if (iph->protocol == IPPROTO_UDP
16551 +           && skb_in->tail-(u8*)iph >= sizeof(struct udphdr)) {
16552 +               int datalen = skb_in->len - (iph->ihl<<2);
16553 +               udph = (struct udphdr *)((char *)iph + (iph->ihl<<2));
16554 +               if (udph->check
16555 +                   && csum_tcpudp_magic(iph->saddr, iph->daddr,
16556 +                                        datalen, IPPROTO_UDP,
16557 +                                        csum_partial((char *)udph, datalen,
16558 +                                                     0)) != 0)
16559 +                       return;
16560 +       }
16561 +                   
16562         /* If we send an ICMP error to an ICMP error a mess would result.. */
16563         if (iph->protocol == IPPROTO_ICMP
16564             && skb_in->tail-(u8*)iph >= sizeof(struct icmphdr)) {
16565 @@ -201,7 +263,7 @@
16566                         return;
16567         }
16568  
16569 -       saddr = iph->daddr;
16570 +       packet_daddr = saddr = iph->daddr;
16571         if (!(rt->rt_flags & RTCF_LOCAL))
16572                 saddr = 0;
16573  
16574 @@ -244,7 +306,16 @@
16575         iph->ttl = MAXTTL;
16576         ip_select_ident(iph, &rt->u.dst, NULL);
16577         iph->protocol=IPPROTO_ICMP;
16578 -       iph->saddr=rt->rt_src;
16579 +
16580 +        /* fake source IP if we have to
16581 +           if fake_source_address == 1, we fake the source IP
16582 +           from the packet destination address dynamically.
16583 +        */
16584 +        if (fake_source_address == 1)
16585 +                iph->saddr = packet_daddr;
16586 +        else
16587 +               iph->saddr=rt->rt_src;
16588 +
16589         iph->daddr=rt->rt_dst;
16590         iph->check=0;
16591         iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
16592 @@ -291,25 +362,28 @@
16593            must return an absolute verdict. --RR */
16594         switch (reject->with) {
16595         case IPT_ICMP_NET_UNREACHABLE:
16596 -               send_unreach(*pskb, ICMP_NET_UNREACH);
16597 +               send_unreach(*pskb, ICMP_NET_UNREACH, reject->fake_source_address);
16598                 break;
16599         case IPT_ICMP_HOST_UNREACHABLE:
16600 -               send_unreach(*pskb, ICMP_HOST_UNREACH);
16601 +               send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
16602                 break;
16603         case IPT_ICMP_PROT_UNREACHABLE:
16604 -               send_unreach(*pskb, ICMP_PROT_UNREACH);
16605 +               send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
16606                 break;
16607         case IPT_ICMP_PORT_UNREACHABLE:
16608 -               send_unreach(*pskb, ICMP_PORT_UNREACH);
16609 +               send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
16610                 break;
16611         case IPT_ICMP_NET_PROHIBITED:
16612 -               send_unreach(*pskb, ICMP_NET_ANO);
16613 +               send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
16614                 break;
16615         case IPT_ICMP_HOST_PROHIBITED:
16616 -               send_unreach(*pskb, ICMP_HOST_ANO);
16617 +               send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
16618                 break;
16619 +       case IPT_ICMP_ADMIN_PROHIBITED:
16620 +               send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
16621 +               break;
16622         case IPT_TCP_RESET:
16623 -               send_reset(*pskb, hooknum == NF_IP_LOCAL_IN);
16624 +               send_reset(*pskb, hooknum);
16625         case IPT_ICMP_ECHOREPLY:
16626                 /* Doesn't happen. */
16627                 break;
16628 @@ -353,6 +427,11 @@
16629                         DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
16630                         return 0;
16631                 }
16632 +               /* cannot fake source address */
16633 +               if (rejinfo->fake_source_address != 0) {
16634 +                       DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
16635 +                       return 0;
16636 +               }
16637         }
16638  
16639         return 1;
16640 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_ROUTE.c linux-2.4.20/net/ipv4/netfilter/ipt_ROUTE.c
16641 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_ROUTE.c     Thu Jan  1 00:00:00 1970
16642 +++ linux-2.4.20/net/ipv4/netfilter/ipt_ROUTE.c Wed Sep 24 09:17:25 2003
16643 @@ -0,0 +1,369 @@
16644 +/*
16645 + * This implements the ROUTE target, which enables you to setup unusual
16646 + * routes not supported by the standard kernel routing table.
16647 + *
16648 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
16649 + *
16650 + * v 1.8 2003/07/25
16651 + *
16652 + * This software is distributed under GNU GPL v2, 1991
16653 + */
16654 +
16655 +#include <linux/module.h>
16656 +#include <linux/skbuff.h>
16657 +#include <linux/ip.h>
16658 +#include <linux/netfilter_ipv4/ip_tables.h>
16659 +#include <linux/netfilter_ipv4/ipt_ROUTE.h>
16660 +#include <linux/netdevice.h>
16661 +#include <linux/route.h>
16662 +#include <net/ip.h>
16663 +#include <net/route.h>
16664 +#include <net/icmp.h>
16665 +
16666 +#if 0
16667 +#define DEBUGP printk
16668 +#else
16669 +#define DEBUGP(format, args...)
16670 +#endif
16671 +
16672 +
16673 +/* Try to route the packet according to the routing keys specified in
16674 + * route_info. Keys are :
16675 + *  - ifindex : 
16676 + *      0 if no oif preferred, 
16677 + *      otherwise set to the index of the desired oif
16678 + *  - route_info->gw :
16679 + *      0 if no gateway specified,
16680 + *      otherwise set to the next host to which the pkt must be routed
16681 + * If success, skb->dev is the output device to which the packet must 
16682 + * be sent and skb->dst is not NULL
16683 + *
16684 + * RETURN: -1 if an error occured
16685 + *          1 if the packet was succesfully routed to the 
16686 + *            destination desired
16687 + *          0 if the kernel routing table could not route the packet
16688 + *            according to the keys specified
16689 + */
16690 +static int route(struct sk_buff *skb,
16691 +                unsigned int ifindex,
16692 +                const struct ipt_route_target_info *route_info)
16693 +{
16694 +       int err;
16695 +       struct rtable *rt;
16696 +       struct iphdr *iph = skb->nh.iph;
16697 +       struct rt_key key = { 
16698 +               dst:iph->daddr,
16699 +               src:0,
16700 +               oif:ifindex, 
16701 +               tos:RT_TOS(iph->tos) 
16702 +       };
16703 +       
16704 +       /* The destination address may be overloaded by the target */
16705 +       if (route_info->gw)
16706 +               key.dst = route_info->gw;
16707 +       
16708 +       /* Trying to route the packet using the standard routing table. */
16709 +       if ((err = ip_route_output_key(&rt, &key))) {
16710 +               if (net_ratelimit()) 
16711 +                       DEBUGP("ipt_ROUTE: couldn't route pkt (err: %i)",err);
16712 +               return -1;
16713 +       }
16714 +       
16715 +       /* Drop old route. */
16716 +       dst_release(skb->dst);
16717 +       skb->dst = NULL;
16718 +
16719 +       /* Success if no oif specified or if the oif correspond to the 
16720 +        * one desired */
16721 +       if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
16722 +               skb->dst = &rt->u.dst;
16723 +               skb->dev = skb->dst->dev;
16724 +               return 1;
16725 +       }
16726 +       
16727 +       /* The interface selected by the routing table is not the one
16728 +        * specified by the user. This may happen because the dst address
16729 +        * is one of our own addresses.
16730 +        */
16731 +       if (net_ratelimit()) 
16732 +               DEBUGP("ipt_ROUTE: failed to route as desired gw=%u.%u.%u.%u oif=%i (got oif=%i)\n", 
16733 +                      NIPQUAD(route_info->gw), ifindex, rt->u.dst.dev->ifindex);
16734 +       
16735 +       return 0;
16736 +}
16737 +
16738 +
16739 +/* Stolen from ip_finish_output2
16740 + * PRE : skb->dev is set to the device we are leaving by
16741 + *       skb->dst is not NULL
16742 + * POST: the packet is sent with the link layer header pushed
16743 + *       the packet is destroyed
16744 + */
16745 +static void ip_direct_send(struct sk_buff *skb)
16746 +{
16747 +       struct dst_entry *dst = skb->dst;
16748 +       struct hh_cache *hh = dst->hh;
16749 +
16750 +       if (hh) {
16751 +               read_lock_bh(&hh->hh_lock);
16752 +               memcpy(skb->data - 16, hh->hh_data, 16);
16753 +               read_unlock_bh(&hh->hh_lock);
16754 +               skb_push(skb, hh->hh_len);
16755 +               hh->hh_output(skb);
16756 +       } else if (dst->neighbour)
16757 +               dst->neighbour->output(skb);
16758 +       else {
16759 +               if (net_ratelimit())
16760 +                       DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
16761 +               kfree_skb(skb);
16762 +       }
16763 +}
16764 +
16765 +
16766 +/* PRE : skb->dev is set to the device we are leaving by
16767 + * POST: - the packet is directly sent to the skb->dev device, without 
16768 + *         pushing the link layer header.
16769 + *       - the packet is destroyed
16770 + */
16771 +static inline int dev_direct_send(struct sk_buff *skb)
16772 +{
16773 +       return dev_queue_xmit(skb);
16774 +}
16775 +
16776 +
16777 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
16778 +                             struct sk_buff *skb) 
16779 +{
16780 +       unsigned int ifindex = 0;
16781 +       struct net_device *dev_out = NULL;
16782 +
16783 +       /* The user set the interface name to use.
16784 +        * Getting the current interface index.
16785 +        */
16786 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
16787 +               ifindex = dev_out->ifindex;
16788 +       } else {
16789 +               /* Unknown interface name : packet dropped */
16790 +               if (net_ratelimit()) 
16791 +                       DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
16792 +               return NF_DROP;
16793 +       }
16794 +
16795 +       /* Trying the standard way of routing packets */
16796 +       switch (route(skb, ifindex, route_info)) {
16797 +       case 1:
16798 +               dev_put(dev_out);
16799 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
16800 +                       return IPT_CONTINUE;
16801 +
16802 +               ip_direct_send(skb);
16803 +               return NF_STOLEN;
16804 +
16805 +       case 0:
16806 +               /* Failed to send to oif. Trying the hard way */
16807 +               if (route_info->flags & IPT_ROUTE_CONTINUE)
16808 +                       return NF_DROP;
16809 +
16810 +               if (net_ratelimit()) 
16811 +                       DEBUGP("ipt_ROUTE: forcing the use of %i\n",
16812 +                              ifindex);
16813 +
16814 +               /* We have to force the use of an interface.
16815 +                * This interface must be a tunnel interface since
16816 +                * otherwise we can't guess the hw address for
16817 +                * the packet. For a tunnel interface, no hw address
16818 +                * is needed.
16819 +                */
16820 +               if ((dev_out->type != ARPHRD_TUNNEL)
16821 +                   && (dev_out->type != ARPHRD_IPGRE)) {
16822 +                       if (net_ratelimit()) 
16823 +                               DEBUGP("ipt_ROUTE: can't guess the hw addr !\n");
16824 +                       dev_put(dev_out);
16825 +                       return NF_DROP;
16826 +               }
16827 +       
16828 +               /* Send the packet. This will also free skb
16829 +                * Do not go through the POST_ROUTING hook because 
16830 +                * skb->dst is not set and because it will probably
16831 +                * get confused by the destination IP address.
16832 +                */
16833 +               skb->dev = dev_out;
16834 +               dev_direct_send(skb);
16835 +               dev_put(dev_out);
16836 +               return NF_STOLEN;
16837 +               
16838 +       default:
16839 +               /* Unexpected error */
16840 +               dev_put(dev_out);
16841 +               return NF_DROP;
16842 +       }
16843 +}
16844 +
16845 +
16846 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
16847 +                             struct sk_buff *skb) 
16848 +{
16849 +       struct net_device *dev_out = NULL;
16850 +       unsigned int ifindex = 0;
16851 +
16852 +       /* Getting the current interface index. */
16853 +       if ((dev_out = dev_get_by_name(route_info->iif)))
16854 +               ifindex = dev_out->ifindex;
16855 +       else {
16856 +               /* Unknown interface name : packet dropped */
16857 +               if (net_ratelimit()) 
16858 +                       DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
16859 +               return NF_DROP;
16860 +       }
16861 +
16862 +       skb->dev = dev_out;
16863 +       dst_release(skb->dst);
16864 +       skb->dst = NULL;
16865 +               
16866 +       netif_rx(skb);
16867 +
16868 +       return NF_STOLEN;
16869 +}
16870 +
16871 +
16872 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
16873 +                            struct sk_buff *skb) 
16874 +{
16875 +       if (route(skb, 0, route_info)!=1)
16876 +               return NF_DROP;
16877 +
16878 +       if (route_info->flags & IPT_ROUTE_CONTINUE)
16879 +               return IPT_CONTINUE;
16880 +
16881 +       ip_direct_send(skb);
16882 +       return NF_STOLEN;
16883 +}
16884 +
16885 +
16886 +static unsigned int ipt_route_target(struct sk_buff **pskb,
16887 +                                    unsigned int hooknum,
16888 +                                    const struct net_device *in,
16889 +                                    const struct net_device *out,
16890 +                                    const void *targinfo,
16891 +                                    void *userinfo)
16892 +{
16893 +       const struct ipt_route_target_info *route_info = targinfo;
16894 +       struct sk_buff *skb = *pskb;
16895 +
16896 +       /* If we are at PREROUTING or INPUT hook
16897 +        * the TTL isn't decreased by the IP stack
16898 +        */
16899 +       if (hooknum == NF_IP_PRE_ROUTING ||
16900 +           hooknum == NF_IP_LOCAL_IN) {
16901 +
16902 +               struct iphdr *iph = skb->nh.iph;
16903 +
16904 +               if (iph->ttl <= 1) {
16905 +                       struct rtable *rt;
16906 +
16907 +                       if (ip_route_output(&rt, iph->saddr, iph->daddr,
16908 +                                           RT_TOS(iph->tos) | RTO_CONN,
16909 +                                           0)) {
16910 +                               return NF_DROP;
16911 +                       }
16912 +
16913 +                       if (skb->dev == rt->u.dst.dev) {
16914 +                               /* Drop old route. */
16915 +                               dst_release(skb->dst);
16916 +                               skb->dst = &rt->u.dst;
16917 +
16918 +                               /* this will traverse normal stack, and 
16919 +                                * thus call conntrack on the icmp packet */
16920 +                               icmp_send(skb, ICMP_TIME_EXCEEDED, 
16921 +                                         ICMP_EXC_TTL, 0);
16922 +                       }
16923 +
16924 +                       return NF_DROP;
16925 +               }
16926 +
16927 +               ip_decrease_ttl(iph);
16928 +       }
16929 +
16930 +       /* Tell conntrack to forget this packet since it may get confused 
16931 +        * when a packet is leaving with dst address == our address.
16932 +        * Good idea ? Dunno. Need advice.
16933 +        */
16934 +       if (!(route_info->flags & IPT_ROUTE_CONTINUE)) {
16935 +               nf_conntrack_put(skb->nfct);
16936 +               skb->nfct = NULL;
16937 +               skb->nfcache = 0;
16938 +#ifdef CONFIG_NETFILTER_DEBUG
16939 +               skb->nf_debug = 0;
16940 +#endif
16941 +       }
16942 +
16943 +       if (route_info->oif[0]) 
16944 +               return route_oif(route_info, *pskb);
16945 +       
16946 +       if (route_info->iif[0]) 
16947 +               return route_iif(route_info, *pskb);
16948 +
16949 +       if (route_info->gw) 
16950 +               return route_gw(route_info, *pskb);
16951 +
16952 +       if (net_ratelimit()) 
16953 +               DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
16954 +
16955 +       return IPT_CONTINUE;
16956 +}
16957 +
16958 +
16959 +static int ipt_route_checkentry(const char *tablename,
16960 +                               const struct ipt_entry *e,
16961 +                               void *targinfo,
16962 +                               unsigned int targinfosize,
16963 +                               unsigned int hook_mask)
16964 +{
16965 +       if (strcmp(tablename, "mangle") != 0) {
16966 +               printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
16967 +                      tablename);
16968 +               return 0;
16969 +       }
16970 +
16971 +       if (hook_mask & ~(  (1 << NF_IP_PRE_ROUTING)
16972 +                           | (1 << NF_IP_LOCAL_IN)
16973 +                           | (1 << NF_IP_FORWARD)
16974 +                           | (1 << NF_IP_LOCAL_OUT)
16975 +                           | (1 << NF_IP_POST_ROUTING))) {
16976 +               printk("ipt_ROUTE: bad hook\n");
16977 +               return 0;
16978 +       }
16979 +
16980 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
16981 +               printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
16982 +                      targinfosize,
16983 +                      IPT_ALIGN(sizeof(struct ipt_route_target_info)));
16984 +               return 0;
16985 +       }
16986 +
16987 +       return 1;
16988 +}
16989 +
16990 +
16991 +static struct ipt_target ipt_route_reg
16992 += { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
16993 +    THIS_MODULE };
16994 +
16995 +
16996 +static int __init init(void)
16997 +{
16998 +       if (ipt_register_target(&ipt_route_reg))
16999 +               return -EINVAL;
17000 +
17001 +       return 0;
17002 +}
17003 +
17004 +
17005 +static void __exit fini(void)
17006 +{
17007 +       ipt_unregister_target(&ipt_route_reg);
17008 +}
17009 +
17010 +module_init(init);
17011 +module_exit(fini);
17012 +MODULE_LICENSE("GPL");
17013 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_SAME.c linux-2.4.20/net/ipv4/netfilter/ipt_SAME.c
17014 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_SAME.c      Thu Jan  1 00:00:00 1970
17015 +++ linux-2.4.20/net/ipv4/netfilter/ipt_SAME.c  Wed Sep 24 09:16:38 2003
17016 @@ -0,0 +1,202 @@
17017 +/* Same.  Just like SNAT, only try to make the connections
17018 + *       between client A and server B always have the same source ip.
17019 + *
17020 + * (C) 2000 Rusty Russell.  GPL.
17021 + *
17022 + * 010320 Martin Josefsson <gandalf@wlug.westbo.se>
17023 + *     * copied ipt_BALANCE.c to ipt_SAME.c and changed a few things.
17024 + * 010728 Martin Josefsson <gandalf@wlug.westbo.se>
17025 + *     * added --nodst to not include destination-ip in new source
17026 + *       calculations.
17027 + *     * added some more sanity-checks.
17028 + * 010729 Martin Josefsson <gandalf@wlug.westbo.se>
17029 + *     * fixed a buggy if-statement in same_check(), should have
17030 + *       used ntohl() but didn't.
17031 + *     * added support for multiple ranges. IPT_SAME_MAX_RANGE is
17032 + *       defined in linux/include/linux/netfilter_ipv4/ipt_SAME.h
17033 + *       and is currently set to 10.
17034 + *     * added support for 1-address range, nice to have now that
17035 + *       we have multiple ranges.
17036 + */
17037 +#include <linux/types.h>
17038 +#include <linux/ip.h>
17039 +#include <linux/timer.h>
17040 +#include <linux/module.h>
17041 +#include <linux/netfilter.h>
17042 +#include <linux/netdevice.h>
17043 +#include <linux/if.h>
17044 +#include <linux/inetdevice.h>
17045 +#include <net/protocol.h>
17046 +#include <net/checksum.h>
17047 +#include <linux/netfilter_ipv4.h>
17048 +#include <linux/netfilter_ipv4/ip_nat_rule.h>
17049 +#include <linux/netfilter_ipv4/ipt_SAME.h>
17050 +
17051 +MODULE_LICENSE("GPL");
17052 +MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
17053 +MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
17054 +
17055 +#if 0
17056 +#define DEBUGP printk
17057 +#else
17058 +#define DEBUGP(format, args...)
17059 +#endif
17060 +
17061 +static int
17062 +same_check(const char *tablename,
17063 +             const struct ipt_entry *e,
17064 +             void *targinfo,
17065 +             unsigned int targinfosize,
17066 +             unsigned int hook_mask)
17067 +{
17068 +       unsigned int count, countess, rangeip, index = 0;
17069 +       struct ipt_same_info *mr = targinfo;
17070 +
17071 +       mr->ipnum = 0;
17072 +
17073 +       if (strcmp(tablename, "nat") != 0) {
17074 +               DEBUGP("same_check: bad table `%s'.\n", tablename);
17075 +               return 0;
17076 +       }
17077 +       if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
17078 +               DEBUGP("same_check: size %u.\n", targinfosize);
17079 +               return 0;
17080 +       }
17081 +       if (hook_mask & ~(1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING)) {
17082 +               DEBUGP("same_check: bad hooks %x.\n", hook_mask);
17083 +               return 0;
17084 +       }
17085 +       if (mr->rangesize < 1) {
17086 +               DEBUGP("same_check: need at least one dest range.\n");
17087 +               return 0;
17088 +       }
17089 +       if (mr->rangesize > IPT_SAME_MAX_RANGE) {
17090 +               DEBUGP("same_check: too many ranges specified, maximum "
17091 +                               "is %u ranges\n",
17092 +                               IPT_SAME_MAX_RANGE);
17093 +               return 0;
17094 +       }
17095 +       for (count = 0; count < mr->rangesize; count++) {
17096 +               if (ntohl(mr->range[count].min_ip) >
17097 +                               ntohl(mr->range[count].max_ip)) {
17098 +                       DEBUGP("same_check: min_ip is larger than max_ip in "
17099 +                               "range `%u.%u.%u.%u-%u.%u.%u.%u'.\n",
17100 +                               NIPQUAD(mr->range[count].min_ip),
17101 +                               NIPQUAD(mr->range[count].max_ip));
17102 +                       return 0;
17103 +               }
17104 +               if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
17105 +                       DEBUGP("same_check: bad MAP_IPS.\n");
17106 +                       return 0;
17107 +               }
17108 +               rangeip = (ntohl(mr->range[count].max_ip) - 
17109 +                                       ntohl(mr->range[count].min_ip) + 1);
17110 +               mr->ipnum += rangeip;
17111 +               
17112 +               DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
17113 +       }
17114 +       DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
17115 +       
17116 +       mr->iparray = kmalloc((sizeof(u_int32_t) * mr->ipnum), GFP_KERNEL);
17117 +       if (!mr->iparray) {
17118 +               DEBUGP("same_check: Couldn't allocate %u bytes "
17119 +                       "for %u ipaddresses!\n", 
17120 +                       (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
17121 +               return 0;
17122 +       }
17123 +       DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
17124 +                       (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
17125 +       
17126 +       for (count = 0; count < mr->rangesize; count++) {
17127 +               for (countess = ntohl(mr->range[count].min_ip);
17128 +                               countess <= ntohl(mr->range[count].max_ip);
17129 +                                       countess++) {
17130 +                       mr->iparray[index] = countess;
17131 +                       DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
17132 +                               "in index %u.\n",
17133 +                               HIPQUAD(countess), index);
17134 +                       index++;
17135 +               }
17136 +       }
17137 +       return 1;
17138 +}
17139 +
17140 +static void 
17141 +same_destroy(void *targinfo,
17142 +               unsigned int targinfosize)
17143 +{
17144 +       struct ipt_same_info *mr = targinfo;
17145 +
17146 +       kfree(mr->iparray);
17147 +       
17148 +       DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
17149 +                       (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
17150 +}
17151 +
17152 +static unsigned int
17153 +same_target(struct sk_buff **pskb,
17154 +               unsigned int hooknum,
17155 +               const struct net_device *in,
17156 +               const struct net_device *out,
17157 +               const void *targinfo,
17158 +               void *userinfo)
17159 +{
17160 +       struct ip_conntrack *ct;
17161 +       enum ip_conntrack_info ctinfo;
17162 +       u_int32_t tmpip, aindex, new_ip;
17163 +       const struct ipt_same_info *mr = targinfo;
17164 +       struct ip_nat_multi_range newrange;
17165 +       const struct ip_conntrack_tuple *t;
17166 +
17167 +       IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
17168 +                       hooknum == NF_IP_POST_ROUTING);
17169 +       ct = ip_conntrack_get(*pskb, &ctinfo);
17170 +
17171 +       t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
17172 +
17173 +       /* Base new source on real src ip and optionally dst ip,
17174 +          giving some hope for consistency across reboots.
17175 +          Here we calculate the index in mr->iparray which
17176 +          holds the ipaddress we should use */
17177 +       
17178 +       tmpip = ntohl(t->src.ip);
17179 +
17180 +       if (!(mr->info & IPT_SAME_NODST))
17181 +               tmpip += ntohl(t->dst.ip);
17182 +       
17183 +       aindex = tmpip % mr->ipnum;
17184 +               
17185 +       new_ip = htonl(mr->iparray[aindex]);
17186 +
17187 +       DEBUGP("ipt_SAME: src=%u.%u.%u.%u dst=%u.%u.%u.%u, "
17188 +                       "new src=%u.%u.%u.%u\n",
17189 +                       NIPQUAD(t->src.ip), NIPQUAD(t->dst.ip),
17190 +                       NIPQUAD(new_ip));
17191 +
17192 +       /* Transfer from original range. */
17193 +       newrange = ((struct ip_nat_multi_range)
17194 +               { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
17195 +                        new_ip, new_ip,
17196 +                        mr->range[0].min, mr->range[0].max } } });
17197 +
17198 +       /* Hand modified range to generic setup. */
17199 +       return ip_nat_setup_info(ct, &newrange, hooknum);
17200 +}
17201 +
17202 +static struct ipt_target same_reg
17203 += { { NULL, NULL }, "SAME", same_target, same_check, same_destroy,
17204 +    THIS_MODULE };
17205 +
17206 +static int __init init(void)
17207 +{
17208 +       return ipt_register_target(&same_reg);
17209 +}
17210 +
17211 +static void __exit fini(void)
17212 +{
17213 +       ipt_unregister_target(&same_reg);
17214 +}
17215 +
17216 +module_init(init);
17217 +module_exit(fini);
17218 +
17219 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_TARPIT.c linux-2.4.20/net/ipv4/netfilter/ipt_TARPIT.c
17220 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_TARPIT.c    Thu Jan  1 00:00:00 1970
17221 +++ linux-2.4.20/net/ipv4/netfilter/ipt_TARPIT.c        Wed Sep 24 09:17:45 2003
17222 @@ -0,0 +1,284 @@
17223 +/* 
17224 + * Kernel module to capture and hold incoming TCP connections using 
17225 + * no local per-connection resources.
17226 + * 
17227 + * Based on ipt_REJECT.c and offering functionality similar to 
17228 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
17229 + * 
17230 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
17231 + * 
17232 + * This program is free software; you can redistribute it and/or modify
17233 + * it under the terms of the GNU General Public License as published by
17234 + * the Free Software Foundation; either version 2 of the License, or
17235 + * (at your option) any later version.
17236 + *
17237 + * This program is distributed in the hope that it will be useful,
17238 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17239 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17240 + * GNU General Public License for more details.
17241 + *
17242 + * You should have received a copy of the GNU General Public License
17243 + * along with this program; if not, write to the Free Software
17244 + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17245 + * 
17246 + * Goal:
17247 + * - Allow incoming TCP connections to be established.
17248 + * - Passing data should result in the connection being switched to the 
17249 + *   persist state (0 byte window), in which the remote side stops sending 
17250 + *   data and asks to continue every 60 seconds.
17251 + * - Attempts to shut down the connection should be ignored completely, so 
17252 + *   the remote side ends up having to time it out.
17253 + *
17254 + * This means:
17255 + * - Reply to TCP SYN,!ACK,!RST,!FIN with SYN-ACK, window 5 bytes
17256 + * - Reply to TCP SYN,ACK,!RST,!FIN with RST to prevent spoofing
17257 + * - Reply to TCP !SYN,!RST,!FIN with ACK, window 0 bytes, rate-limited
17258 + */
17259 +
17260 +#include <linux/config.h>
17261 +#include <linux/module.h>
17262 +#include <linux/skbuff.h>
17263 +#include <linux/ip.h>
17264 +#include <net/ip.h>
17265 +#include <net/tcp.h>
17266 +#include <net/icmp.h>
17267 +struct in_device;
17268 +#include <net/route.h>
17269 +#include <linux/random.h>
17270 +#include <linux/netfilter_ipv4/ip_tables.h>
17271 +
17272 +#if 0
17273 +#define DEBUGP printk
17274 +#else
17275 +#define DEBUGP(format, args...)
17276 +#endif
17277 +
17278 +
17279 +/* Stolen from ip_finish_output2 */
17280 +static int ip_direct_send(struct sk_buff *skb)
17281 +{
17282 +       struct dst_entry *dst = skb->dst;
17283 +       struct hh_cache *hh = dst->hh;
17284 +
17285 +       if (hh) {    
17286 +               read_lock_bh(&hh->hh_lock);
17287 +               memcpy(skb->data - 16, hh->hh_data, 16);
17288 +                read_unlock_bh(&hh->hh_lock);
17289 +                skb_push(skb, hh->hh_len);
17290 +                return hh->hh_output(skb);
17291 +        } else if (dst->neighbour)
17292 +                return dst->neighbour->output(skb);
17293 +
17294 +       if (net_ratelimit())
17295 +               printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
17296 +        kfree_skb(skb);
17297 +        return -EINVAL;
17298 +}
17299 +
17300 +
17301 +/* Send reply */
17302 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
17303 +{
17304 +       struct sk_buff *nskb;
17305 +       struct rtable *nrt;
17306 +       struct tcphdr *otcph, *ntcph;
17307 +       unsigned int otcplen;
17308 +       u_int16_t tmp;
17309 +
17310 +       /* A truncated TCP header isn't going to be useful */
17311 +       if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
17312 +               return;
17313 +
17314 +       otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph 
17315 +                                  + oskb->nh.iph->ihl);
17316 +       otcplen = oskb->len - oskb->nh.iph->ihl*4;
17317 +
17318 +       /* No replies for RST or FIN */
17319 +       if (otcph->rst || otcph->fin)
17320 +               return;
17321 +
17322 +       /* No reply to !SYN,!ACK.  Rate-limit replies to !SYN,ACKs */
17323 +       if (!otcph->syn && (!otcph->ack || !xrlim_allow(&ort->u.dst, 1*HZ)))
17324 +               return;
17325 +
17326 +       /* Check checksum. */
17327 +       if (tcp_v4_check(otcph, otcplen, oskb->nh.iph->saddr,
17328 +                        oskb->nh.iph->daddr,
17329 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
17330 +               return;
17331 +
17332 +       /* Copy skb (even if skb is about to be dropped, we can't just
17333 +           clone it because there may be other things, such as tcpdump,
17334 +           interested in it) */
17335 +       nskb = skb_copy(oskb, GFP_ATOMIC);
17336 +       if (!nskb)
17337 +               return;
17338 +
17339 +       /* This packet will not be the same as the other: clear nf fields */
17340 +       nf_conntrack_put(nskb->nfct);
17341 +       nskb->nfct = NULL;
17342 +       nskb->nfcache = 0;
17343 +#ifdef CONFIG_NETFILTER_DEBUG
17344 +       nskb->nf_debug = 0;
17345 +#endif
17346 +
17347 +       ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
17348 +
17349 +       /* Truncate to length (no data) */
17350 +       ntcph->doff = sizeof(struct tcphdr)/4;
17351 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
17352 +       nskb->nh.iph->tot_len = htons(nskb->len);
17353 +
17354 +       /* Swap source and dest */
17355 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
17356 +       tmp = ntcph->source;
17357 +       ntcph->source = ntcph->dest;
17358 +       ntcph->dest = tmp;
17359 +
17360 +       /* Use supplied sequence number or make a new one */
17361 +       ntcph->seq = otcph->ack ? otcph->ack_seq 
17362 +                     : htonl(secure_tcp_sequence_number(nskb->nh.iph->saddr, 
17363 +                                                       nskb->nh.iph->daddr, 
17364 +                                                       ntcph->source, 
17365 +                                                       ntcph->dest));
17366 +
17367 +       /* Our SYN-ACKs must have a >0 window */
17368 +       ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
17369 +
17370 +       ntcph->urg_ptr = 0;
17371 +
17372 +       /* Reset flags */
17373 +       ((u_int8_t *)ntcph)[13] = 0;
17374 +
17375 +       if (otcph->syn && otcph->ack) {
17376 +               ntcph->rst = 1;
17377 +               ntcph->ack_seq = 0;
17378 +       } else {
17379 +               ntcph->syn = otcph->syn;
17380 +               ntcph->ack = 1;
17381 +               ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
17382 +       }
17383 +
17384 +       /* Adjust TCP checksum */
17385 +       ntcph->check = 0;
17386 +       ntcph->check = tcp_v4_check(ntcph, sizeof(struct tcphdr),
17387 +                                  nskb->nh.iph->saddr,
17388 +                                  nskb->nh.iph->daddr,
17389 +                                  csum_partial((char *)ntcph,
17390 +                                               sizeof(struct tcphdr), 0));
17391 +
17392 +       /* Adjust IP TTL */
17393 +       nskb->nh.iph->ttl = sysctl_ip_default_ttl;
17394 +
17395 +       /* Set DF, id = 0 */
17396 +       nskb->nh.iph->frag_off = htons(IP_DF);
17397 +       nskb->nh.iph->id = 0;
17398 +
17399 +       /* Adjust IP checksum */
17400 +       nskb->nh.iph->check = 0;
17401 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
17402 +                                          nskb->nh.iph->ihl);
17403 +
17404 +       if (ip_route_output(&nrt, nskb->nh.iph->daddr, 
17405 +                           local ? nskb->nh.iph->saddr : 0,
17406 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN, 
17407 +                           0) != 0)
17408 +               goto free_nskb;
17409 +
17410 +       dst_release(nskb->dst);
17411 +       nskb->dst = &nrt->u.dst;
17412 +
17413 +       /* "Never happens" */
17414 +       if (nskb->len > nskb->dst->pmtu)
17415 +               goto free_nskb;
17416 +
17417 +       ip_direct_send (nskb);
17418 +
17419 +       return;
17420 +
17421 + free_nskb:
17422 +       kfree_skb(nskb);
17423 +}
17424 +
17425 +
17426 +static unsigned int tarpit(struct sk_buff **pskb,
17427 +                          unsigned int hooknum,
17428 +                          const struct net_device *in,
17429 +                          const struct net_device *out,
17430 +                          const void *targinfo,
17431 +                          void *userinfo)
17432 +{
17433 +       struct sk_buff *skb = *pskb;
17434 +       struct rtable *rt = (struct rtable*)skb->dst;
17435 +
17436 +       /* Do we have an input route cache entry? */
17437 +       if (!rt)
17438 +               return NF_DROP;
17439 +
17440 +        /* No replies to physical multicast/broadcast */
17441 +        if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
17442 +               return NF_DROP;
17443 +
17444 +        /* Now check at the protocol level */
17445 +       if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
17446 +                return NF_DROP;
17447 +
17448 +       /* Our naive response construction doesn't deal with IP
17449 +           options, and probably shouldn't try. */
17450 +       if (skb->nh.iph->ihl*4 != sizeof(struct iphdr))
17451 +               return NF_DROP;
17452 +
17453 +        /* We aren't interested in fragments */
17454 +       if (skb->nh.iph->frag_off & htons(IP_OFFSET))
17455 +                return NF_DROP;
17456 +
17457 +       tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
17458 +
17459 +       return NF_DROP;
17460 +}
17461 +
17462 +
17463 +static int check(const char *tablename,
17464 +                const struct ipt_entry *e,
17465 +                void *targinfo,
17466 +                unsigned int targinfosize,
17467 +                unsigned int hook_mask)
17468 +{
17469 +       /* Only allow these for input/forward packet filtering. */
17470 +       if (strcmp(tablename, "filter") != 0) {
17471 +               DEBUGP("TARPIT: bad table %s'.\n", tablename);
17472 +               return 0;
17473 +       }
17474 +       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN) 
17475 +                           | (1 << NF_IP_FORWARD))) != 0) {
17476 +               DEBUGP("TARPIT: bad hook mask %X\n", hook_mask);
17477 +               return 0;
17478 +       }
17479 +
17480 +       /* Must specify that it's a TCP packet */
17481 +       if (e->ip.proto != IPPROTO_TCP || (e->ip.invflags & IPT_INV_PROTO)) {
17482 +               DEBUGP("TARPIT: not valid for non-tcp\n");
17483 +               return 0;
17484 +       }
17485 +
17486 +       return 1;
17487 +}
17488 +
17489 +static struct ipt_target ipt_tarpit_reg
17490 += { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
17491 +
17492 +static int __init init(void)
17493 +{
17494 +       if (ipt_register_target(&ipt_tarpit_reg))
17495 +               return -EINVAL;
17496 +       return 0;
17497 +}
17498 +
17499 +static void __exit fini(void)
17500 +{
17501 +       ipt_unregister_target(&ipt_tarpit_reg);
17502 +}
17503 +
17504 +module_init(init);
17505 +module_exit(fini);
17506 +MODULE_LICENSE("GPL");
17507 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_TCPLAG.c linux-2.4.20/net/ipv4/netfilter/ipt_TCPLAG.c
17508 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_TCPLAG.c    Thu Jan  1 00:00:00 1970
17509 +++ linux-2.4.20/net/ipv4/netfilter/ipt_TCPLAG.c        Wed Sep 24 09:17:29 2003
17510 @@ -0,0 +1,697 @@
17511 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
17512 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
17513 + *
17514 + * This program is free software; you can redistribute it and/or modify
17515 + * it under the terms of the GNU General Public License as published by
17516 + * the Free Software Foundation; either version 2 of the License, or
17517 + * (at your option) any later version.
17518 + *
17519 + * This program is distributed in the hope that it will be useful,
17520 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
17521 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17522 + * GNU General Public License for more details.
17523 + *
17524 + * You should have received a copy of the GNU General Public License
17525 + * along with this program; if not, write to the Free Software
17526 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17527 + */
17528 +
17529 +/*
17530 + * This collects packets and attempts to make them into pairs
17531 + * based on its own knowledge of how typical network conversations
17532 + * operate. Once it has a pair, it logs the time between them.
17533 + */
17534 +#include <linux/module.h>
17535 +#include <linux/skbuff.h>
17536 +#include <linux/ip.h>
17537 +#include <linux/spinlock.h>
17538 +#include <net/icmp.h>
17539 +#include <net/udp.h>
17540 +#include <net/tcp.h>
17541 +#include <linux/netfilter_ipv4/ip_tables.h>
17542 +
17543 +#include <net/route.h>
17544 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
17545 +
17546 +#if 0
17547 +#define DEBUGP printk
17548 +#else
17549 +#define DEBUGP(format, args...)
17550 +#endif
17551 +
17552 +/*
17553 + * We need one spinlock for the hash table.
17554 + */
17555 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
17556 +
17557 +typedef struct timeval timeval_T;
17558 +
17559 +/*
17560 + * Linked lists of events in the connection,
17561 + * these store the SEQ numbers and the newest is always
17562 + * at the start of the linked list, then they get older
17563 + * down to the end of the linked list (this is not perfect
17564 + * if packets get out of order but we don't worry about fine
17565 + * details like that).
17566 + *
17567 + * Matching any event wipes out that event and also all other
17568 + * events down the chain (i.e. all older events).
17569 + * This keeps the linked list as short as possible.
17570 + */
17571 +typedef struct tcplag_event_S
17572 +{
17573 +       struct tcplag_event_S *next;
17574 +       u16 source_port;
17575 +       u16 dest_port;
17576 +       u32 expected_ACK;
17577 +       struct timeval stamp;
17578 +} tcplag_event_T;
17579 +
17580 +/*
17581 + * This stores the connection statistics
17582 + * We define connections more loosely than TCP/IP does,
17583 + * because we only consider the two hosts, not the ports
17584 + * Also, we list the host-pairs in low,high order which
17585 + * means that we don't care who originated the connection.
17586 + */
17587 +typedef struct tcplag_hash_S
17588 +{
17589 +       u32 low_ip;
17590 +       u32 high_ip;
17591 +       struct timeval lag_l_SEQ_h_ACK; /* l sends some data and h acknowledges that (sum of lag times) */
17592 +       struct timeval lag_h_SEQ_l_ACK; /* h sends some data and l acknowledges that (sum of lag times) */
17593 +       tcplag_event_T *h_ACK_list;     /* Try to match ACK packets coming from h in this list */
17594 +       tcplag_event_T *l_ACK_list;     /* Try to match ACK packets coming from l in this list */
17595 +       time_t stamp;                   /* When this bucket got added to the table */
17596 +       u16 count_l_SEQ_h_ACK;          /* Increment for each event */
17597 +       u16 count_h_SEQ_l_ACK;          /* Increment for each event */
17598 +} tcplag_hash_T;
17599 +
17600 +static tcplag_hash_T **hashtab = 0;
17601 +static u32 hashsize = 0;
17602 +static u16 max_seconds = 30; /* Empty a hash bucket after this time */
17603 +static u32 reaper_ix = 0;
17604 +
17605 +static void divide_down( timeval_T *T, int c )
17606 +{
17607 +       int remainder;
17608 +
17609 +       T->tv_usec /= c;
17610 +       remainder = T->tv_sec % c; /* Only works properly with positive numbers */
17611 +       remainder *= 1000000;
17612 +       T->tv_usec == remainder;
17613 +       T->tv_sec /= c;
17614 +}
17615 +
17616 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
17617 +{
17618 +       register long x;
17619 +
17620 +       x = tv1->tv_sec - tv2->tv_sec;
17621 +       if( x ) return( x );
17622 +       x = tv1->tv_usec - tv2->tv_usec;
17623 +       return( x );
17624 +}
17625 +
17626 +void sprint_timeval( char *buf, timeval_T *tv )
17627 +{
17628 +       if( tv->tv_sec )
17629 +               sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
17630 +       else
17631 +               sprintf( buf, "%lu", tv->tv_usec );
17632 +}
17633 +
17634 +/*
17635 + * This generates the log messages through printk()
17636 + *
17637 + * There is really no particular interest in the port numbers at this stage,
17638 + * they are only useful for matching up the request with the reply.
17639 + * The IP numbers are useful because some sites may be slower than others
17640 + * or may travel different routes, etc (OK, in theory changing the port number
17641 + * could also change the route but I don't like that sort of theory).
17642 + *
17643 + * The tags are:
17644 + *
17645 + * LIP=          The IP number of the side with the lowest lag
17646 + * RIP=          The IP number of the side with the highest lag
17647 + * LLAG=         The average time (in us) between RIP->LIP SEQ and LIP->RIP ACK
17648 + * RLAG=         The average time (in us) between LIP->RIP SEQ and RIP->LIP ACK
17649 + */
17650 +static void output( tcplag_hash_T *H, int level, const char *prefix )
17651 +{
17652 +       struct timeval ltm, rtm;
17653 +       u32 local_ip, remote_ip;
17654 +       char r_buf[ 20 ], l_buf[ 20 ];
17655 +/*
17656 + * We can't make sense of a connection that only passes data one way,
17657 + * In principle, at least the SYN and FIN should go both ways so we
17658 + * should get a few hits for every connection.
17659 + */
17660 +       if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
17661 +/*
17662 + * Calculate average times by dividing down
17663 + */
17664 +       divide_down( &H->lag_l_SEQ_h_ACK, H->count_l_SEQ_h_ACK );
17665 +       divide_down( &H->lag_h_SEQ_l_ACK, H->count_h_SEQ_l_ACK );
17666 +/*
17667 + * Sort these two by the lag so the the local is always the short lag
17668 + */
17669 +       if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
17670 +       {
17671 +               local_ip    = H->low_ip;
17672 +               remote_ip   = H->high_ip;
17673 +               rtm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
17674 +               rtm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17675 +               ltm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
17676 +               ltm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17677 +       }
17678 +       else
17679 +       {
17680 +               local_ip    = H->high_ip;
17681 +               remote_ip   = H->low_ip;
17682 +               ltm.tv_sec  = H->lag_l_SEQ_h_ACK.tv_sec;
17683 +               ltm.tv_usec = H->lag_l_SEQ_h_ACK.tv_usec;
17684 +               rtm.tv_sec  = H->lag_h_SEQ_l_ACK.tv_sec;
17685 +               rtm.tv_usec = H->lag_h_SEQ_l_ACK.tv_usec;
17686 +       }
17687 +/*
17688 + * Don't use a spinlock on the output,
17689 + * it is not guaranteed safe because some OTHER printk could
17690 + * split our log message so we want only one single printk.
17691 + *
17692 + * We use sprintf() to partially pre-digest the output
17693 + *
17694 + * Actually, neither this not the main netfilter LOG target is
17695 + * really safe from printk() overlap, basically syslog cannot
17696 + * be regarded as a guaranteed data output channel. It is good
17697 + * enough for most purposes.
17698 + */
17699 +       sprint_timeval( l_buf, &ltm );
17700 +       sprint_timeval( r_buf, &rtm );
17701 +       printk( "<%d>%sLIP=%u.%u.%u.%u RIP=%u.%u.%u.%u LLAG=%s RLAG=%s\n",
17702 +                       level & 7, prefix,
17703 +                       NIPQUAD( local_ip ), NIPQUAD( remote_ip ),
17704 +                       l_buf, r_buf );
17705 +}
17706 +
17707 +/*
17708 + * The reaper rolls through the hash table looking for old.
17709 + * Log entries are only generated at the reaping time
17710 + * (which means all log entries are out-of-date)
17711 + */
17712 +static void reaper( time_t now, int level, const char *prefix )
17713 +{
17714 +       int i;
17715 +
17716 +       now -= max_seconds;
17717 +       if( !hashsize ) return;
17718 +       if( !hashtab ) return;
17719 +       for( i = 0; i < 10; i++ )
17720 +       {
17721 +               if( ++reaper_ix >= hashsize ) reaper_ix = 0; 
17722 +
17723 +//             DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
17724 +
17725 +               if( hashtab[ reaper_ix ])
17726 +               {
17727 +                       tcplag_hash_T *found = 0;
17728 +
17729 +                       spin_lock_bh( &hash_lock );
17730 +                       if( hashtab[ reaper_ix ])
17731 +                       {
17732 +                               if( now > hashtab[ reaper_ix ]->stamp )
17733 +                               {
17734 +                                       DEBUGP( KERN_WARNING "reaper found expired entry\n" );
17735 +                                       found = hashtab[ reaper_ix ];
17736 +                                       hashtab[ reaper_ix ] = 0;
17737 +                               }
17738 +                       }
17739 +                       spin_unlock_bh( &hash_lock );
17740 +
17741 +                       if( found )
17742 +                       {
17743 +                               output( found, level, prefix );
17744 +                               kfree( found );
17745 +                       }
17746 +               }
17747 +       }
17748 +}
17749 +
17750 +/*
17751 + * Convert the connection characteristics into a number
17752 + * (not including the timestamp) FIXME: this is a sucky hash function
17753 + */
17754 +static u32 make_hash( tcplag_hash_T *connection )
17755 +{
17756 +       register u32 r;
17757 +
17758 +       r = connection->low_ip;
17759 +       r += connection->high_ip;
17760 +       return( r );
17761 +}
17762 +
17763 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
17764 +{
17765 +       int x;
17766 +
17767 +       x = con1->low_ip - con2->low_ip; if( x ) return( x );
17768 +       x = con1->high_ip - con2->high_ip;
17769 +       return( x );
17770 +}
17771 +
17772 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
17773 +{
17774 +       int x;
17775 +
17776 +       DEBUGP( "Comparing sequence %u to %u\n", ev1->expected_ACK, ev2->expected_ACK );
17777 +       x = ev1->expected_ACK - ev2->expected_ACK;
17778 +       if( x ) return( x );
17779 +       DEBUGP( "Comparing source port %u to %u\n", ev1->source_port, ev2->source_port );
17780 +       x = ev1->source_port - ev2->source_port;
17781 +       if( x ) return( x );
17782 +       DEBUGP( "Comparing destination port %u to %u\n", ev1->dest_port, ev2->dest_port );
17783 +       x = ev1->dest_port - ev2->dest_port;
17784 +       return( x );
17785 +}
17786 +
17787 +/*
17788 + * Go to the hash table and either find an existing connection that
17789 + * matches correctly or inject a new connection into the table.
17790 + * Once the connection is OK, chain the event onto the linked list.
17791 + */
17792 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17793 +{
17794 +       u32 h, i;
17795 +
17796 +       if( !event ) return; /* Just to be safe */
17797 +       if( !hashsize ) return;
17798 +       if( !hashtab ) return;
17799 +
17800 +       h = make_hash( connection );
17801 +       h %= hashsize;
17802 +
17803 +       DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
17804 +
17805 +       spin_lock_bh( &hash_lock );
17806 +       for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
17807 +       {
17808 +               tcplag_hash_T *co_new = 0;
17809 +/*
17810 + * Consider existing entry
17811 + */
17812 +               if( hashtab[ h ])
17813 +               {
17814 +                       if( compare_connections( hashtab[ h ], connection )) continue;
17815 +                       co_new = hashtab[ h ];
17816 +                       DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
17817 +                       goto add_link;
17818 +               }
17819 +/*
17820 + * Use empty slot for new entry
17821 + */
17822 +               if( !hashtab[ h ])
17823 +               {
17824 +                       co_new = kmalloc( sizeof( tcplag_hash_T ), GFP_ATOMIC );
17825 +                       memset( co_new, 0, sizeof( tcplag_hash_T ));
17826 +                       co_new->low_ip = connection->low_ip;
17827 +                       co_new->high_ip = connection->high_ip;
17828 +                       co_new->stamp = event->stamp.tv_sec;
17829 +                       hashtab[ h ] = co_new;
17830 +                       DEBUGP( KERN_WARNING "Added connection to table at %u\n", h );
17831 + add_link:
17832 +                       {
17833 +                               tcplag_event_T *ev_new;
17834 +
17835 +                               ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
17836 +                               memcpy( ev_new, event, sizeof( tcplag_event_T ));
17837 +                               if( direction )
17838 +                               {
17839 +                                       ev_new->next = co_new->h_ACK_list;
17840 +                                       co_new->h_ACK_list = ev_new;
17841 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17842 +                               }
17843 +                               else
17844 +                               {
17845 +                                       ev_new->next = co_new->l_ACK_list;
17846 +                                       co_new->l_ACK_list = ev_new;
17847 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17848 +                               }
17849 +                       }
17850 +                       goto done;
17851 +               }
17852 +       }
17853 + done:
17854 +       spin_unlock_bh( &hash_lock );
17855 +}
17856 +
17857 +/*
17858 + * Search the hash table for a matching connection,
17859 + * if we can't find one of those then we are stuffed.
17860 + *
17861 + * Once a connection has been found, scan along the list for
17862 + * a matching SEQ number and if that is found then calculate
17863 + * the lag, update the counters and cut the chain at the
17864 + * point where the matching SEQ is found.
17865 + */
17866 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17867 +{
17868 +       u32 h, i;
17869 +
17870 +       if( !event ) return( 0 );
17871 +       if( !hashsize ) return( 0 );
17872 +       if( !hashtab ) return( 0 );
17873 +       h = make_hash( connection );
17874 +       h %= hashsize;
17875 +
17876 +       DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
17877 +
17878 +       for( i = 0; i < hashsize; i++ )
17879 +       {
17880 +               tcplag_hash_T *found = 0;
17881 +
17882 +               if( !hashtab[ h ]) return( 0 );
17883 +
17884 +               spin_lock_bh( &hash_lock );
17885 +               if( hashtab[ h ])
17886 +               {
17887 +                       if( !compare_connections( hashtab[ h ], connection ))
17888 +                       {
17889 +                               tcplag_event_T *ev, **evroot;
17890 +                               timeval_T *tv;
17891 +                               u16 *cn;
17892 +
17893 +                               found = hashtab[ h ];
17894 +                               if( direction )
17895 +                               {
17896 +                                       evroot = &found->h_ACK_list;
17897 +                                       tv = &found->lag_l_SEQ_h_ACK;
17898 +                                       cn = &found->count_l_SEQ_h_ACK;
17899 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is h_ACK_list\n", h );
17900 +                               }
17901 +                               else
17902 +                               {
17903 +                                       evroot = &found->l_ACK_list;
17904 +                                       tv = &found->lag_h_SEQ_l_ACK;
17905 +                                       cn = &found->count_h_SEQ_l_ACK;
17906 +                                       DEBUGP( KERN_WARNING "Connection at %u, direction is l_ACK_list\n", h );
17907 +                               }
17908 +                               for( ev = *evroot; ev; ev = ev->next )
17909 +                               {
17910 +                                       if( !compare_events( ev, event ))
17911 +                                       {
17912 +/*
17913 + * Calculate the lag (in two parts) and add that to the collection
17914 + */
17915 +                                               event->stamp.tv_sec -= ev->stamp.tv_sec;
17916 +                                               event->stamp.tv_usec -= ev->stamp.tv_usec;
17917 +                                               if( event->stamp.tv_usec < 0 )
17918 +                                               {
17919 +                                                       event->stamp.tv_usec += 1000000;
17920 +                                                       event->stamp.tv_sec++;
17921 +                                               }
17922 +                                               if( event->stamp.tv_sec < 0 )
17923 +                                               {
17924 +                                                       DEBUGP( KERN_WARNING "Negative lag detected\n" );
17925 +                                               }
17926 +                                               else
17927 +                                               {
17928 +                                                       tv->tv_sec += event->stamp.tv_sec;
17929 +                                                       tv->tv_usec += event->stamp.tv_usec;
17930 +                                                       ++*cn;
17931 +                                                       DEBUGP( KERN_WARNING "Found a match, added %lu.%06lu"
17932 +                                                                       " (accumulator is up to %lu.%06lu, %u events)\n",
17933 +                                                                       event->stamp.tv_sec,
17934 +                                                                       event->stamp.tv_usec,
17935 +                                                                       tv->tv_sec, tv->tv_usec, *cn );
17936 +                                               }
17937 +/*
17938 + * Truncate the linked list.
17939 + *
17940 + * Visit each event in the list and return the memory to the pool.
17941 + *
17942 + * If a host is making multiple connections to the same remote host
17943 + * then this truncation will result in some requests not being
17944 + * monitored. Statistically we will still get some reasonable number
17945 + * of measurements and multiple simultaneous connections between host
17946 + * pairs don't happen all that often.
17947 + */
17948 +                                               *evroot = 0;
17949 +                                               while( ev )
17950 +                                               {
17951 +                                                       tcplag_event_T *ev_next = ev->next;
17952 +                                                       DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
17953 +                                                       kfree( ev );
17954 +                                                       ev = ev_next;
17955 +                                               }
17956 +/*
17957 + * TODO: overflow limit for *cn, force premature output() if necessary
17958 + * (and drop this connection from the hash table)
17959 + */
17960 +                                               break;
17961 +                                       }
17962 +                               }
17963 +                               goto done;
17964 +                       }
17965 +               }
17966 + done:
17967 +               spin_unlock_bh( &hash_lock );
17968 +
17969 +               if( found ) return( 1 );
17970 +               if( ++h >= hashsize ) h = 0;
17971 +       }       
17972 +       return( 0 );
17973 +}
17974 +
17975 +/*
17976 + * Here is our target data:
17977 + *
17978 + * pskb      --  The packet itself (see linux/skbuff.h for breakdown)
17979 + *
17980 + * hooknum   --
17981 + *
17982 + * in        --  The device that this packet came in on
17983 + *               (depending on the chain this may or may not exist)
17984 + *
17985 + * out       --  The device that this packet is just about to go
17986 + *               out onto (again existance depends on the chain)
17987 + *
17988 + * targinfo  --  Our private data (handed through from iptables command util)
17989 + *
17990 + * userinfo  --  Some more data
17991 + *
17992 + */
17993 +
17994 +static unsigned int target( struct sk_buff **pskb,
17995 +                                                       unsigned int hooknum,
17996 +                                                       const struct net_device *in,
17997 +                                                       const struct net_device *out,
17998 +                                                       const void *targinfo,
17999 +                                                       void *userinfo )
18000 +{
18001 +       struct iphdr *iph = ( *pskb )->nh.iph;
18002 +       const struct ipt_tcplag *el = targinfo;
18003 +       tcplag_hash_T connection;
18004 +       tcplag_event_T event;
18005 +       int direction;
18006 +/*
18007 + * We know we are dealing with IP here
18008 + * Fill in all the obvious fields
18009 + */
18010 +       if( iph->saddr > iph->daddr )
18011 +       {
18012 +               direction = 0;
18013 +               connection.high_ip = iph->saddr;
18014 +               connection.low_ip = iph->daddr;
18015 +       }
18016 +       else
18017 +       {
18018 +               direction = 1;
18019 +               connection.low_ip = iph->saddr;
18020 +               connection.high_ip = iph->daddr;
18021 +       }
18022 +       do_gettimeofday( &event.stamp );
18023 +/*
18024 + * Do a bit of cleaning
18025 + */
18026 +       reaper( event.stamp.tv_sec, el->level, el->prefix );
18027 +
18028 +       DEBUGP( KERN_WARNING "got packet %lu %lu %s %s\n",
18029 +                       event.stamp.tv_sec,
18030 +                       event.stamp.tv_usec,
18031 +                       in ? in->name : "none", out ? out->name : "none" );
18032 +/*
18033 + * Now start looking at the details
18034 + *
18035 + * First step is to identify this packet to see if it is 
18036 + * the sort of packet that we are interested in.
18037 + * Don't hold any locks while we are doing this because often
18038 + * we will just let the packet go without any further consideration.
18039 + */
18040 +       switch( iph->protocol )
18041 +       {
18042 +               case IPPROTO_TCP:
18043 +               {
18044 +                       struct tcphdr *tcp;
18045 +
18046 +                       if( ntohs( iph->frag_off ) & IP_OFFSET )
18047 +                       {
18048 +                               DEBUGP( KERN_WARNING "ignoring fragment\n" );
18049 +                               break;
18050 +                       }
18051 +                       tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
18052 +                       event.source_port = ntohs( tcp->source );
18053 +                       event.dest_port = ntohs( tcp->dest );
18054 +/*
18055 + * Every packet should have a valid SEQ number so use this to
18056 + * generate an ACK number. This works along the formula:
18057 + * -- Start with the SEQ number
18058 + * -- For SYN or FIN add 1 to that number
18059 + * -- For data packet, add the data length to that number
18060 + */
18061 +
18062 +/*
18063 + * Data length requires a bit of fiddling around
18064 + */
18065 +                       {
18066 +                               unsigned int data_len;
18067 +                               if( tcp->syn || tcp->fin )
18068 +                               {
18069 +                                       data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
18070 +                               }
18071 +                               else
18072 +                               {
18073 +                                       data_len = ntohs( iph->tot_len );
18074 +                                       data_len -= 4 * iph->ihl;  /* Subtract away IP header & options */
18075 +                                       data_len -= 4 * tcp->doff; /* Subtract away TCP header & options */
18076 +                               }
18077 +                               
18078 +                               DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
18079 +
18080 +                               if( data_len ) /* Only track events that demand an ACK */
18081 +                               {
18082 +                                       event.expected_ACK = ntohl( tcp->seq ) + data_len;
18083 +                                       hash_insert( &connection, &event, direction );
18084 +                               }
18085 +                               else
18086 +                               {
18087 +                                       DEBUGP( "Don't bother to insert this, ACK not required\n" );
18088 +                               }
18089 +                       }
18090 +
18091 +                       if( tcp->ack )
18092 +                       {
18093 +/*
18094 + * Now we consider the matching of an existing event.
18095 + * Reverse the port numbers and change the ACK number to the actual ACK number
18096 + * Note that the direction is reversed because the reply will be going
18097 + * the opposite way to the request.
18098 + */
18099 +                               event.expected_ACK = ntohl( tcp->ack_seq );
18100 +                               event.dest_port = ntohs( tcp->source );
18101 +                               event.source_port = ntohs( tcp->dest );
18102 +                               request_complete( &connection, &event, !direction );
18103 +                       }
18104 +                       else
18105 +                       {
18106 +                               DEBUGP( "Don't bother to check this, ACK not valid\n" );
18107 +                       }
18108 +               }
18109 +       }
18110 +       return( IPT_CONTINUE );
18111 +}
18112 +
18113 +/*
18114 + * return( 0 ) if there is a problem with this entry (i.e. kick it out of the kernel)
18115 + * return( 1 ) if the entry is suitable
18116 + *
18117 + * tablename     --  
18118 + *
18119 + * e             --  
18120 + *
18121 + * targinfo      --  Our private data block (handed to us from iptables plug-in)
18122 + *
18123 + * targinfosize  --  The size of our private data block
18124 + *
18125 + * hook_mask     --  
18126 + *
18127 + *
18128 + * Not much can go wrong for us, any illegal flags are harmlessly ignored,
18129 + * all possible flag combos make sense. All we check for is correct data size.
18130 + */
18131 +static int checkentry( const char *tablename,
18132 +                                          const struct ipt_entry *e,
18133 +                                          void *targinfo,
18134 +                                          unsigned int targinfosize,
18135 +                                          unsigned int hook_mask )
18136 +{
18137 +       const struct ipt_tcplag *el = targinfo;
18138 +
18139 +       if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
18140 +       {
18141 +               DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
18142 +                               IPT_ALIGN( sizeof( struct ipt_tcplag )));
18143 +               return( 0 );
18144 +       }
18145 +       if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
18146 +       return( 1 );
18147 +}
18148 +
18149 +static struct ipt_target reg =
18150 +{
18151 +       { 0, 0 },
18152 +       "TCPLAG",
18153 +       &target,
18154 +       &checkentry,
18155 +       0,
18156 +    THIS_MODULE
18157 +};
18158 +
18159 +static int __init init( void )
18160 +{
18161 +       if( ipt_register_target( &reg )) return( -EINVAL );
18162 +       hashsize = 123; /* should be configurable */
18163 +       hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
18164 +       memset( hashtab, 0, sizeof( void * ) * hashsize );
18165 +       return( 0 );
18166 +}
18167 +
18168 +/*
18169 + * This should not need locks (in theory)
18170 + * because it can only get punted after it is no longer
18171 + * chained into any of the netfilter lists.
18172 + */
18173 +static void __exit fini( void )
18174 +{
18175 +       int i;
18176 +
18177 +       ipt_unregister_target( &reg );
18178 +/*
18179 + * Put back kernel memory
18180 + */
18181 +       for( i = 0; i < hashsize; i++ )
18182 +       {
18183 +               tcplag_hash_T *p;
18184 +
18185 +               if(( p = hashtab[ i ]))
18186 +               {
18187 +                       tcplag_event_T *ev, *evn;
18188 +
18189 +                       hashtab[ i ] = 0;
18190 +                       for( ev = p->h_ACK_list; ev; ev = evn )
18191 +                       {
18192 +                               evn = ev->next;
18193 +                               kfree( ev );
18194 +                       }
18195 +                       for( ev = p->l_ACK_list; ev; ev = evn )
18196 +                       {
18197 +                               evn = ev->next;
18198 +                               kfree( ev );
18199 +                       }
18200 +                       kfree( p );
18201 +               }
18202 +       }
18203 +       kfree( hashtab );
18204 +}
18205 +
18206 +module_init(init);
18207 +module_exit(fini);
18208 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_TRACE.c linux-2.4.20/net/ipv4/netfilter/ipt_TRACE.c
18209 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_TRACE.c     Thu Jan  1 00:00:00 1970
18210 +++ linux-2.4.20/net/ipv4/netfilter/ipt_TRACE.c Wed Sep 24 09:18:12 2003
18211 @@ -0,0 +1,66 @@
18212 +/* This is a module which is used for setting 
18213 + * the NFC_TRACE flag in the nfcache field of an skb. 
18214 + */
18215 +#include <linux/module.h>
18216 +#include <linux/skbuff.h>
18217 +
18218 +#include <linux/netfilter_ipv4/ip_tables.h>
18219 +
18220 +static unsigned int
18221 +target(struct sk_buff **pskb,
18222 +       unsigned int hooknum,
18223 +       const struct net_device *in,
18224 +       const struct net_device *out,
18225 +       const void *targinfo,
18226 +       void *userinfo)
18227 +{
18228 +       (*pskb)->nfcache |= NFC_TRACE;
18229 +       return IPT_CONTINUE;
18230 +}
18231 +
18232 +static int
18233 +checkentry(const char *tablename,
18234 +          const struct ipt_entry *e,
18235 +           void *targinfo,
18236 +           unsigned int targinfosize,
18237 +           unsigned int hook_mask)
18238 +{
18239 +       if (targinfosize != 0) {
18240 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
18241 +                      targinfosize);
18242 +               return 0;
18243 +       }
18244 +
18245 +       if (strcmp(tablename, "raw") != 0) {
18246 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
18247 +               return 0;
18248 +       }
18249 +
18250 +       return 1;
18251 +}
18252 +
18253 +static struct ipt_target ipt_trace_reg = { 
18254 +       .list = { NULL, NULL }, 
18255 +       .name = "TRACE", 
18256 +       .target = target, 
18257 +       .checkentry = checkentry, 
18258 +       .destroy = NULL, 
18259 +       .me THIS_MODULE
18260 +};
18261 +
18262 +static int __init init(void)
18263 +{
18264 +       if (ipt_register_target(&ipt_trace_reg))
18265 +               return -EINVAL;
18266 +
18267 +       return 0;
18268 +}
18269 +
18270 +static void __exit fini(void)
18271 +{
18272 +       ipt_unregister_target(&ipt_trace_reg);
18273 +}
18274 +
18275 +module_init(init);
18276 +module_exit(fini);
18277 +MODULE_LICENSE("GPL");
18278 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_TTL.c linux-2.4.20/net/ipv4/netfilter/ipt_TTL.c
18279 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_TTL.c       Thu Jan  1 00:00:00 1970
18280 +++ linux-2.4.20/net/ipv4/netfilter/ipt_TTL.c   Wed Sep 24 09:16:40 2003
18281 @@ -0,0 +1,110 @@
18282 +/* TTL modification target for IP tables
18283 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
18284 + *
18285 + * Version: 1.8
18286 + *
18287 + * This software is distributed under the terms of GNU GPL
18288 + */
18289 +
18290 +#include <linux/module.h>
18291 +#include <linux/skbuff.h>
18292 +#include <linux/ip.h>
18293 +#include <net/checksum.h>
18294 +
18295 +#include <linux/netfilter_ipv4/ip_tables.h>
18296 +#include <linux/netfilter_ipv4/ipt_TTL.h>
18297 +
18298 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
18299 +MODULE_DESCRIPTION("IP tables TTL modification module");
18300 +MODULE_LICENSE("GPL");
18301 +
18302 +static unsigned int ipt_ttl_target(struct sk_buff **pskb, unsigned int hooknum,
18303 +               const struct net_device *in, const struct net_device *out,
18304 +               const void *targinfo, void *userinfo)
18305 +{
18306 +       struct iphdr *iph = (*pskb)->nh.iph;
18307 +       const struct ipt_TTL_info *info = targinfo;
18308 +       u_int16_t diffs[2];
18309 +       int new_ttl;
18310 +                        
18311 +       switch (info->mode) {
18312 +               case IPT_TTL_SET:
18313 +                       new_ttl = info->ttl;
18314 +                       break;
18315 +               case IPT_TTL_INC:
18316 +                       new_ttl = iph->ttl + info->ttl;
18317 +                       if (new_ttl > 255)
18318 +                               new_ttl = 255;
18319 +                       break;
18320 +               case IPT_TTL_DEC:
18321 +                       new_ttl = iph->ttl + info->ttl;
18322 +                       if (new_ttl < 0)
18323 +                               new_ttl = 0;
18324 +                       break;
18325 +               default:
18326 +                       new_ttl = iph->ttl;
18327 +                       break;
18328 +       }
18329 +
18330 +       if (new_ttl != iph->ttl) {
18331 +               diffs[0] = htons(((unsigned)iph->ttl) << 8) ^ 0xFFFF;
18332 +               iph->ttl = new_ttl;
18333 +               diffs[1] = htons(((unsigned)iph->ttl) << 8);
18334 +               iph->check = csum_fold(csum_partial((char *)diffs,
18335 +                                                   sizeof(diffs),
18336 +                                                   iph->check^0xFFFF));
18337 +                                                                                               (*pskb)->nfcache |= NFC_ALTERED;
18338 +       }
18339 +
18340 +       return IPT_CONTINUE;
18341 +}
18342 +
18343 +static int ipt_ttl_checkentry(const char *tablename,
18344 +               const struct ipt_entry *e,
18345 +               void *targinfo,
18346 +               unsigned int targinfosize,
18347 +               unsigned int hook_mask)
18348 +{
18349 +       struct ipt_TTL_info *info = targinfo;
18350 +
18351 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
18352 +               printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
18353 +                               targinfosize,
18354 +                               IPT_ALIGN(sizeof(struct ipt_TTL_info)));
18355 +               return 0;       
18356 +       }       
18357 +
18358 +       if (strcmp(tablename, "mangle")) {
18359 +               printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
18360 +               return 0;
18361 +       }
18362 +
18363 +       if (info->mode > IPT_TTL_MAXMODE) {
18364 +               printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n", 
18365 +                       info->mode);
18366 +               return 0;
18367 +       }
18368 +
18369 +       if ((info->mode != IPT_TTL_SET) && (info->ttl == 0)) {
18370 +               printk(KERN_WARNING "TTL: increment/decrement doesn't make sense with value 0\n");
18371 +               return 0;
18372 +       }
18373 +       
18374 +       return 1;
18375 +}
18376 +
18377 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL", 
18378 +       ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
18379 +
18380 +static int __init init(void)
18381 +{
18382 +       return ipt_register_target(&ipt_TTL);
18383 +}
18384 +
18385 +static void __exit fini(void)
18386 +{
18387 +       ipt_unregister_target(&ipt_TTL);
18388 +}
18389 +
18390 +module_init(init);
18391 +module_exit(fini);
18392 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_ULOG.c linux-2.4.20/net/ipv4/netfilter/ipt_ULOG.c
18393 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_ULOG.c      Thu Nov 28 23:53:15 2002
18394 +++ linux-2.4.20/net/ipv4/netfilter/ipt_ULOG.c  Wed Sep 24 09:16:23 2003
18395 @@ -12,6 +12,7 @@
18396   *           module loadtime -HW
18397   * 2002/07/07 remove broken nflog_rcv() function -HW
18398   * 2002/08/29 fix shifted/unshifted nlgroup bug -HW
18399 + * 2002/10/30 fix uninitialized mac_len field - <Anders K. Pedersen>
18400   *
18401   * Released under the terms of the GPL
18402   *
18403 @@ -31,7 +32,7 @@
18404   *   Specify, after how many clock ticks (intel: 100 per second) the queue
18405   * should be flushed even if it is not full yet.
18406   *
18407 - * ipt_ULOG.c,v 1.21 2002/08/29 10:54:34 laforge Exp
18408 + * ipt_ULOG.c,v 1.22 2002/10/30 09:07:31 laforge Exp
18409   */
18410  
18411  #include <linux/module.h>
18412 @@ -47,6 +48,7 @@
18413  #include <linux/mm.h>
18414  #include <linux/socket.h>
18415  #include <linux/netfilter_ipv4/ip_tables.h>
18416 +#include <linux/netfilter_ipv4/ip_logging.h>
18417  #include <linux/netfilter_ipv4/ipt_ULOG.h>
18418  #include <linux/netfilter_ipv4/lockhelp.h>
18419  #include <net/sock.h>
18420 @@ -76,6 +78,10 @@
18421  MODULE_PARM(flushtimeout, "i");
18422  MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
18423  
18424 +static unsigned int nflog = 1;
18425 +MODULE_PARM(nflog, "i");
18426 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
18427 +
18428  /* global data structures */
18429  
18430  typedef struct {
18431 @@ -153,17 +159,17 @@
18432         return skb;
18433  }
18434  
18435 -static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18436 -                                   unsigned int hooknum,
18437 -                                   const struct net_device *in,
18438 -                                   const struct net_device *out,
18439 -                                   const void *targinfo, void *userinfo)
18440 +static void ipt_ulog_packet(struct sk_buff **pskb,
18441 +                           unsigned int hooknum,
18442 +                           const struct net_device *in,
18443 +                           const struct net_device *out,
18444 +                           const struct ipt_ulog_info *loginfo,
18445 +                           const char *prefix)
18446  {
18447         ulog_buff_t *ub;
18448         ulog_packet_msg_t *pm;
18449         size_t size, copy_len;
18450         struct nlmsghdr *nlh;
18451 -       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18452  
18453         /* ffs == find first bit set, necessary because userspace
18454          * is already shifting groupnumber, but we need unshifted.
18455 @@ -214,7 +220,9 @@
18456         pm->timestamp_usec = (*pskb)->stamp.tv_usec;
18457         pm->mark = (*pskb)->nfmark;
18458         pm->hook = hooknum;
18459 -       if (loginfo->prefix[0] != '\0')
18460 +       if (prefix != NULL)
18461 +               strncpy(pm->prefix, prefix, sizeof(pm->prefix));
18462 +       else if (loginfo->prefix[0] != '\0')
18463                 strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
18464         else
18465                 *(pm->prefix) = '\0';
18466 @@ -224,7 +232,8 @@
18467             && in->hard_header_len <= ULOG_MAC_LEN) {
18468                 memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len);
18469                 pm->mac_len = in->hard_header_len;
18470 -       }
18471 +       } else
18472 +               pm->mac_len = 0;
18473  
18474         if (in)
18475                 strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
18476 @@ -260,8 +269,7 @@
18477  
18478         UNLOCK_BH(&ulog_lock);
18479  
18480 -       return IPT_CONTINUE;
18481 -
18482 +       return;
18483  
18484  nlmsg_failure:
18485         PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18486 @@ -270,8 +278,128 @@
18487         PRINTR("ipt_ULOG: Error building netlink message\n");
18488  
18489         UNLOCK_BH(&ulog_lock);
18490 +}
18491  
18492 -       return IPT_CONTINUE;
18493 +static unsigned int ipt_ulog_target(struct sk_buff **pskb,
18494 +                                   unsigned int hooknum,
18495 +                                   const struct net_device *in,
18496 +                                   const struct net_device *out,
18497 +                                   const void *targinfo, void *userinfo)
18498 +{
18499 +       struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18500 +
18501 +       ipt_ulog_packet(pskb, hooknum, in, out, loginfo, NULL);
18502
18503 +       return IPT_CONTINUE;
18504 +}
18505
18506 +static void ip_ulog_packet_fn(struct sk_buff **pskb,
18507 +                             unsigned int hooknum,
18508 +                             const struct net_device *in,
18509 +                             const struct net_device *out,
18510 +                             const char *prefix)
18511 +{
18512 +       struct ipt_ulog_info loginfo = { 
18513 +               .nl_group = ULOG_DEFAULT_NLGROUP,
18514 +               .copy_range = 0,
18515 +               .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
18516 +               .prefix = ""
18517 +       };
18518 +
18519 +       ipt_ulog_packet(pskb, hooknum, in, out, &loginfo, prefix);
18520 +}
18521 +
18522 +static void ip_ulog_fn(char *pfh, size_t len,
18523 +                      const char *prefix)
18524 +{
18525 +       struct ipt_ulog_info loginfo = { 
18526 +               .nl_group = ULOG_DEFAULT_NLGROUP,
18527 +               .copy_range = 0,
18528 +               .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
18529 +               .prefix = ""
18530 +       };
18531 +       ulog_buff_t *ub;
18532 +       ulog_packet_msg_t *pm;
18533 +       size_t size;
18534 +       struct nlmsghdr *nlh;
18535 +
18536 +       /* ffs == find first bit set, necessary because userspace
18537 +        * is already shifting groupnumber, but we need unshifted.
18538 +        * ffs() returns [1..32], we need [0..31] */
18539 +       unsigned int groupnum = ffs(loginfo.nl_group) - 1;
18540 +
18541 +       size = NLMSG_SPACE(sizeof(*pm) + len);
18542 +
18543 +       ub = &ulog_buffers[groupnum];
18544 +       
18545 +       LOCK_BH(&ulog_lock);
18546 +
18547 +       if (!ub->skb) {
18548 +               if (!(ub->skb = ulog_alloc_skb(size)))
18549 +                       goto alloc_failure;
18550 +       } else if (ub->qlen >= loginfo.qthreshold ||
18551 +                  size > skb_tailroom(ub->skb)) {
18552 +               /* either the queue len is too high or we don't have 
18553 +                * enough room in nlskb left. send it to userspace. */
18554 +
18555 +               ulog_send(groupnum);
18556 +
18557 +               if (!(ub->skb = ulog_alloc_skb(size)))
18558 +                       goto alloc_failure;
18559 +       }
18560 +
18561 +       DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen, 
18562 +               loginfo.qthreshold);
18563 +
18564 +       /* NLMSG_PUT contains a hidden goto nlmsg_failure !!! */
18565 +       nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, 
18566 +                       size - sizeof(*nlh));
18567 +       ub->qlen++;
18568 +
18569 +       pm = NLMSG_DATA(nlh);
18570 +
18571 +       /* Set fake hook, prefix, timestamp etc. */
18572 +       pm->data_len = len;
18573 +       pm->timestamp_sec = 0;
18574 +       pm->timestamp_usec = 0;
18575 +       pm->mark = 0;
18576 +       pm->hook = 0;
18577 +       strncpy(pm->prefix, prefix, sizeof(pm->prefix));
18578 +       pm->mac_len = 0;
18579 +       pm->indev_name[0] = '\0';
18580 +       pm->outdev_name[0] = '\0';
18581 +       memcpy(pm->payload, pfh, len);
18582 +       
18583 +       /* check if we are building multi-part messages */
18584 +       if (ub->qlen > 1) {
18585 +               ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
18586 +       }
18587 +
18588 +       /* if threshold is reached, send message to userspace */
18589 +       if (qlen >= loginfo.qthreshold) {
18590 +               if (loginfo.qthreshold > 1)
18591 +                       nlh->nlmsg_type = NLMSG_DONE;
18592 +       }
18593 +
18594 +       ub->lastnlh = nlh;
18595 +
18596 +       /* if timer isn't already running, start it */
18597 +       if (!timer_pending(&ub->timer)) {
18598 +               ub->timer.expires = jiffies + flushtimeout;
18599 +               add_timer(&ub->timer);
18600 +       }
18601 +
18602 +       UNLOCK_BH(&ulog_lock);
18603 +
18604 +       return;
18605 +
18606 +nlmsg_failure:
18607 +       PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18608 +
18609 +alloc_failure:
18610 +       PRINTR("ipt_ULOG: Error building netlink message\n");
18611 +
18612 +       UNLOCK_BH(&ulog_lock);
18613  }
18614  
18615  static int ipt_ulog_checkentry(const char *tablename,
18616 @@ -306,6 +434,8 @@
18617      { {NULL, NULL}, "ULOG", ipt_ulog_target, ipt_ulog_checkentry, NULL,
18618  THIS_MODULE
18619  };
18620 +static struct nf_logging_t ip_logging_fn
18621 += { ip_ulog_packet_fn, ip_ulog_fn };
18622  
18623  static int __init init(void)
18624  {
18625 @@ -320,7 +450,6 @@
18626  
18627         /* initialize ulog_buffers */
18628         for (i = 0; i < ULOG_MAXNLGROUPS; i++) {
18629 -               memset(&ulog_buffers[i], 0, sizeof(ulog_buff_t));
18630                 init_timer(&ulog_buffers[i].timer);
18631                 ulog_buffers[i].timer.function = ulog_timer;
18632                 ulog_buffers[i].timer.data = i;
18633 @@ -334,7 +463,9 @@
18634                 sock_release(nflognl->socket);
18635                 return -EINVAL;
18636         }
18637 -
18638 +       if (nflog)
18639 +               nf_ip_log_register(&ip_logging_fn);
18640 +       
18641         return 0;
18642  }
18643  
18644 @@ -345,6 +476,8 @@
18645  
18646         DEBUGP("ipt_ULOG: cleanup_module\n");
18647  
18648 +       if (nflog)
18649 +               nf_ip_log_unregister(&ip_logging_fn);
18650         ipt_unregister_target(&ipt_ulog_reg);
18651         sock_release(nflognl->socket);
18652  
18653 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_XOR.c linux-2.4.20/net/ipv4/netfilter/ipt_XOR.c
18654 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_XOR.c       Thu Jan  1 00:00:00 1970
18655 +++ linux-2.4.20/net/ipv4/netfilter/ipt_XOR.c   Wed Sep 24 09:17:31 2003
18656 @@ -0,0 +1,107 @@
18657 +/* XOR target for IP tables
18658 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
18659 + * Based on ipt_TTL.c
18660 + *
18661 + * Version 1.0
18662 + *
18663 + * This software is distributed under the terms of GNU GPL
18664 + */
18665 +
18666 +#include <linux/module.h>
18667 +#include <linux/skbuff.h>
18668 +#include <linux/ip.h>
18669 +#include <linux/tcp.h>
18670 +#include <linux/udp.h>
18671 +
18672 +#include <linux/netfilter_ipv4/ip_tables.h>
18673 +#include <linux/netfilter_ipv4/ipt_XOR.h>
18674 +
18675 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
18676 +MODULE_DESCRIPTION("IP tables XOR module");
18677 +MODULE_LICENSE("GPL");
18678 +
18679 +static unsigned int ipt_xor_target(struct sk_buff **pskb, unsigned int hooknum, 
18680 +               const struct net_device *in, const struct net_device *out, 
18681 +               const void *targinfo, void *userinfo)
18682 +{
18683 +       struct ipt_XOR_info *info = (void *) targinfo;
18684 +       struct iphdr *iph = (*pskb)->nh.iph;
18685 +       struct tcphdr *tcph;
18686 +       struct udphdr *udph;
18687 +       int i, j, k;
18688 +  
18689 +       if (iph->protocol == IPPROTO_TCP) {
18690 +               tcph = (struct tcphdr *) ((*pskb)->data + iph->ihl*4);
18691 +               for (i=0, j=0; i<(ntohs(iph->tot_len) - iph->ihl*4 - tcph->doff*4); ) {
18692 +                       for (k=0; k<=info->block_size; k++) {
18693 +                               (char) (*pskb)->data[ iph->ihl*4 + tcph->doff*4 + i ] ^= 
18694 +                                               info->key[j];
18695 +                               i++;
18696 +                       }
18697 +                       j++;
18698 +                       if (info->key[j] == 0x00)
18699 +                               j = 0;
18700 +               }
18701 +       } else if (iph->protocol == IPPROTO_UDP) {
18702 +               udph = (struct udphdr *) ((*pskb)->data + iph->ihl*4);
18703 +               for (i=0, j=0; i<(ntohs(udph->len)-8); ) {
18704 +                       for (k=0; k<=info->block_size; k++) {
18705 +                               (char) (*pskb)->data[ iph->ihl*4 + sizeof(struct udphdr) + i ] ^= 
18706 +                                               info->key[j];
18707 +                               i++;
18708 +                       }
18709 +                       j++;
18710 +                       if (info->key[j] == 0x00)
18711 +                               j = 0;
18712 +               }
18713 +       }
18714 +  
18715 +       return IPT_CONTINUE;
18716 +}
18717 +
18718 +static int ipt_xor_checkentry(const char *tablename, const struct ipt_entry *e,
18719 +               void *targinfo, unsigned int targinfosize, 
18720 +               unsigned int hook_mask)
18721 +{
18722 +       struct ipt_XOR_info *info = targinfo;
18723 +
18724 +       if (targinfosize != IPT_ALIGN(sizeof(struct ipt_XOR_info))) {
18725 +               printk(KERN_WARNING "XOR: targinfosize %u != %Zu\n", 
18726 +                               targinfosize, IPT_ALIGN(sizeof(struct ipt_XOR_info)));
18727 +       return 0;
18728 +       }       
18729 +
18730 +       if (strcmp(tablename, "mangle")) {
18731 +               printk(KERN_WARNING "XOR: can only be called from"
18732 +                               "\"mangle\" table, not \"%s\"\n", tablename);
18733 +               return 0; 
18734 +       }
18735 +
18736 +       if (!strcmp(info->key, "")) {
18737 +               printk(KERN_WARNING "XOR: You must specify a key");
18738 +               return 0;
18739 +       }
18740 +
18741 +       if (info->block_size == 0) {
18742 +               printk(KERN_WARNING "XOR: You must specify a block-size");
18743 +               return 0;
18744 +       }
18745 +
18746 +       return 1;
18747 +}
18748 +
18749 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
18750 +       ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
18751 +
18752 +static int __init init(void)
18753 +{
18754 +       return ipt_register_target(&ipt_XOR);
18755 +}
18756 +
18757 +static void __exit fini(void)
18758 +{
18759 +       ipt_unregister_target(&ipt_XOR);
18760 +}
18761 +
18762 +module_init(init);
18763 +module_exit(fini);
18764 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_addrtype.c linux-2.4.20/net/ipv4/netfilter/ipt_addrtype.c
18765 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_addrtype.c  Thu Jan  1 00:00:00 1970
18766 +++ linux-2.4.20/net/ipv4/netfilter/ipt_addrtype.c      Wed Sep 24 09:17:32 2003
18767 @@ -0,0 +1,65 @@
18768 +/*
18769 + *  iptables module to match inet_addr_type() of an ip.
18770 + */
18771 +
18772 +#include <linux/module.h>
18773 +#include <linux/skbuff.h>
18774 +#include <linux/netdevice.h>
18775 +#include <net/route.h>
18776 +
18777 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
18778 +#include <linux/netfilter_ipv4/ip_tables.h>
18779 +
18780 +MODULE_LICENSE("GPL");
18781 +
18782 +static inline int match_type(u_int32_t addr, u_int16_t mask)
18783 +{
18784 +       return !!(mask & (1 << inet_addr_type(addr)));
18785 +}
18786 +
18787 +static int match(const struct sk_buff *skb, const struct net_device *in,
18788 +                const struct net_device *out, const void *matchinfo,
18789 +                int offset, const void *hdr, u_int16_t datalen,
18790 +                int *hotdrop)
18791 +{
18792 +       const struct ipt_addrtype_info *info = matchinfo;
18793 +       const struct iphdr *iph = skb->nh.iph;
18794 +       int ret = 1;
18795 +
18796 +       if (info->source)
18797 +               ret &= match_type(iph->saddr, info->source)^info->invert_source;
18798 +       if (info->dest)
18799 +               ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
18800 +       
18801 +       return ret;
18802 +}
18803 +
18804 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
18805 +                     void *matchinfo, unsigned int matchsize,
18806 +                     unsigned int hook_mask)
18807 +{
18808 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_addrtype_info))) {
18809 +               printk(KERN_ERR "ipt_addrtype: invalid size (%u != %u)\n.",
18810 +                      matchsize, IPT_ALIGN(sizeof(struct ipt_addrtype_info)));
18811 +               return 0;
18812 +       }
18813 +
18814 +       return 1;
18815 +}
18816 +
18817 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
18818 +               &checkentry, NULL, THIS_MODULE };
18819 +
18820 +static int __init init(void)
18821 +{
18822 +       return ipt_register_match(&addrtype_match);
18823 +}
18824 +
18825 +static void __exit fini(void)
18826 +{
18827 +       ipt_unregister_match(&addrtype_match);
18828 +
18829 +}
18830 +
18831 +module_init(init);
18832 +module_exit(fini);
18833 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_ah.c linux-2.4.20/net/ipv4/netfilter/ipt_ah.c
18834 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_ah.c        Thu Nov 28 23:53:15 2002
18835 +++ linux-2.4.20/net/ipv4/netfilter/ipt_ah.c    Wed Sep 24 09:16:18 2003
18836 @@ -15,7 +15,11 @@
18837  #endif
18838  
18839  struct ahhdr {
18840 +       __u8    nexthdr;
18841 +       __u8    hdrlen;
18842 +       __u16   reserved;
18843         __u32   spi;
18844 +       __u32   seq_no;
18845  };
18846  
18847  /* Returns 1 if the spi is matched by the range, 0 otherwise */
18848 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_condition.c linux-2.4.20/net/ipv4/netfilter/ipt_condition.c
18849 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_condition.c Thu Jan  1 00:00:00 1970
18850 +++ linux-2.4.20/net/ipv4/netfilter/ipt_condition.c     Wed Sep 24 09:17:34 2003
18851 @@ -0,0 +1,256 @@
18852 +/*-------------------------------------------*\
18853 +|          Netfilter Condition Module         |
18854 +|                                             |
18855 +|  Description: This module allows firewall   |
18856 +|    rules to match using condition variables |
18857 +|    stored in /proc files.                   |
18858 +|                                             |
18859 +|  Author: Stephane Ouellette     2002-10-22  |
18860 +|          <ouellettes@videotron.ca>          |
18861 +|                                             |
18862 +|  History:                                   |
18863 +|    2003-02-10  Second version with improved |
18864 +|                locking and simplified code. |
18865 +|                                             |
18866 +|  This software is distributed under the     |
18867 +|  terms of the GNU GPL.                      |
18868 +\*-------------------------------------------*/
18869 +
18870 +#include<linux/module.h>
18871 +#include<linux/proc_fs.h>
18872 +#include<linux/spinlock.h>
18873 +#include<linux/string.h>
18874 +#include<asm/atomic.h>
18875 +#include<linux/netfilter_ipv4/ip_tables.h>
18876 +#include<linux/netfilter_ipv4/ipt_condition.h>
18877 +
18878 +
18879 +#ifndef CONFIG_PROC_FS
18880 +#error  "Proc file system support is required for this module"
18881 +#endif
18882 +
18883 +
18884 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
18885 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
18886 +MODULE_LICENSE("GPL");
18887 +
18888 +
18889 +struct condition_variable {
18890 +       struct condition_variable *next;
18891 +       struct proc_dir_entry *status_proc;
18892 +       atomic_t refcount;
18893 +        int enabled;   /* TRUE == 1, FALSE == 0 */
18894 +};
18895 +
18896 +
18897 +static rwlock_t list_lock;
18898 +static struct condition_variable *head = NULL;
18899 +static struct proc_dir_entry *proc_net_condition = NULL;
18900 +
18901 +
18902 +static int
18903 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
18904 +                       int length, int *eof, void *data)
18905 +{
18906 +       struct condition_variable *var =
18907 +           (struct condition_variable *) data;
18908 +
18909 +       if (offset == 0) {
18910 +               *start = buffer;
18911 +               buffer[0] = (var->enabled) ? '1' : '0';
18912 +               buffer[1] = '\n';
18913 +               return 2;
18914 +       }
18915 +
18916 +       *eof = 1;
18917 +       return 0;
18918 +}
18919 +
18920 +
18921 +static int
18922 +ipt_condition_write_info(struct file *file, const char *buffer,
18923 +                        unsigned long length, void *data)
18924 +{
18925 +       struct condition_variable *var =
18926 +           (struct condition_variable *) data;
18927 +
18928 +       if (length) {
18929 +               /* Match only on the first character */
18930 +               switch (buffer[0]) {
18931 +               case '0':
18932 +                       var->enabled = 0;
18933 +                       break;
18934 +               case '1':
18935 +                       var->enabled = 1;
18936 +               }
18937 +       }
18938 +
18939 +       return (int) length;
18940 +}
18941 +
18942 +
18943 +static int
18944 +match(const struct sk_buff *skb, const struct net_device *in,
18945 +      const struct net_device *out, const void *matchinfo, int offset,
18946 +      const void *hdr, u_int16_t datalen, int *hotdrop)
18947 +{
18948 +       const struct condition_info *info =
18949 +           (const struct condition_info *) matchinfo;
18950 +       struct condition_variable *var;
18951 +       int condition_status = 0;
18952 +
18953 +       read_lock(&list_lock);
18954 +
18955 +       for (var = head; var; var = var->next) {
18956 +               if (strcmp(info->name, var->status_proc->name) == 0) {
18957 +                       condition_status = var->enabled;
18958 +                       break;
18959 +               }
18960 +       }
18961 +
18962 +       read_unlock(&list_lock);
18963 +
18964 +       return condition_status ^ info->invert;
18965 +}
18966 +
18967 +
18968 +
18969 +static int
18970 +checkentry(const char *tablename, const struct ipt_ip *ip,
18971 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
18972 +{
18973 +       struct condition_info *info = (struct condition_info *) matchinfo;
18974 +       struct condition_variable *var, *newvar;
18975 +
18976 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
18977 +               return 0;
18978 +
18979 +       /* The first step is to check if the condition variable already exists. */
18980 +       /* Here, a read lock is sufficient because we won't change the list */
18981 +       read_lock(&list_lock);
18982 +
18983 +       for (var = head; var; var = var->next) {
18984 +               if (strcmp(info->name, var->status_proc->name) == 0) {
18985 +                       atomic_inc(&var->refcount);
18986 +                       read_unlock(&list_lock);
18987 +                       return 1;
18988 +               }
18989 +       }
18990 +
18991 +       read_unlock(&list_lock);
18992 +
18993 +       /* At this point, we need to allocate a new condition variable */
18994 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
18995 +
18996 +       if (!newvar)
18997 +               return -ENOMEM;
18998 +
18999 +       /* Create the condition variable's proc file entry */
19000 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19001 +
19002 +       if (!newvar->status_proc) {
19003 +         /*
19004 +          * There are two possibilities:
19005 +          *  1- Another condition variable with the same name has been created, which is valid.
19006 +          *  2- There was a memory allocation error.
19007 +          */
19008 +               kfree(newvar);
19009 +               read_lock(&list_lock);
19010 +
19011 +               for (var = head; var; var = var->next) {
19012 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
19013 +                               atomic_inc(&var->refcount);
19014 +                               read_unlock(&list_lock);
19015 +                               return 1;
19016 +                       }
19017 +               }
19018 +
19019 +               read_unlock(&list_lock);
19020 +               return -ENOMEM;
19021 +       }
19022 +
19023 +       atomic_set(&newvar->refcount, 1);
19024 +       newvar->enabled = 0;
19025 +       newvar->status_proc->owner = THIS_MODULE;
19026 +       newvar->status_proc->data = newvar;
19027 +       wmb();
19028 +       newvar->status_proc->read_proc = ipt_condition_read_info;
19029 +       newvar->status_proc->write_proc = ipt_condition_write_info;
19030 +
19031 +       write_lock(&list_lock);
19032 +
19033 +       newvar->next = head;
19034 +       head = newvar;
19035 +
19036 +       write_unlock(&list_lock);
19037 +
19038 +       return 1;
19039 +}
19040 +
19041 +
19042 +static void
19043 +destroy(void *matchinfo, unsigned int matchsize)
19044 +{
19045 +       struct condition_info *info = (struct condition_info *) matchinfo;
19046 +       struct condition_variable *var, *prev = NULL;
19047 +
19048 +       if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
19049 +               return;
19050 +
19051 +       write_lock(&list_lock);
19052 +
19053 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
19054 +            prev = var, var = var->next);
19055 +
19056 +       if (var && atomic_dec_and_test(&var->refcount)) {
19057 +               if (prev)
19058 +                       prev->next = var->next;
19059 +               else
19060 +                       head = var->next;
19061 +
19062 +               write_unlock(&list_lock);
19063 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
19064 +               kfree(var);
19065 +       } else
19066 +               write_unlock(&list_lock);
19067 +}
19068 +
19069 +
19070 +static struct ipt_match condition_match = {
19071 +       .name = "condition",
19072 +       .match = &match,
19073 +       .checkentry = &checkentry,
19074 +       .destroy = &destroy,
19075 +       .me = THIS_MODULE
19076 +};
19077 +
19078 +
19079 +static int __init
19080 +init(void)
19081 +{
19082 +       int errorcode;
19083 +
19084 +       rwlock_init(&list_lock);
19085 +       proc_net_condition = proc_mkdir("ipt_condition", proc_net);
19086 +
19087 +       if (proc_net_condition) {
19088 +               errorcode = ipt_register_match(&condition_match);
19089 +
19090 +               if (errorcode)
19091 +                       remove_proc_entry("ipt_condition", proc_net);
19092 +       } else
19093 +               errorcode = -EACCES;
19094 +
19095 +       return errorcode;
19096 +}
19097 +
19098 +
19099 +static void __exit
19100 +fini(void)
19101 +{
19102 +       ipt_unregister_match(&condition_match);
19103 +       remove_proc_entry("ipt_condition", proc_net);
19104 +}
19105 +
19106 +module_init(init);
19107 +module_exit(fini);
19108 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_connlimit.c linux-2.4.20/net/ipv4/netfilter/ipt_connlimit.c
19109 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_connlimit.c Thu Jan  1 00:00:00 1970
19110 +++ linux-2.4.20/net/ipv4/netfilter/ipt_connlimit.c     Wed Sep 24 09:16:42 2003
19111 @@ -0,0 +1,232 @@
19112 +/*
19113 + * netfilter module to limit the number of parallel tcp
19114 + * connections per IP address.
19115 + *   (c) 2000 Gerd Knorr <kraxel@bytesex.org>
19116 + *   Nov 2002: Martin Bene <martin.bene@icomedias.com>:
19117 + *             only ignore TIME_WAIT or gone connections
19118 + *
19119 + * based on ...
19120 + *
19121 + * Kernel module to match connection tracking information.
19122 + * GPL (C) 1999  Rusty Russell (rusty@rustcorp.com.au).
19123 + */
19124 +#include <linux/module.h>
19125 +#include <linux/skbuff.h>
19126 +#include <linux/list.h>
19127 +#include <linux/netfilter_ipv4/ip_conntrack.h>
19128 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
19129 +#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
19130 +#include <linux/netfilter_ipv4/ip_tables.h>
19131 +#include <linux/netfilter_ipv4/ipt_connlimit.h>
19132 +
19133 +#define DEBUG 0
19134 +
19135 +MODULE_LICENSE("GPL");
19136 +
19137 +/* we'll save the tuples of all connections we care about */
19138 +struct ipt_connlimit_conn
19139 +{
19140 +        struct list_head list;
19141 +       struct ip_conntrack_tuple tuple;
19142 +};
19143 +
19144 +struct ipt_connlimit_data {
19145 +       spinlock_t lock;
19146 +       struct list_head iphash[256];
19147 +};
19148 +
19149 +static int ipt_iphash(u_int32_t addr)
19150 +{
19151 +       int hash;
19152 +
19153 +       hash  =  addr        & 0xff;
19154 +       hash ^= (addr >>  8) & 0xff;
19155 +       hash ^= (addr >> 16) & 0xff;
19156 +       hash ^= (addr >> 24) & 0xff;
19157 +       return hash;
19158 +}
19159 +
19160 +static int count_them(struct ipt_connlimit_data *data,
19161 +                     u_int32_t addr, u_int32_t mask,
19162 +                     struct ip_conntrack *ct)
19163 +{
19164 +#if DEBUG
19165 +       const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
19166 +                                    "fin_wait", "time_wait", "close", "close_wait",
19167 +                                    "last_ack", "listen" };
19168 +#endif
19169 +       int addit = 1, matches = 0;
19170 +       struct ip_conntrack_tuple tuple;
19171 +       struct ip_conntrack_tuple_hash *found;
19172 +       struct ipt_connlimit_conn *conn;
19173 +       struct list_head *hash,*lh;
19174 +
19175 +       spin_lock(&data->lock);
19176 +       tuple = ct->tuplehash[0].tuple;
19177 +       hash = &data->iphash[ipt_iphash(addr & mask)];
19178 +
19179 +       /* check the saved connections */
19180 +       for (lh = hash->next; lh != hash; lh = lh->next) {
19181 +               conn = list_entry(lh,struct ipt_connlimit_conn,list);
19182 +               found = ip_conntrack_find_get(&conn->tuple,ct);
19183 +               if (0 == memcmp(&conn->tuple,&tuple,sizeof(tuple)) &&
19184 +                   found != NULL &&
19185 +                   found->ctrack->proto.tcp.state != TCP_CONNTRACK_TIME_WAIT) {
19186 +                       /* Just to be sure we have it only once in the list.
19187 +                          We should'nt see tuples twice unless someone hooks this
19188 +                          into a table without "-p tcp --syn" */
19189 +                       addit = 0;
19190 +               }
19191 +#if DEBUG
19192 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d %s\n",
19193 +                      ipt_iphash(addr & mask),
19194 +                      NIPQUAD(conn->tuple.src.ip), ntohs(conn->tuple.src.u.tcp.port),
19195 +                      NIPQUAD(conn->tuple.dst.ip), ntohs(conn->tuple.dst.u.tcp.port),
19196 +                      (NULL != found) ? tcp[found->ctrack->proto.tcp.state] : "gone");
19197 +#endif
19198 +               if (NULL == found) {
19199 +                       /* this one is gone */
19200 +                       lh = lh->prev;
19201 +                       list_del(lh->next);
19202 +                       kfree(conn);
19203 +                       continue;
19204 +               }
19205 +               if (found->ctrack->proto.tcp.state == TCP_CONNTRACK_TIME_WAIT) {
19206 +                       /* we don't care about connections which are
19207 +                          closed already -> ditch it */
19208 +                       lh = lh->prev;
19209 +                       list_del(lh->next);
19210 +                       kfree(conn);
19211 +                       nf_conntrack_put(&found->ctrack->infos[0]);
19212 +                       continue;
19213 +               }
19214 +               if ((addr & mask) == (conn->tuple.src.ip & mask)) {
19215 +                       /* same source IP address -> be counted! */
19216 +                       matches++;
19217 +               }
19218 +               nf_conntrack_put(&found->ctrack->infos[0]);
19219 +       }
19220 +       if (addit) {
19221 +               /* save the new connection in our list */
19222 +#if DEBUG
19223 +               printk("ipt_connlimit [%d]: src=%u.%u.%u.%u:%d dst=%u.%u.%u.%u:%d new\n",
19224 +                      ipt_iphash(addr & mask),
19225 +                      NIPQUAD(tuple.src.ip), ntohs(tuple.src.u.tcp.port),
19226 +                      NIPQUAD(tuple.dst.ip), ntohs(tuple.dst.u.tcp.port));
19227 +#endif
19228 +               conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
19229 +               if (NULL == conn)
19230 +                       return -1;
19231 +               memset(conn,0,sizeof(*conn));
19232 +               INIT_LIST_HEAD(&conn->list);
19233 +               conn->tuple = tuple;
19234 +               list_add(&conn->list,hash);
19235 +               matches++;
19236 +       }
19237 +       spin_unlock(&data->lock);
19238 +       return matches;
19239 +}
19240 +
19241 +static int
19242 +match(const struct sk_buff *skb,
19243 +      const struct net_device *in,
19244 +      const struct net_device *out,
19245 +      const void *matchinfo,
19246 +      int offset,
19247 +      const void *hdr,
19248 +      u_int16_t datalen,
19249 +      int *hotdrop)
19250 +{
19251 +       const struct ipt_connlimit_info *info = matchinfo;
19252 +       int connections, match;
19253 +       struct ip_conntrack *ct;
19254 +       enum ip_conntrack_info ctinfo;
19255 +
19256 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
19257 +       if (NULL == ct) {
19258 +               printk("ipt_connlimit: Oops: invalid ct state ?\n");
19259 +               *hotdrop = 1;
19260 +               return 0;
19261 +       }
19262 +       connections = count_them(info->data,skb->nh.iph->saddr,info->mask,ct);
19263 +       if (-1 == connections) {
19264 +               printk("ipt_connlimit: Hmm, kmalloc failed :-(\n");
19265 +               *hotdrop = 1; /* let's free some memory :-) */
19266 +               return 0;
19267 +       }
19268 +        match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
19269 +#if DEBUG
19270 +       printk("ipt_connlimit: src=%u.%u.%u.%u mask=%u.%u.%u.%u "
19271 +              "connections=%d limit=%d match=%s\n",
19272 +              NIPQUAD(skb->nh.iph->saddr), NIPQUAD(info->mask),
19273 +              connections, info->limit, match ? "yes" : "no");
19274 +#endif
19275 +
19276 +       return match;
19277 +}
19278 +
19279 +static int check(const char *tablename,
19280 +                const struct ipt_ip *ip,
19281 +                void *matchinfo,
19282 +                unsigned int matchsize,
19283 +                unsigned int hook_mask)
19284 +{
19285 +       struct ipt_connlimit_info *info = matchinfo;
19286 +       int i;
19287 +
19288 +       /* verify size */
19289 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
19290 +               return 0;
19291 +
19292 +       /* refuse anything but tcp */
19293 +       if (ip->proto != IPPROTO_TCP)
19294 +               return 0;
19295 +
19296 +       /* init private data */
19297 +       info->data = kmalloc(sizeof(struct ipt_connlimit_data),GFP_KERNEL);
19298 +       spin_lock_init(&(info->data->lock));
19299 +       for (i = 0; i < 256; i++)
19300 +               INIT_LIST_HEAD(&(info->data->iphash[i]));
19301 +       
19302 +       return 1;
19303 +}
19304 +
19305 +static void destroy(void *matchinfo, unsigned int matchinfosize)
19306 +{
19307 +       struct ipt_connlimit_info *info = matchinfo;
19308 +       struct ipt_connlimit_conn *conn;
19309 +       struct list_head *hash;
19310 +       int i;
19311 +
19312 +       /* cleanup */
19313 +       for (i = 0; i < 256; i++) {
19314 +               hash = &(info->data->iphash[i]);
19315 +               while (hash != hash->next) {
19316 +                       conn = list_entry(hash->next,struct ipt_connlimit_conn,list);
19317 +                       list_del(hash->next);
19318 +                       kfree(conn);
19319 +               }
19320 +       }
19321 +       kfree(info->data);
19322 +}
19323 +
19324 +static struct ipt_match connlimit_match
19325 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
19326 +
19327 +static int __init init(void)
19328 +{
19329 +       /* NULL if ip_conntrack not a module */
19330 +       if (ip_conntrack_module)
19331 +               __MOD_INC_USE_COUNT(ip_conntrack_module);
19332 +       return ipt_register_match(&connlimit_match);
19333 +}
19334 +
19335 +static void __exit fini(void)
19336 +{
19337 +       ipt_unregister_match(&connlimit_match);
19338 +       if (ip_conntrack_module)
19339 +               __MOD_DEC_USE_COUNT(ip_conntrack_module);
19340 +}
19341 +
19342 +module_init(init);
19343 +module_exit(fini);
19344 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_connmark.c linux-2.4.20/net/ipv4/netfilter/ipt_connmark.c
19345 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_connmark.c  Thu Jan  1 00:00:00 1970
19346 +++ linux-2.4.20/net/ipv4/netfilter/ipt_connmark.c      Wed Sep 24 09:17:17 2003
19347 @@ -0,0 +1,55 @@
19348 +/* Kernel module to match connection mark values. */
19349 +#include <linux/module.h>
19350 +#include <linux/skbuff.h>
19351 +
19352 +#include <linux/netfilter_ipv4/ip_tables.h>
19353 +#include <linux/netfilter_ipv4/ipt_connmark.h>
19354 +#include <linux/netfilter_ipv4/ip_conntrack.h>
19355 +
19356 +static int
19357 +match(const struct sk_buff *skb,
19358 +      const struct net_device *in,
19359 +      const struct net_device *out,
19360 +      const void *matchinfo,
19361 +      int offset,
19362 +      const void *hdr,
19363 +      u_int16_t datalen,
19364 +      int *hotdrop)
19365 +{
19366 +       const struct ipt_connmark_info *info = matchinfo;
19367 +       enum ip_conntrack_info ctinfo;
19368 +       struct ip_conntrack *ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
19369 +       if (!ct)
19370 +           return 0;
19371 +
19372 +       return ((ct->mark & info->mask) == info->mark) ^ info->invert;
19373 +}
19374 +
19375 +static int
19376 +checkentry(const char *tablename,
19377 +           const struct ipt_ip *ip,
19378 +           void *matchinfo,
19379 +           unsigned int matchsize,
19380 +           unsigned int hook_mask)
19381 +{
19382 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
19383 +               return 0;
19384 +
19385 +       return 1;
19386 +}
19387 +
19388 +static struct ipt_match connmark_match
19389 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
19390 +
19391 +static int __init init(void)
19392 +{
19393 +       return ipt_register_match(&connmark_match);
19394 +}
19395 +
19396 +static void __exit fini(void)
19397 +{
19398 +       ipt_unregister_match(&connmark_match);
19399 +}
19400 +
19401 +module_init(init);
19402 +module_exit(fini);
19403 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_conntrack.c linux-2.4.20/net/ipv4/netfilter/ipt_conntrack.c
19404 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_conntrack.c Thu Nov 28 23:53:15 2002
19405 +++ linux-2.4.20/net/ipv4/netfilter/ipt_conntrack.c     Wed Sep 24 09:18:12 2003
19406 @@ -27,7 +27,13 @@
19407  
19408  #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
19409  
19410 -       statebit = ct ? IPT_CONNTRACK_STATE_INVALID : IPT_CONNTRACK_STATE_BIT(ctinfo);
19411 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
19412 +               statebit = IPT_CONNTRACK_STATE_UNTRACKED;
19413 +       else if (ct)
19414 +               statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
19415 +       else
19416 +               statebit = IPT_CONNTRACK_STATE_INVALID;
19417
19418         if(sinfo->flags & IPT_CONNTRACK_STATE) {
19419                 if (ct) {
19420                         if(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip !=
19421 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_esp.c linux-2.4.20/net/ipv4/netfilter/ipt_esp.c
19422 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_esp.c       Mon Feb 25 19:38:14 2002
19423 +++ linux-2.4.20/net/ipv4/netfilter/ipt_esp.c   Wed Sep 24 09:16:18 2003
19424 @@ -16,6 +16,7 @@
19425  
19426  struct esphdr {
19427         __u32   spi;
19428 +       __u32   seq_no;
19429  };
19430  
19431  /* Returns 1 if the spi is matched by the range, 0 otherwise */
19432 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_fuzzy.c linux-2.4.20/net/ipv4/netfilter/ipt_fuzzy.c
19433 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_fuzzy.c     Thu Jan  1 00:00:00 1970
19434 +++ linux-2.4.20/net/ipv4/netfilter/ipt_fuzzy.c Wed Sep 24 09:16:44 2003
19435 @@ -0,0 +1,190 @@
19436 +/*
19437 + *  This module implements a simple TSK FLC 
19438 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
19439 + * to limit , in an adaptive and flexible way , the packet rate crossing 
19440 + * a given stream . It serves as an initial and very simple (but effective)
19441 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
19442 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"  
19443 + * into our code in a precise , adaptive and efficient manner. 
19444 + *  The goal is very similar to that of "limit" match , but using techniques of
19445 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
19446 + * avoiding over and undershoots - and stuff like that .
19447 + *
19448 + *
19449 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
19450 + * 2002-08-17  : Changed to eliminate floating point operations .
19451 + * 2002-08-23  : Coding style changes .
19452 +*/
19453 +
19454 +#include <linux/module.h>
19455 +#include <linux/skbuff.h>
19456 +#include <linux/ip.h>
19457 +#include <linux/random.h>
19458 +#include <net/tcp.h>
19459 +#include <linux/spinlock.h>
19460 +#include <linux/netfilter_ipv4/ip_tables.h>
19461 +#include <linux/netfilter_ipv4/ipt_fuzzy.h>
19462 +
19463 +/*
19464 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19465 + Expressed in percentage
19466 +*/
19467 +
19468 +#define PAR_LOW                1/100
19469 +#define PAR_HIGH       1
19470 +
19471 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
19472 +
19473 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
19474 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
19475 +MODULE_LICENSE("GPL");
19476 +
19477 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19478 +{
19479 +       if (tx >= maxi) return 100;
19480 +
19481 +       if (tx <= mini) return 0;
19482 +
19483 +       return ( (100*(tx-mini)) / (maxi-mini) ) ;
19484 +}
19485 +
19486 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19487 +{
19488 +       if (tx <= mini) return 100;
19489 +
19490 +       if (tx >= maxi) return 0;
19491 +
19492 +       return ( (100*( maxi - tx ))  / ( maxi - mini ) ) ;
19493 +
19494 +}
19495 +
19496 +static int
19497 +ipt_fuzzy_match(const struct sk_buff *pskb,
19498 +              const struct net_device *in,
19499 +              const struct net_device *out,
19500 +              const void *matchinfo,
19501 +              int offset,
19502 +              const void *hdr,
19503 +              u_int16_t datalen,
19504 +              int *hotdrop)
19505 +{
19506 +       /* From userspace */
19507 +       
19508 +       struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
19509 +
19510 +       u_int8_t random_number;
19511 +       unsigned long amount ;
19512 +       u_int8_t howhigh , howlow ;
19513 +       
19514 +
19515 +       spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
19516 +
19517 +       info->bytes_total += pskb->len ;
19518 +       info->packets_total++ ;
19519 +
19520 +       info->present_time = jiffies ;
19521 +       
19522 +       if ( info->present_time >= info->previous_time )
19523 +               amount = info->present_time - info->previous_time ;
19524 +       else { 
19525 +               /* There was a transition : I choose to re-sample 
19526 +                  and keep the old acceptance rate...
19527 +               */
19528 +
19529 +               amount = 0 ;
19530 +               info->previous_time = info->present_time ;
19531 +               info->bytes_total = info->packets_total = 0;
19532 +            };
19533 +       
19534 +       if (  amount > HZ/10 ) /* More than 100 ms elapsed ... */
19535 +               {
19536 +
19537 +       info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total )  \
19538 +                                       / amount ) ;
19539 +
19540 +               info->previous_time = info->present_time ;
19541 +               info->bytes_total = info->packets_total = 0 ;
19542 +
19543 +       howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
19544 +       howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
19545 +
19546 +    info->acceptance_rate = (u_int8_t) \
19547 +                          ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
19548 +
19549 +    /* In fact , the above defuzzification would require a denominator
19550 +       proportional to (howhigh+howlow) but , in this particular case ,
19551 +       that expression is constant .
19552 +        An imediate consequence is that it isn't necessary to call 
19553 +       both mf_high and mf_low - but to keep things understandable ,
19554 +       I did so .
19555 +     */ 
19556 +
19557 +               }
19558 +       
19559 +       spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
19560 +
19561 +
19562 +       if ( info->acceptance_rate < 100 )
19563 +       {                
19564 +               get_random_bytes((void *)(&random_number), 1);
19565 +
19566 +               /*  If within the acceptance , it can pass => don't match */
19567 +               if ( random_number <= (255 * info->acceptance_rate) / 100 )
19568 +                       return 0 ;
19569 +               else
19570 +                       return 1; /* It can't pass ( It matches ) */
19571 +       } ;
19572 +
19573 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
19574 +       
19575 +}
19576 +
19577 +static int
19578 +ipt_fuzzy_checkentry(const char *tablename,
19579 +                  const struct ipt_ip *e,
19580 +                  void *matchinfo,
19581 +                  unsigned int matchsize,
19582 +                  unsigned int hook_mask)
19583 +{
19584 +       
19585 +       const struct ipt_fuzzy_info *info = matchinfo;
19586 +
19587 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_fuzzy_info))) {
19588 +               printk("ipt_fuzzy: matchsize %u != %u\n", matchsize,
19589 +                      IPT_ALIGN(sizeof(struct ipt_fuzzy_info)));
19590 +               return 0;
19591 +       }
19592 +
19593 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
19594 +       || (info->minimum_rate >= info->maximum_rate ))
19595 +               {
19596 +               printk("ipt_fuzzy: BAD limits , please verify !!!\n");
19597 +               return 0;
19598 +               }
19599 +
19600 +       return 1;
19601 +}
19602 +
19603 +static struct ipt_match ipt_fuzzy_reg = { 
19604 +       {NULL, NULL},
19605 +       "fuzzy",
19606 +       ipt_fuzzy_match,
19607 +       ipt_fuzzy_checkentry,
19608 +       NULL,
19609 +       THIS_MODULE };
19610 +
19611 +static int __init init(void)
19612 +{
19613 +       if (ipt_register_match(&ipt_fuzzy_reg))
19614 +               return -EINVAL;
19615 +
19616 +       return 0;
19617 +}
19618 +
19619 +static void __exit fini(void)
19620 +{
19621 +       ipt_unregister_match(&ipt_fuzzy_reg);
19622 +}
19623 +
19624 +module_init(init);
19625 +module_exit(fini);
19626 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_helper.c linux-2.4.20/net/ipv4/netfilter/ipt_helper.c
19627 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_helper.c    Thu Nov 28 23:53:15 2002
19628 +++ linux-2.4.20/net/ipv4/netfilter/ipt_helper.c        Wed Sep 24 09:16:17 2003
19629 @@ -10,6 +10,7 @@
19630  #include <linux/module.h>
19631  #include <linux/skbuff.h>
19632  #include <linux/netfilter_ipv4/ip_conntrack.h>
19633 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
19634  #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
19635  #include <linux/netfilter_ipv4/ip_tables.h>
19636  #include <linux/netfilter_ipv4/ipt_helper.h>
19637 @@ -36,6 +37,7 @@
19638         struct ip_conntrack_expect *exp;
19639         struct ip_conntrack *ct;
19640         enum ip_conntrack_info ctinfo;
19641 +       int ret = 0;
19642         
19643         ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
19644         if (!ct) {
19645 @@ -49,23 +51,27 @@
19646         }
19647  
19648         exp = ct->master;
19649 +       READ_LOCK(&ip_conntrack_lock);
19650         if (!exp->expectant) {
19651                 DEBUGP("ipt_helper: expectation %p without expectant !?!\n", 
19652                         exp);
19653 -               return 0;
19654 +               goto out_unlock;
19655         }
19656  
19657         if (!exp->expectant->helper) {
19658                 DEBUGP("ipt_helper: master ct %p has no helper\n", 
19659                         exp->expectant);
19660 -               return 0;
19661 +               goto out_unlock;
19662         }
19663  
19664         DEBUGP("master's name = %s , info->name = %s\n", 
19665                 exp->expectant->helper->name, info->name);
19666  
19667 -       return !strncmp(exp->expectant->helper->name, info->name, 
19668 -                       strlen(exp->expectant->helper->name)) ^ info->invert;
19669 +       ret = !strncmp(exp->expectant->helper->name, info->name, 
19670 +                      strlen(exp->expectant->helper->name)) ^ info->invert;
19671 +out_unlock:
19672 +       READ_UNLOCK(&ip_conntrack_lock);
19673 +       return ret;
19674  }
19675  
19676  static int check(const char *tablename,
19677 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_iprange.c linux-2.4.20/net/ipv4/netfilter/ipt_iprange.c
19678 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_iprange.c   Thu Jan  1 00:00:00 1970
19679 +++ linux-2.4.20/net/ipv4/netfilter/ipt_iprange.c       Wed Sep 24 09:16:47 2003
19680 @@ -0,0 +1,101 @@
19681 +/*
19682 + * iptables module to match IP address ranges
19683 + *   (c) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
19684 + *
19685 + * Released under the terms of GNU GPLv2.
19686 + *
19687 + */
19688 +#include <linux/module.h>
19689 +#include <linux/skbuff.h>
19690 +#include <linux/ip.h>
19691 +#include <linux/netfilter_ipv4/ip_tables.h>
19692 +#include <linux/netfilter_ipv4/ipt_iprange.h>
19693 +
19694 +MODULE_LICENSE("GPL");
19695 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
19696 +MODULE_DESCRIPTION("iptables arbitrary IP range match module");
19697 +
19698 +#if 0
19699 +#define DEBUGP printk
19700 +#else
19701 +#define DEBUGP(format, args...)
19702 +#endif
19703 +
19704 +static int
19705 +match(const struct sk_buff *skb,
19706 +      const struct net_device *in,
19707 +      const struct net_device *out,
19708 +      const void *matchinfo,
19709 +      int offset,
19710 +      const void *hdr,
19711 +      u_int16_t datalen,
19712 +      int *hotdrop)
19713 +{
19714 +       const struct ipt_iprange_info *info = matchinfo;
19715 +       const struct iphdr *iph = skb->nh.iph;
19716 +       
19717 +
19718 +       if (info->flags & IPRANGE_SRC) {
19719 +               if (((ntohl(iph->saddr) < ntohl(info->src.min_ip))
19720 +                         || (ntohl(iph->saddr) > ntohl(info->src.max_ip)))
19721 +                        ^ !!(info->flags & IPRANGE_SRC_INV)) {
19722 +                       DEBUGP("src IP %u.%u.%u.%u NOT in range %s"
19723 +                              "%u.%u.%u.%u-%u.%u.%u.%u\n",
19724 +                               NIPQUAD(iph->saddr),
19725 +                               info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
19726 +                               NIPQUAD(info->src.min_ip),
19727 +                               NIPQUAD(info->src.max_ip));
19728 +                       return 0;
19729 +               }
19730 +       }
19731 +       if (info->flags & IPRANGE_DST) {
19732 +               if (((ntohl(iph->daddr) < ntohl(info->dst.min_ip))
19733 +                         || (ntohl(iph->daddr) > ntohl(info->dst.max_ip)))
19734 +                        ^ !!(info->flags & IPRANGE_DST_INV)) {
19735 +                       DEBUGP("dst IP %u.%u.%u.%u NOT in range %s"
19736 +                              "%u.%u.%u.%u-%u.%u.%u.%u\n",
19737 +                               NIPQUAD(iph->daddr),
19738 +                               info->flags & IPRANGE_DST_INV ? "(INV) " : "",
19739 +                               NIPQUAD(info->dst.min_ip),
19740 +                               NIPQUAD(info->dst.max_ip));
19741 +                       return 0;
19742 +               }
19743 +       }
19744 +       return 1;
19745 +}
19746 +
19747 +static int check(const char *tablename,
19748 +                const struct ipt_ip *ip,
19749 +                void *matchinfo,
19750 +                unsigned int matchsize,
19751 +                unsigned int hook_mask)
19752 +{
19753 +       /* verify size */
19754 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_iprange_info)))
19755 +               return 0;
19756 +
19757 +       return 1;
19758 +}
19759 +
19760 +static struct ipt_match iprange_match = 
19761 +{ 
19762 +       .list = { NULL, NULL }, 
19763 +       .name = "iprange", 
19764 +       .match = &match, 
19765 +       .checkentry = &check, 
19766 +       .destroy = NULL, 
19767 +       .me = THIS_MODULE
19768 +};
19769 +
19770 +static int __init init(void)
19771 +{
19772 +       return ipt_register_match(&iprange_match);
19773 +}
19774 +
19775 +static void __exit fini(void)
19776 +{
19777 +       ipt_unregister_match(&iprange_match);
19778 +}
19779 +
19780 +module_init(init);
19781 +module_exit(fini);
19782 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_ipv4options.c linux-2.4.20/net/ipv4/netfilter/ipt_ipv4options.c
19783 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_ipv4options.c       Thu Jan  1 00:00:00 1970
19784 +++ linux-2.4.20/net/ipv4/netfilter/ipt_ipv4options.c   Wed Sep 24 09:16:49 2003
19785 @@ -0,0 +1,170 @@
19786 +/*
19787 +  This is a module which is used to match ipv4 options.
19788 +  This file is distributed under the terms of the GNU General Public
19789 +  License (GPL). Copies of the GPL can be obtained from:
19790 +  ftp://prep.ai.mit.edu/pub/gnu/GPL
19791 +
19792 +  11-mars-2001 Fabrice MARIE <fabrice@netfilter.org> : initial development.
19793 +  12-july-2001 Fabrice MARIE <fabrice@netfilter.org> : added router-alert otions matching. Fixed a bug with no-srr
19794 +  12-august-2001 Imran Patel <ipatel@crosswinds.net> : optimization of the match.
19795 +  18-november-2001 Fabrice MARIE <fabrice@netfilter.org> : added [!] 'any' option match.
19796 +*/
19797 +
19798 +#include <linux/module.h>
19799 +#include <linux/skbuff.h>
19800 +#include <net/ip.h>
19801 +
19802 +#include <linux/netfilter_ipv4/ip_tables.h>
19803 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
19804 +
19805 +MODULE_LICENSE("GPL");
19806 +
19807 +static int
19808 +match(const struct sk_buff *skb,
19809 +      const struct net_device *in,
19810 +      const struct net_device *out,
19811 +      const void *matchinfo,
19812 +      int offset,
19813 +      const void *hdr,
19814 +      u_int16_t datalen,
19815 +      int *hotdrop)
19816 +{
19817 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
19818 +       const struct iphdr *iph = skb->nh.iph;
19819 +       const struct ip_options *opt;
19820 +
19821 +       if (iph->ihl * 4 == sizeof(struct iphdr)) {
19822 +               /* No options, so we match only the "DONTs" and the "IGNOREs" */
19823 +
19824 +               if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) ||
19825 +                   ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
19826 +                   ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
19827 +                   ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
19828 +                   ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
19829 +                    ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT))
19830 +                       return 0;
19831 +               return 1;
19832 +       }
19833 +       else {
19834 +               if ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)
19835 +                       /* there are options, and we don't need to care which one */
19836 +                       return 1;
19837 +               else {
19838 +                       if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)
19839 +                               /* there are options but we don't want any ! */
19840 +                               return 0;
19841 +               }
19842 +       }
19843 +
19844 +       opt = &(IPCB(skb)->opt);
19845 +
19846 +       /* source routing */
19847 +       if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
19848 +               if (!((opt->srr) & (opt->is_strictroute)))
19849 +                       return 0;
19850 +       }
19851 +       else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
19852 +               if (!((opt->srr) & (!opt->is_strictroute)))
19853 +                       return 0;
19854 +       }
19855 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
19856 +               if (opt->srr)
19857 +                       return 0;
19858 +       }
19859 +       /* record route */
19860 +       if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
19861 +               if (!opt->rr)
19862 +                       return 0;
19863 +       }
19864 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
19865 +               if (opt->rr)
19866 +                       return 0;
19867 +       }
19868 +       /* timestamp */
19869 +       if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
19870 +               if (!opt->ts)
19871 +                       return 0;
19872 +       }
19873 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
19874 +               if (opt->ts)
19875 +                       return 0;
19876 +       }
19877 +       /* router-alert option  */
19878 +       if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
19879 +               if (!opt->router_alert)
19880 +                       return 0;
19881 +       }
19882 +       else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
19883 +               if (opt->router_alert)
19884 +                       return 0;
19885 +       }
19886 +
19887 +       /* we match ! */
19888 +       return 1;
19889 +}
19890 +
19891 +static int
19892 +checkentry(const char *tablename,
19893 +          const struct ipt_ip *ip,
19894 +          void *matchinfo,
19895 +          unsigned int matchsize,
19896 +          unsigned int hook_mask)
19897 +{
19898 +       const struct ipt_ipv4options_info *info = matchinfo;   /* match info for rule */
19899 +       /* Check the size */
19900 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_ipv4options_info)))
19901 +               return 0;
19902 +       /* Now check the coherence of the data ... */
19903 +       if (((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT) &&
19904 +           (((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) ||
19905 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) ||
19906 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) ||
19907 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) ||
19908 +            ((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT)))
19909 +               return 0; /* opposites */
19910 +       if (((info->options & IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) == IPT_IPV4OPTION_DONT_MATCH_ANY_OPT) &&
19911 +           (((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) ||
19912 +            ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
19913 +            ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) ||
19914 +            ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) ||
19915 +            ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) ||
19916 +            ((info->options & IPT_IPV4OPTION_MATCH_ANY_OPT) == IPT_IPV4OPTION_MATCH_ANY_OPT)))
19917 +               return 0; /* opposites */
19918 +       if (((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) &&
19919 +           ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR))
19920 +               return 0; /* cannot match in the same time loose and strict source routing */
19921 +       if ((((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) ||
19922 +            ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR)) &&
19923 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR))
19924 +               return 0; /* opposites */
19925 +       if (((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) &&
19926 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR))
19927 +               return 0; /* opposites */
19928 +       if (((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) &&
19929 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP))
19930 +               return 0; /* opposites */
19931 +       if (((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) &&
19932 +           ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT))
19933 +               return 0; /* opposites */
19934 +
19935 +       /* everything looks ok. */
19936 +       return 1;
19937 +}
19938 +
19939 +static struct ipt_match ipv4options_match
19940 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
19941 +
19942 +static int __init init(void)
19943 +{
19944 +       printk("ipt_ipv4options loading\n");
19945 +       return ipt_register_match(&ipv4options_match);
19946 +}
19947 +
19948 +static void __exit fini(void)
19949 +{
19950 +       ipt_unregister_match(&ipv4options_match);
19951 +       printk("ipt_ipv4options unloaded\n");
19952 +}
19953 +
19954 +module_init(init);
19955 +module_exit(fini);
19956 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_mark.c linux-2.4.20/net/ipv4/netfilter/ipt_mark.c
19957 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_mark.c      Sun Sep 30 19:26:08 2001
19958 +++ linux-2.4.20/net/ipv4/netfilter/ipt_mark.c  Wed Sep 24 09:18:10 2003
19959 @@ -15,9 +15,15 @@
19960        u_int16_t datalen,
19961        int *hotdrop)
19962  {
19963 -       const struct ipt_mark_info *info = matchinfo;
19964 +       const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
19965  
19966 -       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
19967 +       if (info->bit_op == IPT_MARK_BIT_OP_NONE)
19968 +               return (skb->nfmark == info->mark) ^ info->invert;
19969 +       else
19970 +               if (info->bit_op == IPT_MARK_BIT_OP_AND)
19971 +                       return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
19972 +               else
19973 +                       return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
19974  }
19975  
19976  static int
19977 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_mport.c linux-2.4.20/net/ipv4/netfilter/ipt_mport.c
19978 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_mport.c     Thu Jan  1 00:00:00 1970
19979 +++ linux-2.4.20/net/ipv4/netfilter/ipt_mport.c Wed Sep 24 09:16:51 2003
19980 @@ -0,0 +1,112 @@
19981 +/* Kernel module to match one of a list of TCP/UDP ports: ports are in
19982 +   the same place so we can treat them as equal. */
19983 +#include <linux/module.h>
19984 +#include <linux/types.h>
19985 +#include <linux/udp.h>
19986 +#include <linux/skbuff.h>
19987 +
19988 +#include <linux/netfilter_ipv4/ipt_mport.h>
19989 +#include <linux/netfilter_ipv4/ip_tables.h>
19990 +
19991 +MODULE_LICENSE("GPL");
19992 +
19993 +#if 0
19994 +#define duprintf(format, args...) printk(format , ## args)
19995 +#else
19996 +#define duprintf(format, args...)
19997 +#endif
19998 +
19999 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
20000 +static inline int
20001 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
20002 +{
20003 +       unsigned int i;
20004 +        unsigned int m;
20005 +        u_int16_t pflags = minfo->pflags;
20006 +       for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
20007 +                u_int16_t s, e;
20008 +
20009 +                if (pflags & m
20010 +                    && minfo->ports[i] == 65535)
20011 +                        return 0;
20012 +
20013 +                s = minfo->ports[i];
20014 +
20015 +                if (pflags & m) {
20016 +                        e = minfo->ports[++i];
20017 +                        m <<= 1;
20018 +                } else
20019 +                        e = s;
20020 +
20021 +                if (minfo->flags & IPT_MPORT_SOURCE
20022 +                    && src >= s && src <= e)
20023 +                        return 1;
20024 +
20025 +               if (minfo->flags & IPT_MPORT_DESTINATION
20026 +                   && dst >= s && dst <= e)
20027 +                       return 1;
20028 +       }
20029 +
20030 +       return 0;
20031 +}
20032 +
20033 +static int
20034 +match(const struct sk_buff *skb,
20035 +      const struct net_device *in,
20036 +      const struct net_device *out,
20037 +      const void *matchinfo,
20038 +      int offset,
20039 +      const void *hdr,
20040 +      u_int16_t datalen,
20041 +      int *hotdrop)
20042 +{
20043 +       const struct udphdr *udp = hdr;
20044 +       const struct ipt_mport *minfo = matchinfo;
20045 +
20046 +       /* Must be big enough to read ports. */
20047 +       if (offset == 0 && datalen < sizeof(struct udphdr)) {
20048 +               /* We've been asked to examine this packet, and we
20049 +                  can't.  Hence, no choice but to drop. */
20050 +                       duprintf("ipt_mport:"
20051 +                                " Dropping evil offset=0 tinygram.\n");
20052 +                       *hotdrop = 1;
20053 +                       return 0;
20054 +       }
20055 +
20056 +       /* Must not be a fragment. */
20057 +       return !offset
20058 +               && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
20059 +}
20060 +
20061 +/* Called when user tries to insert an entry of this type. */
20062 +static int
20063 +checkentry(const char *tablename,
20064 +          const struct ipt_ip *ip,
20065 +          void *matchinfo,
20066 +          unsigned int matchsize,
20067 +          unsigned int hook_mask)
20068 +{
20069 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
20070 +               return 0;
20071 +
20072 +       /* Must specify proto == TCP/UDP, no unknown flags or bad count */
20073 +       return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
20074 +               && !(ip->invflags & IPT_INV_PROTO)
20075 +               && matchsize == IPT_ALIGN(sizeof(struct ipt_mport));
20076 +}
20077 +
20078 +static struct ipt_match mport_match
20079 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
20080 +
20081 +static int __init init(void)
20082 +{
20083 +       return ipt_register_match(&mport_match);
20084 +}
20085 +
20086 +static void __exit fini(void)
20087 +{
20088 +       ipt_unregister_match(&mport_match);
20089 +}
20090 +
20091 +module_init(init);
20092 +module_exit(fini);
20093 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_multiport.c linux-2.4.20/net/ipv4/netfilter/ipt_multiport.c
20094 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_multiport.c Sun Sep 30 19:26:08 2001
20095 +++ linux-2.4.20/net/ipv4/netfilter/ipt_multiport.c     Wed Sep 24 09:16:14 2003
20096 @@ -78,7 +78,7 @@
20097  
20098         /* Must specify proto == TCP/UDP, no unknown flags or bad count */
20099         return (ip->proto == IPPROTO_TCP || ip->proto == IPPROTO_UDP)
20100 -               && !(ip->flags & IPT_INV_PROTO)
20101 +               && !(ip->invflags & IPT_INV_PROTO)
20102                 && matchsize == IPT_ALIGN(sizeof(struct ipt_multiport))
20103                 && (multiinfo->flags == IPT_MULTIPORT_SOURCE
20104                     || multiinfo->flags == IPT_MULTIPORT_DESTINATION
20105 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_nth.c linux-2.4.20/net/ipv4/netfilter/ipt_nth.c
20106 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_nth.c       Thu Jan  1 00:00:00 1970
20107 +++ linux-2.4.20/net/ipv4/netfilter/ipt_nth.c   Wed Sep 24 09:16:53 2003
20108 @@ -0,0 +1,172 @@
20109 +/*
20110 +  This is a module which is used for match support for every Nth packet
20111 +  This file is distributed under the terms of the GNU General Public
20112 +  License (GPL). Copies of the GPL can be obtained from:
20113 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
20114 +
20115 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
20116 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
20117 +        * added support for multiple counters
20118 +        * added support for matching on individual packets
20119 +          in the counter cycle
20120 +
20121 +*/
20122 +
20123 +#include <linux/module.h>
20124 +#include <linux/skbuff.h>
20125 +#include <linux/ip.h>
20126 +#include <net/tcp.h>
20127 +#include <linux/spinlock.h>
20128 +#include <linux/netfilter_ipv4/ip_tables.h>
20129 +#include <linux/netfilter_ipv4/ipt_nth.h>
20130 +
20131 +MODULE_LICENSE("GPL");
20132 +
20133 +/*
20134 + * State information.
20135 + */
20136 +struct state {
20137 +       spinlock_t lock;
20138 +       u_int16_t number;
20139 +};
20140 +
20141 +static struct state states[IPT_NTH_NUM_COUNTERS];
20142 +
20143 +static int
20144 +ipt_nth_match(const struct sk_buff *pskb,
20145 +             const struct net_device *in,
20146 +             const struct net_device *out,
20147 +             const void *matchinfo,
20148 +             int offset,
20149 +             const void *hdr,
20150 +             u_int16_t datalen,
20151 +             int *hotdrop)
20152 +{
20153 +       /* Parameters from userspace */
20154 +       const struct ipt_nth_info *info = matchinfo;
20155 +        unsigned counter = info->counter;
20156 +               if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
20157 +       {
20158 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
20159 +               return 0;
20160 +        };
20161 +
20162 +        spin_lock(&states[counter].lock);
20163 +
20164 +        /* Are we matching every nth packet?*/
20165 +        if (info->packet == 0xFF)
20166 +        {
20167 +               /* We're matching every nth packet and only every nth packet*/
20168 +               /* Do we match or invert match? */
20169 +               if (info->not == 0)
20170 +               {
20171 +                       if (states[counter].number == 0)
20172 +                       {
20173 +                               ++states[counter].number;
20174 +                               goto match;
20175 +                       }
20176 +                       if (states[counter].number >= info->every)
20177 +                               states[counter].number = 0; /* reset the counter */
20178 +                       else
20179 +                               ++states[counter].number;
20180 +                       goto dontmatch;
20181 +               }
20182 +               else
20183 +               {
20184 +                       if (states[counter].number == 0)
20185 +                       {
20186 +                               ++states[counter].number;
20187 +                               goto dontmatch;
20188 +                       }
20189 +                       if (states[counter].number >= info->every)
20190 +                               states[counter].number = 0;
20191 +                       else
20192 +                               ++states[counter].number;
20193 +                       goto match;
20194 +               }
20195 +        }
20196 +        else
20197 +        {
20198 +               /* We're using the --packet, so there must be a rule for every value */
20199 +               if (states[counter].number == info->packet)
20200 +               {
20201 +                       /* only increment the counter when a match happens */
20202 +                       if (states[counter].number >= info->every)
20203 +                               states[counter].number = 0; /* reset the counter */
20204 +                       else
20205 +                               ++states[counter].number;
20206 +                       goto match;
20207 +               }
20208 +               else
20209 +                       goto dontmatch;
20210 +       }
20211 +
20212 + dontmatch:
20213 +       /* don't match */
20214 +       spin_unlock(&states[counter].lock);
20215 +       return 0;
20216 +
20217 + match:
20218 +       spin_unlock(&states[counter].lock);
20219 +       return 1;
20220 +}
20221 +
20222 +static int
20223 +ipt_nth_checkentry(const char *tablename,
20224 +                  const struct ipt_ip *e,
20225 +                  void *matchinfo,
20226 +                  unsigned int matchsize,
20227 +                  unsigned int hook_mask)
20228 +{
20229 +       /* Parameters from userspace */
20230 +       const struct ipt_nth_info *info = matchinfo;
20231 +        unsigned counter = info->counter;
20232 +        if((counter < 0) || (counter >= IPT_NTH_NUM_COUNTERS)) 
20233 +       {
20234 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
20235 +                       return 0;
20236 +               };
20237 +
20238 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_nth_info))) {
20239 +               printk("nth: matchsize %u != %u\n", matchsize,
20240 +                      IPT_ALIGN(sizeof(struct ipt_nth_info)));
20241 +               return 0;
20242 +       }
20243 +
20244 +       states[counter].number = info->startat;
20245 +
20246 +       return 1;
20247 +}
20248 +
20249 +static struct ipt_match ipt_nth_reg = { 
20250 +       {NULL, NULL},
20251 +       "nth",
20252 +       ipt_nth_match,
20253 +       ipt_nth_checkentry,
20254 +       NULL,
20255 +       THIS_MODULE };
20256 +
20257 +static int __init init(void)
20258 +{
20259 +       unsigned counter;
20260 +        memset(&states, 0, sizeof(states));
20261 +       if (ipt_register_match(&ipt_nth_reg))
20262 +               return -EINVAL;
20263 +
20264 +        for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++) 
20265 +       {
20266 +               spin_lock_init(&(states[counter].lock));
20267 +        };
20268 +
20269 +       printk("ipt_nth match loaded\n");
20270 +       return 0;
20271 +}
20272 +
20273 +static void __exit fini(void)
20274 +{
20275 +       ipt_unregister_match(&ipt_nth_reg);
20276 +       printk("ipt_nth match unloaded\n");
20277 +}
20278 +
20279 +module_init(init);
20280 +module_exit(fini);
20281 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_osf.c linux-2.4.20/net/ipv4/netfilter/ipt_osf.c
20282 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_osf.c       Thu Jan  1 00:00:00 1970
20283 +++ linux-2.4.20/net/ipv4/netfilter/ipt_osf.c   Wed Sep 24 09:16:57 2003
20284 @@ -0,0 +1,685 @@
20285 +/*
20286 + * ipt_osf.c
20287 + *
20288 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
20289 + *
20290 + *
20291 + * This program is free software; you can redistribute it and/or modify
20292 + * it under the terms of the GNU General Public License as published by
20293 + * the Free Software Foundation; either version 2 of the License, or
20294 + * (at your option) any later version.
20295 + *
20296 + * This program is distributed in the hope that it will be useful,
20297 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
20298 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20299 + * GNU General Public License for more details.
20300 + *
20301 + * You should have received a copy of the GNU General Public License
20302 + * along with this program; if not, write to the Free Software
20303 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20304 + */
20305 +
20306 +/*
20307 + * OS fingerprint matching module.
20308 + * It simply compares various parameters from SYN packet with
20309 + * some hardcoded ones.
20310 + *
20311 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
20312 + * for his p0f.
20313 + */
20314 +
20315 +#include <linux/smp.h>
20316 +#include <linux/module.h>
20317 +#include <linux/skbuff.h>
20318 +#include <linux/file.h>
20319 +#include <linux/ip.h>
20320 +#include <linux/proc_fs.h>
20321 +#include <linux/fs.h>
20322 +#include <linux/slab.h>
20323 +#include <linux/spinlock.h>
20324 +#include <linux/ctype.h>
20325 +#include <linux/list.h>
20326 +
20327 +#include <net/sock.h>
20328 +#include <net/ip.h>
20329 +
20330 +#include <linux/netfilter_ipv4/ip_tables.h>
20331 +
20332 +#include <linux/netfilter_ipv4/ipt_osf.h>
20333 +
20334 +//#define OSF_DEBUG
20335 +
20336 +#ifdef OSF_DEBUG
20337 +#define log(x...)              printk(KERN_ERR "ipt_osf: " x)
20338 +#define loga(x...)             printk(x)
20339 +#else
20340 +#define log(x...)              do {} while(0)
20341 +#define loga(x...)             do {} while(0)
20342 +#endif
20343 +
20344 +#define FMATCH_WRONG           0
20345 +#define FMATCH_OK              1
20346 +#define FMATCH_OPT_WRONG       2
20347 +
20348 +#define OPTDEL                 ','
20349 +#define OSFPDEL                ':'
20350 +#define MAXOPTSTRLEN           128
20351 +#define OSFFLUSH               "FLUSH"
20352 +
20353 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
20354 +static struct list_head        finger_list;    
20355 +
20356 +static int match(const struct sk_buff *, const struct net_device *, const struct net_device *,
20357 +                     const void *, int, const void *, u_int16_t, int *);
20358 +static int checkentry(const char *, const struct ipt_ip *, void *,
20359 +                          unsigned int, unsigned int);
20360 +
20361 +static struct ipt_match osf_match = 
20362 +{ 
20363 +       { NULL, NULL }, 
20364 +       "osf", 
20365 +       &match, 
20366 +       &checkentry, 
20367 +       NULL, 
20368 +       THIS_MODULE 
20369 +};
20370 +
20371 +static int
20372 +match(const struct sk_buff *skb,
20373 +      const struct net_device *in,
20374 +      const struct net_device *out,
20375 +      const void *matchinfo,
20376 +      int offset,
20377 +      const void *hdr,
20378 +      u_int16_t datalen,
20379 +      int *hotdrop)
20380 +{
20381 +       struct ipt_osf_info *info = (struct ipt_osf_info *)matchinfo;
20382 +       struct iphdr *ip = skb->nh.iph;
20383 +       struct tcphdr *tcp;
20384 +       int fmatch = FMATCH_WRONG;
20385 +       unsigned long totlen, optsize = 0, window;
20386 +       unsigned char df, *optp = NULL, *_optp = NULL;
20387 +       char check_WSS = 0;
20388 +       struct list_head *ent;
20389 +       struct osf_finger *f;
20390 +
20391 +       if (!ip || !info)
20392 +               return 0;
20393 +                               
20394 +       tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
20395 +
20396 +       if (!tcp->syn)
20397 +               return 0;
20398 +       
20399 +       totlen = ntohs(ip->tot_len);
20400 +       df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
20401 +       window = ntohs(tcp->window);
20402 +       
20403 +       if (tcp->doff*4 > sizeof(struct tcphdr))
20404 +       {
20405 +               _optp = optp = (char *)(tcp+1);
20406 +               optsize = tcp->doff*4 - sizeof(struct tcphdr);
20407 +       }
20408 +
20409 +       
20410 +       /* Actually we can create hash/table of all genres and search
20411 +        * only in appropriate part, but here is initial variant,
20412 +        * so will use slow path.
20413 +        */
20414 +       read_lock(&osf_lock);
20415 +       list_for_each(ent, &finger_list)
20416 +       {
20417 +               f = list_entry(ent, struct osf_finger, flist);
20418 +               
20419 +               if (strcmp(info->genre, f->genre)) 
20420 +                       continue;
20421 +
20422 +               optp = _optp;
20423 +
20424 +               if (    ip->ttl == f->ttl &&
20425 +                       totlen  == f->ss &&
20426 +                       df      == f->df)
20427 +               {
20428 +                       unsigned long foptsize;
20429 +                       int optnum;
20430 +                       unsigned short mss = 0;
20431 +
20432 +                       check_WSS = 0;
20433 +
20434 +                       switch (f->wss.wc)
20435 +                       {
20436 +                               case 0:   check_WSS = 0; break;
20437 +                               case 'S': check_WSS = 1; break;
20438 +                               case 'T': check_WSS = 2; break;
20439 +                               case '%': check_WSS = 3; break;
20440 +                               default: log("Wrong fingerprint wss.wc=%d, %s - %s\n", 
20441 +                                                        f->wss.wc, f->genre, f->details);
20442 +                                        check_WSS = 4;
20443 +                                        break;
20444 +                       }
20445 +                       if (check_WSS == 4)
20446 +                               continue;
20447 +
20448 +                       /* Check options */
20449 +
20450 +                       foptsize = 0;
20451 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
20452 +                               foptsize += f->opt[optnum].length;
20453 +
20454 +                               
20455 +                       if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
20456 +                               continue;
20457 +
20458 +                       if (!optp)
20459 +                       {
20460 +                               fmatch = FMATCH_OK;
20461 +                               loga("\tYEP : matching without options.\n");
20462 +                               break;
20463 +                       }
20464 +                       
20465 +
20466 +                       for (optnum=0; optnum<f->opt_num; ++optnum)
20467 +                       {
20468 +                               if (f->opt[optnum].kind == (*optp))
20469 +                               {
20470 +                                       unsigned char len = f->opt[optnum].length;
20471 +                                       unsigned char *optend = optp + len;
20472 +
20473 +                                       fmatch = FMATCH_OK;
20474 +
20475 +                                       if (*optp == OSFOPT_MSS) /* MSS */
20476 +                                               mss = ntohs(*(unsigned short *)(optp+2));
20477 +                                       
20478 +                                       if (len != 1)
20479 +                                       {
20480 +                                               /* Skip kind and length fields*/
20481 +                                               optp += 2; 
20482 +
20483 +                                               if (f->opt[optnum].wc.wc != 0)
20484 +                                               {
20485 +                                                       unsigned long tmp = 0;
20486 +                                                       
20487 +                                                       /* Hmmm... It looks a bit ugly. :) */
20488 +                                                       memcpy(&tmp, &f->opt[optnum].wc.val, 
20489 +                                                               (len > sizeof(unsigned long)?
20490 +                                                                       sizeof(unsigned long):len));
20491 +
20492 +                                                       tmp = ntohl(tmp);
20493 +                                                       if (tmp != f->opt[optnum].wc.val)
20494 +                                                               fmatch = FMATCH_OPT_WRONG;
20495 +                                               }
20496 +                                       }
20497 +
20498 +                                       optp = optend;
20499 +                               }
20500 +                               else
20501 +                                       fmatch = FMATCH_OPT_WRONG;
20502 +
20503 +                               if (fmatch != FMATCH_OK)
20504 +                                       break;
20505 +                       }
20506 +
20507 +                       if (fmatch != FMATCH_OPT_WRONG)
20508 +                       {
20509 +                               fmatch = FMATCH_WRONG;
20510 +
20511 +                               switch (check_WSS)
20512 +                               {
20513 +                                       case 0:
20514 +                                               if (window == f->wss.val)
20515 +                                                       fmatch = FMATCH_OK;
20516 +                                               break;
20517 +                                       case 1: /* MSS */
20518 +                                               if (window == f->wss.val*mss)
20519 +                                                       fmatch = FMATCH_OK;
20520 +                                               break;
20521 +                                       case 2: /* MTU */
20522 +                                               if (window == f->wss.val*(mss+40))
20523 +                                                       fmatch = FMATCH_OK;
20524 +                                               break;
20525 +                                       case 3: /* MOD */
20526 +                                               if (window % f->wss.val == 0)
20527 +                                                       fmatch = FMATCH_OK;
20528 +                                               break;
20529 +                               }
20530 +                       }
20531 +                                       
20532 +
20533 +                       if (fmatch == FMATCH_OK)
20534 +                       {
20535 +
20536 +                               log("genre %s[%25s]: ttl=%d, size=%lu, df=%d, "
20537 +                                       "check_WSS=%d, win=%lu, optsize=%lu:\n", 
20538 +                                       f->genre, f->details, 
20539 +                                       ip->ttl, totlen, df, 
20540 +                                       check_WSS, window, optsize);
20541 +                               break;
20542 +                       }
20543 +               }
20544 +       }
20545 +       read_unlock(&osf_lock);
20546 +
20547 +       return (fmatch == FMATCH_OK)?1:0;
20548 +}
20549 +
20550 +static int
20551 +checkentry(const char *tablename,
20552 +           const struct ipt_ip *ip,
20553 +           void *matchinfo,
20554 +           unsigned int matchsize,
20555 +           unsigned int hook_mask)
20556 +{
20557 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
20558 +               return 0;
20559 +       if (ip->proto != IPPROTO_TCP)
20560 +              return 0;
20561 +
20562 +       return 1;
20563 +}
20564 +
20565 +static struct osf_finger * finger_alloc()
20566 +{
20567 +       struct osf_finger *f;
20568 +
20569 +       f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
20570 +       if (f)
20571 +               memset(f, 0, sizeof(struct osf_finger));
20572 +       
20573 +       return f;
20574 +}
20575 +
20576 +static void finger_free(struct osf_finger *f)
20577 +{
20578 +       memset(f, 0, sizeof(struct osf_finger));
20579 +       kfree(f);
20580 +}
20581 +
20582 +
20583 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
20584 +{
20585 +       int i, op;
20586 +       char *ptr, wc;
20587 +       unsigned long val;
20588 +
20589 +       ptr = &obuf[0];
20590 +       i = 0;
20591 +       while (ptr != NULL && i < olen)
20592 +       {
20593 +               val = 0;
20594 +               op = 0;
20595 +               wc = 0;
20596 +               switch (obuf[i])
20597 +               {
20598 +                       case 'N': 
20599 +                               op = OSFOPT_NOP;
20600 +                               ptr = strchr(&obuf[i], OPTDEL);
20601 +                               if (ptr)
20602 +                               {
20603 +                                       *ptr = '\0';
20604 +                                       ptr++;
20605 +                                       i += (int)(ptr-&obuf[i]);
20606 +
20607 +                               }
20608 +                               else
20609 +                                       i++;
20610 +                               break;
20611 +                       case 'S': 
20612 +                               op = OSFOPT_SACKP;
20613 +                               ptr = strchr(&obuf[i], OPTDEL);
20614 +                               if (ptr)
20615 +                               {
20616 +                                       *ptr = '\0';
20617 +                                       ptr++;
20618 +                                       i += (int)(ptr-&obuf[i]);
20619 +
20620 +                               }
20621 +                               else
20622 +                                       i++;
20623 +                               break;
20624 +                       case 'T': 
20625 +                               op = OSFOPT_TS;
20626 +                               ptr = strchr(&obuf[i], OPTDEL);
20627 +                               if (ptr)
20628 +                               {
20629 +                                       *ptr = '\0';
20630 +                                       ptr++;
20631 +                                       i += (int)(ptr-&obuf[i]);
20632 +
20633 +                               }
20634 +                               else
20635 +                                       i++;
20636 +                               break;
20637 +                       case 'W': 
20638 +                               op = OSFOPT_WSO;
20639 +                               ptr = strchr(&obuf[i], OPTDEL);
20640 +                               if (ptr)
20641 +                               {
20642 +                                       switch (obuf[i+1])
20643 +                                       {
20644 +                                               case '%':       wc = '%'; break;
20645 +                                               case 'S':       wc = 'S'; break;
20646 +                                               case 'T':       wc = 'T'; break;
20647 +                                               default:        wc = 0; break;
20648 +                                       }
20649 +                                       
20650 +                                       *ptr = '\0';
20651 +                                       ptr++;
20652 +                                       if (wc)
20653 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
20654 +                                       else
20655 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
20656 +                                       i += (int)(ptr-&obuf[i]);
20657 +
20658 +                               }
20659 +                               else
20660 +                                       i++;
20661 +                               break;
20662 +                       case 'M': 
20663 +                               op = OSFOPT_MSS;
20664 +                               ptr = strchr(&obuf[i], OPTDEL);
20665 +                               if (ptr)
20666 +                               {
20667 +                                       if (obuf[i+1] == '%')
20668 +                                               wc = '%';
20669 +                                       *ptr = '\0';
20670 +                                       ptr++;
20671 +                                       if (wc)
20672 +                                               val = simple_strtoul(&obuf[i+2], NULL, 10);
20673 +                                       else
20674 +                                               val = simple_strtoul(&obuf[i+1], NULL, 10);
20675 +                                       i += (int)(ptr-&obuf[i]);
20676 +
20677 +                               }
20678 +                               else
20679 +                                       i++;
20680 +                               break;
20681 +                       case 'E': 
20682 +                               op = OSFOPT_EOL;
20683 +                               ptr = strchr(&obuf[i], OPTDEL);
20684 +                               if (ptr)
20685 +                               {
20686 +                                       *ptr = '\0';
20687 +                                       ptr++;
20688 +                                       i += (int)(ptr-&obuf[i]);
20689 +
20690 +                               }
20691 +                               else
20692 +                                       i++;
20693 +                               break;
20694 +                       default:
20695 +                               ptr = strchr(&obuf[i], OPTDEL);
20696 +                               if (ptr)
20697 +                               {
20698 +                                       ptr++;
20699 +                                       i += (int)(ptr-&obuf[i]);
20700 +
20701 +                               }
20702 +                               else
20703 +                                       i++;
20704 +                               break;
20705 +               }
20706 +
20707 +               opt[*optnum].kind       = IANA_opts[op].kind;
20708 +               opt[*optnum].length     = IANA_opts[op].length;
20709 +               opt[*optnum].wc.wc      = wc;
20710 +               opt[*optnum].wc.val     = val;
20711 +
20712 +               log("opt %2d: kind=%2d, length=%2d, wc.wc=%d, wc.val=%5lu\n",
20713 +                       *optnum, opt[*optnum].kind, opt[*optnum].length, 
20714 +                       opt[*optnum].wc.wc, opt[*optnum].wc.val);
20715 +               
20716 +               (*optnum)++;
20717 +       }
20718 +}
20719 +
20720 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
20721 +{
20722 +       struct list_head *ent;
20723 +       struct osf_finger *f = NULL;
20724 +       int i;
20725 +       
20726 +       *eof = 1;
20727 +       count = 0;
20728 +
20729 +       read_lock_bh(&osf_lock);
20730 +       list_for_each(ent, &finger_list)
20731 +       {
20732 +               f = list_entry(ent, struct osf_finger, flist);
20733 +
20734 +               log("%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
20735 +                       f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
20736 +               
20737 +               count += sprintf(buf+count, "%s - %s: ttl=%d, wss=%c%lu, df=%d, size=%lu",
20738 +                       f->genre, f->details, f->ttl, (f->wss.wc)?f->wss.wc:' ', f->wss.val, f->df, f->ss);
20739 +               
20740 +               if (f->opt_num)
20741 +               {
20742 +                       loga(" OPT: ");
20743 +                       //count += sprintf(buf+count, " OPT: ");
20744 +                       for (i=0; i<f->opt_num; ++i)
20745 +                       {
20746 +                               //count += sprintf(buf+count, "%d.%c%lu; ", 
20747 +                               //      f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
20748 +                               loga("%d.%c%lu; ", 
20749 +                                       f->opt[i].kind, (f->opt[i].wc.wc)?f->opt[i].wc.wc:' ', f->opt[i].wc.val);
20750 +                       }
20751 +               }
20752 +               loga("\n");
20753 +               count += sprintf(buf+count, "\n");
20754 +       }
20755 +       read_unlock_bh(&osf_lock);
20756 +
20757 +       return count;
20758 +}
20759 +
20760 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
20761 +{
20762 +       int cnt;
20763 +       unsigned long i;
20764 +       char quirks[MAXOPTSTRLEN], obuf[MAXOPTSTRLEN];
20765 +       struct osf_finger *finger;
20766 +       struct list_head *ent, *n;
20767 +
20768 +       char *pbeg, *pend;
20769 +
20770 +       if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
20771 +       {
20772 +               int i = 0;
20773 +               write_lock_bh(&osf_lock);
20774 +               list_for_each_safe(ent, n, &finger_list)
20775 +               {
20776 +                       i++;
20777 +                       finger = list_entry(ent, struct osf_finger, flist);
20778 +                       list_del(&finger->flist);
20779 +                       finger_free(finger);
20780 +               }
20781 +               write_unlock_bh(&osf_lock);
20782 +       
20783 +               log("Flushed %d entries.\n", i);
20784 +               
20785 +               return count;
20786 +       }
20787 +
20788 +       
20789 +       cnt = 0;
20790 +       for (i=0; i<count && buffer[i] != '\0'; ++i)
20791 +               if (buffer[i] == ':')
20792 +                       cnt++;
20793 +
20794 +       if (cnt != 7 || i != count)
20795 +       {
20796 +               log("Wrong input line cnt=%d[7], len=%lu[%lu]\n", 
20797 +                       cnt, i, count);
20798 +               return count;
20799 +       }
20800 +
20801 +
20802 +       memset(quirks, 0, sizeof(quirks));
20803 +       memset(obuf, 0, sizeof(obuf));
20804 +       
20805 +       finger = finger_alloc();
20806 +       if (!finger)
20807 +       {
20808 +               log("Failed to allocate new fingerprint entry.\n");
20809 +               return -ENOMEM;
20810 +       }
20811 +
20812 +       pbeg = (char *)buffer;
20813 +       pend = strchr(pbeg, OSFPDEL);
20814 +       if (pend)
20815 +       {
20816 +               *pend = '\0';
20817 +               if (pbeg[0] == 'S')
20818 +               {
20819 +                       finger->wss.wc = 'S';
20820 +                       if (pbeg[1] == '%')
20821 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
20822 +                       else if (pbeg[1] == '*')
20823 +                               finger->wss.val = 0;
20824 +                       else 
20825 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
20826 +               }
20827 +               else if (pbeg[0] == 'T')
20828 +               {
20829 +                       finger->wss.wc = 'T';
20830 +                       if (pbeg[1] == '%')
20831 +                               finger->wss.val = simple_strtoul(pbeg+2, NULL, 10);
20832 +                       else if (pbeg[1] == '*')
20833 +                               finger->wss.val = 0;
20834 +                       else 
20835 +                               finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
20836 +               }
20837 +               if (isdigit(pbeg[0]))
20838 +               {
20839 +                       finger->wss.wc = 0;
20840 +                       finger->wss.val = simple_strtoul(pbeg, NULL, 10);
20841 +               }
20842 +
20843 +               pbeg = pend+1;
20844 +       }
20845 +       pend = strchr(pbeg, OSFPDEL);
20846 +       if (pend)
20847 +       {
20848 +               *pend = '\0';
20849 +               finger->ttl = simple_strtoul(pbeg, NULL, 10);
20850 +               pbeg = pend+1;
20851 +       }
20852 +       pend = strchr(pbeg, OSFPDEL);
20853 +       if (pend)
20854 +       {
20855 +               *pend = '\0';
20856 +               finger->df = simple_strtoul(pbeg, NULL, 10);
20857 +               pbeg = pend+1;
20858 +       }
20859 +       pend = strchr(pbeg, OSFPDEL);
20860 +       if (pend)
20861 +       {
20862 +               *pend = '\0';
20863 +               finger->ss = simple_strtoul(pbeg, NULL, 10);
20864 +               pbeg = pend+1;
20865 +       }
20866 +
20867 +       pend = strchr(pbeg, OSFPDEL);
20868 +       if (pend)
20869 +       {
20870 +               *pend = '\0';
20871 +               cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
20872 +               pbeg = pend+1;
20873 +       }
20874 +       
20875 +       pend = strchr(pbeg, OSFPDEL);
20876 +       if (pend)
20877 +       {
20878 +               *pend = '\0';
20879 +               cnt = snprintf(quirks, sizeof(quirks), "%s", pbeg);
20880 +               pbeg = pend+1;
20881 +       }
20882 +
20883 +       pend = strchr(pbeg, OSFPDEL);
20884 +       if (pend)
20885 +       {
20886 +               *pend = '\0';
20887 +               if (pbeg[0] == '@' || pbeg[0] == '*')
20888 +                       cnt = snprintf(finger->genre, 
20889 +                                       ((count-(pbeg+1-buffer)+1) > MAXGENRELEN)?MAXGENRELEN:(count-(pbeg+1-buffer)+1), 
20890 +                                       "%s", pbeg+1);
20891 +               else
20892 +                       cnt = snprintf(finger->genre, 
20893 +                                       ((count-(pbeg-buffer)+1) > MAXGENRELEN)?MAXGENRELEN:(count-(pbeg-buffer)+1), 
20894 +                                       "%s", pbeg);
20895 +               pbeg = pend+1;
20896 +       }
20897 +
20898 +       cnt = snprintf(finger->details, 
20899 +                       ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1), 
20900 +                       "%s", pbeg);
20901 +       
20902 +       log("%s - %s. ttl=%d, df=%d, size=%lu, wss=[%d, %lu]\n", 
20903 +               finger->genre, finger->details,
20904 +               finger->ttl, finger->df, finger->ss,
20905 +               finger->wss.wc, finger->wss.val);
20906 +       
20907 +       osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
20908 +       
20909 +
20910 +       write_lock_bh(&osf_lock);
20911 +       list_add(&finger->flist, &finger_list);
20912 +       write_unlock_bh(&osf_lock);
20913 +
20914 +       return count;
20915 +}
20916 +
20917 +static int __init osf_init(void)
20918 +{
20919 +       int err;
20920 +       struct proc_dir_entry *p;
20921 +
20922 +       log("Startng OS fingerprint matching module.\n");
20923 +
20924 +       INIT_LIST_HEAD(&finger_list);
20925 +       
20926 +       err = ipt_register_match(&osf_match);
20927 +       if (err)
20928 +       {
20929 +               log("Failed to register OS fingerprint matching module.\n");
20930 +               return -ENXIO;
20931 +       }
20932 +
20933 +       p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
20934 +       if (!p)
20935 +       {
20936 +               ipt_unregister_match(&osf_match);
20937 +               return -ENXIO;
20938 +       }
20939 +
20940 +       p->write_proc = osf_proc_write;
20941 +       p->read_proc  = osf_proc_read;
20942 +
20943 +       return 0;
20944 +}
20945 +
20946 +static void __exit osf_fini(void)
20947 +{
20948 +       struct list_head *ent, *n;
20949 +       struct osf_finger *f;
20950 +       
20951 +       remove_proc_entry("sys/net/ipv4/osf", NULL);
20952 +       ipt_unregister_match(&osf_match);
20953 +
20954 +       list_for_each_safe(ent, n, &finger_list)
20955 +       {
20956 +               f = list_entry(ent, struct osf_finger, flist);
20957 +               list_del(&f->flist);
20958 +               finger_free(f);
20959 +       }
20960 +       
20961 +       log("OS fingerprint matching module finished.\n");
20962 +}
20963 +
20964 +module_init(osf_init);
20965 +module_exit(osf_fini);
20966 +
20967 +MODULE_LICENSE("GPL");
20968 +MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
20969 +MODULE_DESCRIPTION("Passive OS fingerprint matching.");
20970 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_owner.c linux-2.4.20/net/ipv4/netfilter/ipt_owner.c
20971 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_owner.c     Thu Nov 28 23:53:15 2002
20972 +++ linux-2.4.20/net/ipv4/netfilter/ipt_owner.c Wed Sep 24 09:17:52 2003
20973 @@ -2,17 +2,25 @@
20974     locally generated outgoing packets.
20975  
20976     Copyright (C) 2000 Marc Boucher
20977 +
20978 +   03/26/2003 Patrick McHardy <kaber@trash.net>: LOCAL_IN support
20979   */
20980  #include <linux/module.h>
20981  #include <linux/skbuff.h>
20982  #include <linux/file.h>
20983 +#include <linux/ip.h>
20984 +#include <linux/tcp.h>
20985 +#include <linux/udp.h>
20986  #include <net/sock.h>
20987 +#include <net/tcp.h>
20988 +#include <net/udp.h>
20989 +#include <net/route.h>
20990  
20991  #include <linux/netfilter_ipv4/ipt_owner.h>
20992  #include <linux/netfilter_ipv4/ip_tables.h>
20993  
20994  static int
20995 -match_comm(const struct sk_buff *skb, const char *comm)
20996 +match_comm(const struct sock *sk, const char *comm)
20997  {
20998         struct task_struct *p;
20999         struct files_struct *files;
21000 @@ -28,7 +36,7 @@
21001                 if(files) {
21002                         read_lock(&files->file_lock);
21003                         for (i=0; i < files->max_fds; i++) {
21004 -                               if (fcheck_files(files, i) == skb->sk->socket->file) {
21005 +                               if (fcheck_files(files, i) == sk->socket->file) {
21006                                         read_unlock(&files->file_lock);
21007                                         task_unlock(p);
21008                                         read_unlock(&tasklist_lock);
21009 @@ -44,7 +52,7 @@
21010  }
21011  
21012  static int
21013 -match_pid(const struct sk_buff *skb, pid_t pid)
21014 +match_pid(const struct sock *sk, pid_t pid)
21015  {
21016         struct task_struct *p;
21017         struct files_struct *files;
21018 @@ -59,7 +67,7 @@
21019         if(files) {
21020                 read_lock(&files->file_lock);
21021                 for (i=0; i < files->max_fds; i++) {
21022 -                       if (fcheck_files(files, i) == skb->sk->socket->file) {
21023 +                       if (fcheck_files(files, i) == sk->socket->file) {
21024                                 read_unlock(&files->file_lock);
21025                                 task_unlock(p);
21026                                 read_unlock(&tasklist_lock);
21027 @@ -75,10 +83,10 @@
21028  }
21029  
21030  static int
21031 -match_sid(const struct sk_buff *skb, pid_t sid)
21032 +match_sid(const struct sock *sk, pid_t sid)
21033  {
21034         struct task_struct *p;
21035 -       struct file *file = skb->sk->socket->file;
21036 +       struct file *file = sk->socket->file;
21037         int i, found=0;
21038  
21039         read_lock(&tasklist_lock);
21040 @@ -119,41 +127,71 @@
21041        int *hotdrop)
21042  {
21043         const struct ipt_owner_info *info = matchinfo;
21044 -
21045 -       if (!skb->sk || !skb->sk->socket || !skb->sk->socket->file)
21046 -               return 0;
21047 +       struct iphdr *iph = skb->nh.iph;
21048 +       struct sock *sk = NULL;
21049 +       int ret = 0;
21050 +
21051 +       if (out) {
21052 +               sk = skb->sk;
21053 +       } else {
21054 +               if (iph->protocol == IPPROTO_TCP) {
21055 +                       struct tcphdr *tcph =
21056 +                               (struct tcphdr*)((u_int32_t*)iph + iph->ihl);
21057 +                       sk = tcp_v4_lookup(iph->saddr, tcph->source,
21058 +                                          iph->daddr, tcph->dest,
21059 +                                          ((struct rtable*)skb->dst)->rt_iif);
21060 +                       if (sk && sk->state == TCP_TIME_WAIT) {
21061 +                               tcp_tw_put((struct tcp_tw_bucket *)sk);
21062 +                               return ret;
21063 +                       }
21064 +               } else if (iph->protocol == IPPROTO_UDP) {
21065 +                       struct udphdr *udph =
21066 +                               (struct udphdr*)((u_int32_t*)iph + iph->ihl);
21067 +                       sk = udp_v4_lookup(iph->saddr, udph->source, iph->daddr,
21068 +                                          udph->dest, skb->dev->ifindex);
21069 +               }
21070 +       } 
21071 +                                       
21072 +       if (!sk || !sk->socket || !sk->socket->file)
21073 +               goto out;
21074  
21075         if(info->match & IPT_OWNER_UID) {
21076 -               if((skb->sk->socket->file->f_uid != info->uid) ^
21077 +               if((sk->socket->file->f_uid != info->uid) ^
21078                     !!(info->invert & IPT_OWNER_UID))
21079 -                       return 0;
21080 +                       goto out;
21081         }
21082  
21083         if(info->match & IPT_OWNER_GID) {
21084 -               if((skb->sk->socket->file->f_gid != info->gid) ^
21085 +               if((sk->socket->file->f_gid != info->gid) ^
21086                     !!(info->invert & IPT_OWNER_GID))
21087 -                       return 0;
21088 +                       goto out;
21089         }
21090  
21091         if(info->match & IPT_OWNER_PID) {
21092 -               if (!match_pid(skb, info->pid) ^
21093 +               if (!match_pid(sk, info->pid) ^
21094                     !!(info->invert & IPT_OWNER_PID))
21095 -                       return 0;
21096 +                       goto out;
21097         }
21098  
21099         if(info->match & IPT_OWNER_SID) {
21100 -               if (!match_sid(skb, info->sid) ^
21101 +               if (!match_sid(sk, info->sid) ^
21102                     !!(info->invert & IPT_OWNER_SID))
21103 -                       return 0;
21104 +                       goto out;
21105         }
21106  
21107         if(info->match & IPT_OWNER_COMM) {
21108 -               if (!match_comm(skb, info->comm) ^
21109 +               if (!match_comm(sk, info->comm) ^
21110                     !!(info->invert & IPT_OWNER_COMM))
21111 -                       return 0;
21112 +                       goto out;
21113         }
21114  
21115 -       return 1;
21116 +       ret = 1;
21117 +
21118 +out:
21119 +       if (in && sk)
21120 +               sock_put(sk);
21121 +
21122 +       return ret;
21123  }
21124  
21125  static int
21126 @@ -164,11 +202,19 @@
21127             unsigned int hook_mask)
21128  {
21129          if (hook_mask
21130 -            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING))) {
21131 -                printk("ipt_owner: only valid for LOCAL_OUT or POST_ROUTING.\n");
21132 +            & ~((1 << NF_IP_LOCAL_OUT) | (1 << NF_IP_POST_ROUTING) |
21133 +               (1 << NF_IP_LOCAL_IN))) {
21134 +               printk("ipt_owner: only valid for LOCAL_IN, LOCAL_OUT "
21135 +                      "or POST_ROUTING.\n");
21136                  return 0;
21137          }
21138  
21139 +       if ((hook_mask & (1 << NF_IP_LOCAL_IN))
21140 +           && ip->proto != IPPROTO_TCP && ip->proto != IPPROTO_UDP) {
21141 +               printk("ipt_owner: only TCP or UDP can be used in LOCAL_IN\n");
21142 +               return 0;
21143 +       }
21144 +
21145         if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info)))
21146                 return 0;
21147  
21148 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_pool.c linux-2.4.20/net/ipv4/netfilter/ipt_pool.c
21149 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_pool.c      Thu Jan  1 00:00:00 1970
21150 +++ linux-2.4.20/net/ipv4/netfilter/ipt_pool.c  Wed Sep 24 09:16:59 2003
21151 @@ -0,0 +1,71 @@
21152 +/* Kernel module to match an IP address pool. */
21153 +
21154 +#include <linux/module.h>
21155 +#include <linux/ip.h>
21156 +#include <linux/skbuff.h>
21157 +
21158 +#include <linux/netfilter_ipv4/ip_tables.h>
21159 +#include <linux/netfilter_ipv4/ip_pool.h>
21160 +#include <linux/netfilter_ipv4/ipt_pool.h>
21161 +
21162 +static inline int match_pool(
21163 +       ip_pool_t index,
21164 +       __u32 addr,
21165 +       int inv
21166 +) {
21167 +       if (ip_pool_match(index, ntohl(addr)))
21168 +               inv = !inv;
21169 +       return inv;
21170 +}
21171 +
21172 +static int match(
21173 +       const struct sk_buff *skb,
21174 +       const struct net_device *in,
21175 +       const struct net_device *out,
21176 +       const void *matchinfo,
21177 +       int offset,
21178 +       const void *hdr,
21179 +       u_int16_t datalen,
21180 +       int *hotdrop
21181 +) {
21182 +       const struct ipt_pool_info *info = matchinfo;
21183 +       const struct iphdr *iph = skb->nh.iph;
21184 +
21185 +       if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
21186 +                                               info->flags&IPT_POOL_INV_SRC))
21187 +               return 0;
21188 +
21189 +       if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
21190 +                                               info->flags&IPT_POOL_INV_DST))
21191 +               return 0;
21192 +
21193 +       return 1;
21194 +}
21195 +
21196 +static int checkentry(
21197 +       const char *tablename,
21198 +       const struct ipt_ip *ip,
21199 +       void *matchinfo,
21200 +       unsigned int matchsize,
21201 +       unsigned int hook_mask
21202 +) {
21203 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
21204 +               return 0;
21205 +       return 1;
21206 +}
21207 +
21208 +static struct ipt_match pool_match
21209 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
21210 +
21211 +static int __init init(void)
21212 +{
21213 +       return ipt_register_match(&pool_match);
21214 +}
21215 +
21216 +static void __exit fini(void)
21217 +{
21218 +       ipt_unregister_match(&pool_match);
21219 +}
21220 +
21221 +module_init(init);
21222 +module_exit(fini);
21223 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_psd.c linux-2.4.20/net/ipv4/netfilter/ipt_psd.c
21224 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_psd.c       Thu Jan  1 00:00:00 1970
21225 +++ linux-2.4.20/net/ipv4/netfilter/ipt_psd.c   Wed Sep 24 09:17:01 2003
21226 @@ -0,0 +1,361 @@
21227 +/*
21228 +  This is a module which is used for PSD (portscan detection)
21229 +  Derived from scanlogd v2.1 written by Solar Designer <solar@false.com>
21230 +  and LOG target module.
21231 +
21232 +  Copyright (C) 2000,2001 astaro AG
21233 +
21234 +  This file is distributed under the terms of the GNU General Public
21235 +  License (GPL). Copies of the GPL can be obtained from:
21236 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
21237 +
21238 +  2000-05-04 Markus Hennig <hennig@astaro.de> : initial
21239 +  2000-08-18 Dennis Koslowski <koslowski@astaro.de> : first release
21240 +  2000-12-01 Dennis Koslowski <koslowski@astaro.de> : UDP scans detection added
21241 +  2001-01-02 Dennis Koslowski <koslowski@astaro.de> : output modified
21242 +  2001-02-04 Jan Rekorajski <baggins@pld.org.pl> : converted from target to match
21243 +*/
21244 +
21245 +#include <linux/module.h>
21246 +#include <linux/skbuff.h>
21247 +#include <linux/ip.h>
21248 +#include <net/tcp.h>
21249 +#include <linux/spinlock.h>
21250 +#include <linux/netfilter_ipv4/ip_tables.h>
21251 +#include <linux/netfilter_ipv4/ipt_psd.h>
21252 +
21253 +#if 0
21254 +#define DEBUGP printk
21255 +#else
21256 +#define DEBUGP(format, args...)
21257 +#endif
21258 +
21259 +MODULE_LICENSE("GPL");
21260 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
21261 +
21262 +#define HF_DADDR_CHANGING   0x01
21263 +#define HF_SPORT_CHANGING   0x02
21264 +#define HF_TOS_CHANGING            0x04
21265 +#define HF_TTL_CHANGING            0x08
21266 +            
21267 +/*
21268 + * Information we keep per each target port
21269 + */
21270 +struct port {
21271 +       u_int16_t number;      /* port number */ 
21272 +       u_int8_t proto;        /* protocol number */
21273 +       u_int8_t and_flags;    /* tcp ANDed flags */
21274 +       u_int8_t or_flags;     /* tcp ORed flags */
21275 +};
21276 +
21277 +/*
21278 + * Information we keep per each source address.
21279 + */
21280 +struct host {
21281 +       struct host *next;              /* Next entry with the same hash */
21282 +       clock_t timestamp;              /* Last update time */
21283 +       struct in_addr src_addr;        /* Source address */
21284 +       struct in_addr dest_addr;       /* Destination address */
21285 +       unsigned short src_port;        /* Source port */
21286 +       int count;                      /* Number of ports in the list */
21287 +       int weight;                     /* Total weight of ports in the list */
21288 +       struct port ports[SCAN_MAX_COUNT - 1];  /* List of ports */
21289 +       unsigned char tos;              /* TOS */
21290 +       unsigned char ttl;              /* TTL */
21291 +       unsigned char flags;            /* HF_ flags bitmask */
21292 +};
21293 +
21294 +/*
21295 + * State information.
21296 + */
21297 +static struct {
21298 +       spinlock_t lock;
21299 +       struct host list[LIST_SIZE];    /* List of source addresses */
21300 +       struct host *hash[HASH_SIZE];   /* Hash: pointers into the list */
21301 +       int index;                      /* Oldest entry to be replaced */
21302 +} state;
21303 +
21304 +/*
21305 + * Convert an IP address into a hash table index.
21306 + */
21307 +static inline int hashfunc(struct in_addr addr)
21308 +{
21309 +       unsigned int value;
21310 +       int hash;
21311 +
21312 +       value = addr.s_addr;
21313 +       hash = 0;
21314 +       do {
21315 +               hash ^= value;
21316 +       } while ((value >>= HASH_LOG));
21317 +
21318 +       return hash & (HASH_SIZE - 1);
21319 +}
21320 +
21321 +static int
21322 +ipt_psd_match(const struct sk_buff *pskb,
21323 +             const struct net_device *in,
21324 +             const struct net_device *out,
21325 +             const void *matchinfo,
21326 +             int offset,
21327 +             const void *hdr,
21328 +             u_int16_t datalen,
21329 +             int *hotdrop)
21330 +{
21331 +       struct iphdr *ip_hdr;
21332 +       struct tcphdr *tcp_hdr;
21333 +       struct in_addr addr;
21334 +       u_int16_t src_port,dest_port;
21335 +       u_int8_t tcp_flags, proto;
21336 +       clock_t now;
21337 +       struct host *curr, *last, **head;
21338 +       int hash, index, count;
21339 +
21340 +       /* Parameters from userspace */
21341 +       const struct ipt_psd_info *psdinfo = matchinfo;
21342 +
21343 +       /* IP header */
21344 +       ip_hdr = pskb->nh.iph;
21345 +
21346 +       /* Sanity check */
21347 +       if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
21348 +               DEBUGP("PSD: sanity check failed\n");
21349 +               return 0;
21350 +       }
21351 +
21352 +       /* TCP or UDP ? */
21353 +       proto = ip_hdr->protocol;
21354 +
21355 +       if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
21356 +               DEBUGP("PSD: protocol not supported\n");
21357 +               return 0;
21358 +       }
21359 +
21360 +       /* Get the source address, source & destination ports, and TCP flags */
21361 +
21362 +       addr.s_addr = ip_hdr->saddr;
21363 +
21364 +       tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
21365 +
21366 +       /* Yep, it´s dirty */
21367 +       src_port = tcp_hdr->source;
21368 +       dest_port = tcp_hdr->dest;
21369 +
21370 +       if (proto == IPPROTO_TCP) {
21371 +               tcp_flags = *((u_int8_t*)tcp_hdr + 13);
21372 +       }
21373 +       else {
21374 +               tcp_flags = 0x00;
21375 +       }
21376 +
21377 +       /* We're using IP address 0.0.0.0 for a special purpose here, so don't let
21378 +        * them spoof us. [DHCP needs this feature - HW] */
21379 +       if (!addr.s_addr) {
21380 +               DEBUGP("PSD: spoofed source address (0.0.0.0)\n");
21381 +               return 0;
21382 +       }
21383 +
21384 +       /* Use jiffies here not to depend on someone setting the time while we're
21385 +        * running; we need to be careful with possible return value overflows. */
21386 +       now = jiffies;
21387 +
21388 +       spin_lock(&state.lock);
21389 +
21390 +       /* Do we know this source address already? */
21391 +       count = 0;
21392 +       last = NULL;
21393 +       if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
21394 +               do {
21395 +                       if (curr->src_addr.s_addr == addr.s_addr) break;
21396 +                       count++;
21397 +                       if (curr->next) last = curr;
21398 +               } while ((curr = curr->next));
21399 +
21400 +       if (curr) {
21401 +
21402 +               /* We know this address, and the entry isn't too old. Update it. */
21403 +               if (now - curr->timestamp <= (psdinfo->delay_threshold*HZ)/100 &&
21404 +                   time_after_eq(now, curr->timestamp)) {
21405 +
21406 +                       /* Just update the appropriate list entry if we've seen this port already */
21407 +                       for (index = 0; index < curr->count; index++) {
21408 +                               if (curr->ports[index].number == dest_port) {
21409 +                                       curr->ports[index].proto = proto;
21410 +                                       curr->ports[index].and_flags &= tcp_flags;
21411 +                                       curr->ports[index].or_flags |= tcp_flags;
21412 +                                       goto out_no_match;
21413 +                               }
21414 +                       }
21415 +
21416 +                       /* TCP/ACK and/or TCP/RST to a new port? This could be an outgoing connection. */
21417 +                       if (proto == IPPROTO_TCP && (tcp_hdr->ack || tcp_hdr->rst))
21418 +                               goto out_no_match;
21419 +
21420 +                       /* Packet to a new port, and not TCP/ACK: update the timestamp */
21421 +                       curr->timestamp = now;
21422 +
21423 +                       /* Logged this scan already? Then drop the packet. */
21424 +                       if (curr->weight >= psdinfo->weight_threshold)
21425 +                               goto out_match;
21426 +
21427 +                       /* Specify if destination address, source port, TOS or TTL are not fixed */
21428 +                       if (curr->dest_addr.s_addr != ip_hdr->daddr)
21429 +                               curr->flags |= HF_DADDR_CHANGING;
21430 +                       if (curr->src_port != src_port)
21431 +                               curr->flags |= HF_SPORT_CHANGING;
21432 +                       if (curr->tos != ip_hdr->tos)
21433 +                               curr->flags |= HF_TOS_CHANGING;
21434 +                       if (curr->ttl != ip_hdr->ttl)
21435 +                               curr->flags |= HF_TTL_CHANGING;
21436 +
21437 +                       /* Update the total weight */
21438 +                       curr->weight += (ntohs(dest_port) < 1024) ?
21439 +                               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
21440 +
21441 +                       /* Got enough destination ports to decide that this is a scan? */
21442 +                       /* Then log it and drop the packet. */
21443 +                       if (curr->weight >= psdinfo->weight_threshold)
21444 +                               goto out_match;
21445 +
21446 +                       /* Remember the new port */
21447 +                       if (curr->count < SCAN_MAX_COUNT) {
21448 +                               curr->ports[curr->count].number = dest_port;
21449 +                               curr->ports[curr->count].proto = proto;
21450 +                               curr->ports[curr->count].and_flags = tcp_flags;
21451 +                               curr->ports[curr->count].or_flags = tcp_flags;
21452 +                               curr->count++;
21453 +                       }
21454 +
21455 +                       goto out_no_match;
21456 +               }
21457 +
21458 +               /* We know this address, but the entry is outdated. Mark it unused, and
21459 +                * remove from the hash table. We'll allocate a new entry instead since
21460 +                * this one might get re-used too soon. */
21461 +               curr->src_addr.s_addr = 0;
21462 +               if (last)
21463 +                       last->next = last->next->next;
21464 +               else if (*head)
21465 +                       *head = (*head)->next;
21466 +               last = NULL;
21467 +       }
21468 +
21469 +       /* We don't need an ACK from a new source address */
21470 +       if (proto == IPPROTO_TCP && tcp_hdr->ack)
21471 +               goto out_no_match;
21472 +
21473 +       /* Got too many source addresses with the same hash value? Then remove the
21474 +        * oldest one from the hash table, so that they can't take too much of our
21475 +        * CPU time even with carefully chosen spoofed IP addresses. */
21476 +       if (count >= HASH_MAX && last) last->next = NULL;
21477 +
21478 +       /* We're going to re-use the oldest list entry, so remove it from the hash
21479 +        * table first (if it is really already in use, and isn't removed from the
21480 +        * hash table already because of the HASH_MAX check above). */
21481 +
21482 +       /* First, find it */
21483 +       if (state.list[state.index].src_addr.s_addr)
21484 +               head = &state.hash[hashfunc(state.list[state.index].src_addr)];
21485 +       else
21486 +               head = &last;
21487 +       last = NULL;
21488 +       if ((curr = *head))
21489 +       do {
21490 +               if (curr == &state.list[state.index]) break;
21491 +               last = curr;
21492 +       } while ((curr = curr->next));
21493 +
21494 +       /* Then, remove it */
21495 +       if (curr) {
21496 +               if (last)
21497 +                       last->next = last->next->next;
21498 +               else if (*head)
21499 +                       *head = (*head)->next;
21500 +       }
21501 +
21502 +       /* Get our list entry */
21503 +       curr = &state.list[state.index++];
21504 +       if (state.index >= LIST_SIZE) state.index = 0;
21505 +
21506 +       /* Link it into the hash table */
21507 +       head = &state.hash[hash];
21508 +       curr->next = *head;
21509 +       *head = curr;
21510 +
21511 +       /* And fill in the fields */
21512 +       curr->timestamp = now;
21513 +       curr->src_addr = addr;
21514 +       curr->dest_addr.s_addr = ip_hdr->daddr;
21515 +       curr->src_port = src_port;
21516 +       curr->count = 1;
21517 +       curr->weight = (ntohs(dest_port) < 1024) ?
21518 +               psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
21519 +       curr->ports[0].number = dest_port;
21520 +       curr->ports[0].proto = proto;
21521 +       curr->ports[0].and_flags = tcp_flags;
21522 +       curr->ports[0].or_flags = tcp_flags;
21523 +       curr->tos = ip_hdr->tos;
21524 +       curr->ttl = ip_hdr->ttl;
21525 +
21526 +out_no_match:
21527 +       spin_unlock(&state.lock);
21528 +       return 0;
21529 +
21530 +out_match:
21531 +       spin_unlock(&state.lock);
21532 +       return 1;
21533 +}
21534 +
21535 +static int ipt_psd_checkentry(const char *tablename,
21536 +                             const struct ipt_ip *e,
21537 +                             void *matchinfo,
21538 +                             unsigned int matchsize,
21539 +                             unsigned int hook_mask)
21540 +{
21541 +/*     const struct ipt_psd_info *psdinfo = targinfo;*/
21542 +
21543 +       /* we accept TCP only */
21544 +/*     if (e->ip.proto != IPPROTO_TCP) { */
21545 +/*             DEBUGP("PSD: specified protocol may be TCP only\n"); */
21546 +/*             return 0; */
21547 +/*     } */
21548 +
21549 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
21550 +               DEBUGP("PSD: matchsize %u != %u\n",
21551 +                      matchsize,
21552 +                      IPT_ALIGN(sizeof(struct ipt_psd_info)));
21553 +               return 0;
21554 +       }
21555 +
21556 +       return 1;
21557 +}
21558 +
21559 +static struct ipt_match ipt_psd_reg = { 
21560 +       {NULL, NULL},
21561 +       "psd",
21562 +       ipt_psd_match,
21563 +       ipt_psd_checkentry,
21564 +       NULL,
21565 +       THIS_MODULE };
21566 +
21567 +static int __init init(void)
21568 +{
21569 +       if (ipt_register_match(&ipt_psd_reg))
21570 +               return -EINVAL;
21571 +
21572 +       memset(&state, 0, sizeof(state));
21573 +
21574 +       spin_lock_init(&(state.lock));
21575 +
21576 +       printk("netfilter PSD loaded - (c) astaro AG\n");
21577 +       return 0;
21578 +}
21579 +
21580 +static void __exit fini(void)
21581 +{
21582 +       ipt_unregister_match(&ipt_psd_reg);
21583 +       printk("netfilter PSD unloaded - (c) astaro AG\n");
21584 +}
21585 +
21586 +module_init(init);
21587 +module_exit(fini);
21588 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_quota.c linux-2.4.20/net/ipv4/netfilter/ipt_quota.c
21589 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_quota.c     Thu Jan  1 00:00:00 1970
21590 +++ linux-2.4.20/net/ipv4/netfilter/ipt_quota.c Wed Sep 24 09:17:03 2003
21591 @@ -0,0 +1,81 @@
21592 +/* 
21593 + * netfilter module to enforce network quotas
21594 + *
21595 + * Sam Johnston <samj@samj.net>
21596 + */
21597 +#include <linux/module.h>
21598 +#include <linux/skbuff.h>
21599 +#include <linux/spinlock.h>
21600 +#include <linux/interrupt.h>
21601 +
21602 +#include <linux/netfilter_ipv4/ip_tables.h>
21603 +#include <linux/netfilter_ipv4/ipt_quota.h>
21604 +
21605 +MODULE_LICENSE("GPL");
21606 +
21607 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
21608 +
21609 +static int
21610 +match(const struct sk_buff *skb,
21611 +      const struct net_device *in,
21612 +      const struct net_device *out,
21613 +      const void *matchinfo,
21614 +      int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
21615 +{
21616 +
21617 +        struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
21618 +
21619 +        spin_lock_bh(&quota_lock);
21620 +
21621 +        if (q->quota >= datalen) {
21622 +                /* we can afford this one */
21623 +                q->quota -= datalen;
21624 +                spin_unlock_bh(&quota_lock);
21625 +
21626 +#ifdef DEBUG_IPT_QUOTA
21627 +                printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
21628 +#endif
21629 +                return 1;
21630 +        }
21631 +
21632 +        /* so we do not allow even small packets from now on */
21633 +        q->quota = 0;
21634 +
21635 +#ifdef DEBUG_IPT_QUOTA
21636 +        printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
21637 +#endif
21638 +
21639 +        spin_unlock_bh(&quota_lock);
21640 +        return 0;
21641 +}
21642 +
21643 +static int
21644 +checkentry(const char *tablename,
21645 +           const struct ipt_ip *ip,
21646 +           void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
21647 +{
21648 +        /* TODO: spinlocks? sanity checks? */
21649 +        if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
21650 +                return 0;
21651 +
21652 +        return 1;
21653 +}
21654 +
21655 +static struct ipt_match quota_match
21656 +    = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
21657 +
21658 +static int __init
21659 +init(void)
21660 +{
21661 +        return ipt_register_match(&quota_match);
21662 +}
21663 +
21664 +static void __exit
21665 +fini(void)
21666 +{
21667 +        ipt_unregister_match(&quota_match);
21668 +}
21669 +
21670 +module_init(init);
21671 +module_exit(fini);
21672 +
21673 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_random.c linux-2.4.20/net/ipv4/netfilter/ipt_random.c
21674 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_random.c    Thu Jan  1 00:00:00 1970
21675 +++ linux-2.4.20/net/ipv4/netfilter/ipt_random.c        Wed Sep 24 09:17:05 2003
21676 @@ -0,0 +1,96 @@
21677 +/*
21678 +  This is a module which is used for a "random" match support.
21679 +  This file is distributed under the terms of the GNU General Public
21680 +  License (GPL). Copies of the GPL can be obtained from:
21681 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
21682 +
21683 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
21684 +*/
21685 +
21686 +#include <linux/module.h>
21687 +#include <linux/skbuff.h>
21688 +#include <linux/ip.h>
21689 +#include <linux/random.h>
21690 +#include <net/tcp.h>
21691 +#include <linux/spinlock.h>
21692 +#include <linux/netfilter_ipv4/ip_tables.h>
21693 +#include <linux/netfilter_ipv4/ipt_random.h>
21694 +
21695 +MODULE_LICENSE("GPL");
21696 +
21697 +static int
21698 +ipt_rand_match(const struct sk_buff *pskb,
21699 +              const struct net_device *in,
21700 +              const struct net_device *out,
21701 +              const void *matchinfo,
21702 +              int offset,
21703 +              const void *hdr,
21704 +              u_int16_t datalen,
21705 +              int *hotdrop)
21706 +{
21707 +       /* Parameters from userspace */
21708 +       const struct ipt_rand_info *info = matchinfo;
21709 +       u_int8_t random_number;
21710 +
21711 +       /* get 1 random number from the kernel random number generation routine */
21712 +       get_random_bytes((void *)(&random_number), 1);
21713 +
21714 +       /* Do we match ? */
21715 +       if (random_number <= info->average)
21716 +               return 1;
21717 +       else
21718 +               return 0;
21719 +}
21720 +
21721 +static int
21722 +ipt_rand_checkentry(const char *tablename,
21723 +                  const struct ipt_ip *e,
21724 +                  void *matchinfo,
21725 +                  unsigned int matchsize,
21726 +                  unsigned int hook_mask)
21727 +{
21728 +       /* Parameters from userspace */
21729 +       const struct ipt_rand_info *info = matchinfo;
21730 +
21731 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rand_info))) {
21732 +               printk("ipt_random: matchsize %u != %u\n", matchsize,
21733 +                      IPT_ALIGN(sizeof(struct ipt_rand_info)));
21734 +               return 0;
21735 +       }
21736 +
21737 +       /* must be  1 <= average % <= 99 */
21738 +       /* 1  x 2.55 = 2   */
21739 +       /* 99 x 2.55 = 252 */
21740 +       if ((info->average < 2) || (info->average > 252)) {
21741 +               printk("ipt_random:  invalid average %u\n", info->average);
21742 +               return 0;
21743 +       }
21744 +
21745 +       return 1;
21746 +}
21747 +
21748 +static struct ipt_match ipt_rand_reg = { 
21749 +       {NULL, NULL},
21750 +       "random",
21751 +       ipt_rand_match,
21752 +       ipt_rand_checkentry,
21753 +       NULL,
21754 +       THIS_MODULE };
21755 +
21756 +static int __init init(void)
21757 +{
21758 +       if (ipt_register_match(&ipt_rand_reg))
21759 +               return -EINVAL;
21760 +
21761 +       printk("ipt_random match loaded\n");
21762 +       return 0;
21763 +}
21764 +
21765 +static void __exit fini(void)
21766 +{
21767 +       ipt_unregister_match(&ipt_rand_reg);
21768 +       printk("ipt_random match unloaded\n");
21769 +}
21770 +
21771 +module_init(init);
21772 +module_exit(fini);
21773 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_realm.c linux-2.4.20/net/ipv4/netfilter/ipt_realm.c
21774 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_realm.c     Thu Jan  1 00:00:00 1970
21775 +++ linux-2.4.20/net/ipv4/netfilter/ipt_realm.c Wed Sep 24 09:17:09 2003
21776 @@ -0,0 +1,68 @@
21777 +/* Kernel module to match realm from routing. */
21778 +#include <linux/module.h>
21779 +#include <linux/skbuff.h>
21780 +#include <linux/netdevice.h>
21781 +#include <net/route.h>
21782 +
21783 +#include <linux/netfilter_ipv4/ipt_realm.h>
21784 +#include <linux/netfilter_ipv4/ip_tables.h>
21785 +
21786 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
21787 +MODULE_LICENSE("GPL");
21788 +
21789 +static int
21790 +match(const struct sk_buff *skb,
21791 +      const struct net_device *in,
21792 +      const struct net_device *out,
21793 +      const void *matchinfo,
21794 +      int offset,
21795 +      const void *hdr,
21796 +      u_int16_t datalen,
21797 +      int *hotdrop)
21798 +{
21799 +       const struct ipt_realm_info *info = matchinfo;
21800 +       struct dst_entry *dst = skb->dst;
21801 +       u32 id;
21802 +    
21803 +       if(dst == NULL)
21804 +               return 0;
21805 +       id = dst->tclassid;
21806 +
21807 +       return (info->id == (id & info->mask)) ^ info->invert;
21808 +}
21809 +
21810 +static int check(const char *tablename,
21811 +                 const struct ipt_ip *ip,
21812 +                 void *matchinfo,
21813 +                 unsigned int matchsize,
21814 +                 unsigned int hook_mask)
21815 +{
21816 +       if (hook_mask
21817 +           & ~((1 << NF_IP_POST_ROUTING) | (1 << NF_IP_FORWARD) |
21818 +               (1 << NF_IP_LOCAL_OUT)| (1 << NF_IP_LOCAL_IN))) {
21819 +               printk("ipt_realm: only valid for POST_ROUTING, LOCAL_OUT, "
21820 +                      "LOCAL_IN or FORWARD.\n");
21821 +               return 0;
21822 +       }
21823 +
21824 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
21825 +               return 0;
21826 +
21827 +       return 1;
21828 +}
21829 +
21830 +static struct ipt_match realm_match
21831 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
21832 +
21833 +static int __init init(void)
21834 +{
21835 +       return ipt_register_match(&realm_match);
21836 +}
21837 +
21838 +static void __exit fini(void)
21839 +{
21840 +       ipt_unregister_match(&realm_match);
21841 +}
21842 +
21843 +module_init(init);
21844 +module_exit(fini);
21845 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_recent.c linux-2.4.20/net/ipv4/netfilter/ipt_recent.c
21846 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_recent.c    Thu Jan  1 00:00:00 1970
21847 +++ linux-2.4.20/net/ipv4/netfilter/ipt_recent.c        Wed Sep 24 09:16:20 2003
21848 @@ -0,0 +1,1002 @@
21849 +/* Kernel module to check if the source address has been seen recently. */
21850 +/* Copyright 2002-2003, Stephen Frost */
21851 +/* Author: Stephen Frost <sfrost@snowman.net> */
21852 +/* Project Page: http://snowman.net/projects/ipt_recent/ */
21853 +/* This software is distributed under the terms of the GPL, Version 2 */
21854 +/* This copyright does not cover user programs that use kernel services
21855 + * by normal system calls. */
21856 +
21857 +#include <linux/module.h>
21858 +#include <linux/skbuff.h>
21859 +#include <linux/proc_fs.h>
21860 +#include <linux/spinlock.h>
21861 +#include <linux/interrupt.h>
21862 +#include <asm/uaccess.h>
21863 +#include <linux/ctype.h>
21864 +#include <linux/ip.h>
21865 +#include <linux/vmalloc.h>
21866 +
21867 +#include <linux/netfilter_ipv4/ip_tables.h>
21868 +#include <linux/netfilter_ipv4/ipt_recent.h>
21869 +
21870 +#undef DEBUG
21871 +#define HASH_LOG 9
21872 +
21873 +/* Defaults, these can be overridden on the module command-line. */
21874 +static int ip_list_tot = 100;
21875 +static int ip_pkt_list_tot = 20;
21876 +static int ip_list_hash_size = 0;
21877 +static int ip_list_perms = 0644;
21878 +#ifdef DEBUG
21879 +static int debug = 1;
21880 +#endif
21881 +
21882 +static char version[] =
21883 +KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>.  http://snowman.net/projects/ipt_recent/\n";
21884 +
21885 +MODULE_AUTHOR("Stephen Frost <sfrost@snowman.net>");
21886 +MODULE_DESCRIPTION("IP tables recently seen matching module " RECENT_VER);
21887 +MODULE_LICENSE("GPL");
21888 +MODULE_PARM(ip_list_tot,"i");
21889 +MODULE_PARM(ip_pkt_list_tot,"i");
21890 +MODULE_PARM(ip_list_hash_size,"i");
21891 +MODULE_PARM(ip_list_perms,"i");
21892 +#ifdef DEBUG
21893 +MODULE_PARM(debug,"i");
21894 +MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
21895 +#endif
21896 +MODULE_PARM_DESC(ip_list_tot,"number of IPs to remember per list");
21897 +MODULE_PARM_DESC(ip_pkt_list_tot,"number of packets per IP to remember");
21898 +MODULE_PARM_DESC(ip_list_hash_size,"size of hash table used to look up IPs");
21899 +MODULE_PARM_DESC(ip_list_perms,"permissions on /proc/net/ipt_recent/* files");
21900 +
21901 +/* Structure of our list of recently seen addresses. */
21902 +struct recent_ip_list {
21903 +       u_int32_t addr;
21904 +       u_int8_t  ttl;
21905 +       u_int32_t last_seen;
21906 +       u_int32_t *last_pkts;
21907 +       u_int32_t oldest_pkt;
21908 +       u_int32_t hash_entry;
21909 +       u_int32_t time_pos;
21910 +};
21911 +
21912 +struct time_info_list {
21913 +       u_int32_t position;
21914 +       u_int32_t time;
21915 +};
21916 +
21917 +/* Structure of our linked list of tables of recent lists. */
21918 +struct recent_ip_tables {
21919 +       char name[IPT_RECENT_NAME_LEN];
21920 +       int count;
21921 +       int time_pos;
21922 +       struct recent_ip_list *table;
21923 +       struct recent_ip_tables *next;
21924 +       spinlock_t list_lock;
21925 +       int *hash_table;
21926 +       struct time_info_list *time_info;
21927 +#ifdef CONFIG_PROC_FS
21928 +       struct proc_dir_entry *status_proc;
21929 +#endif /* CONFIG_PROC_FS */
21930 +};
21931 +
21932 +/* Our current list of addresses we have recently seen.
21933 + * Only added to on a --set, and only updated on --set || --update 
21934 + */
21935 +static struct recent_ip_tables *r_tables = NULL;
21936 +
21937 +/* We protect r_list with this spinlock so two processors are not modifying
21938 + * the list at the same time. 
21939 + */
21940 +static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
21941 +
21942 +#ifdef CONFIG_PROC_FS
21943 +/* Our /proc/net/ipt_recent entry */
21944 +static struct proc_dir_entry *proc_net_ipt_recent = NULL;
21945 +#endif
21946 +
21947 +/* Function declaration for later. */
21948 +static int
21949 +match(const struct sk_buff *skb,
21950 +      const struct net_device *in,
21951 +      const struct net_device *out,
21952 +      const void *matchinfo,
21953 +      int offset,
21954 +      const void *hdr,
21955 +      u_int16_t datalen,
21956 +      int *hotdrop);
21957 +
21958 +/* Function to hash a given address into the hash table of table_size size */
21959 +int hash_func(unsigned int addr, int table_size)
21960 +{
21961 +       int result = 0;
21962 +       unsigned int value = addr;
21963 +       do { result ^= value; } while((value >>= HASH_LOG));
21964 +
21965 +#ifdef DEBUG
21966 +       if(debug) printk(KERN_INFO RECENT_NAME ": %d = hash_func(%u,%d)\n",
21967 +                        result & (table_size - 1),
21968 +                        addr,
21969 +                        table_size);
21970 +#endif
21971 +
21972 +       return(result & (table_size - 1));
21973 +}
21974 +
21975 +#ifdef CONFIG_PROC_FS
21976 +/* This is the function which produces the output for our /proc output
21977 + * interface which lists each IP address, the last seen time and the 
21978 + * other recent times the address was seen.
21979 + */
21980 +
21981 +static int ip_recent_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
21982 +{
21983 +       int len = 0, count, last_len = 0, pkt_count;
21984 +       off_t pos = 0;
21985 +       off_t begin = 0;
21986 +       struct recent_ip_tables *curr_table;
21987 +
21988 +       curr_table = (struct recent_ip_tables*) data;
21989 +
21990 +       spin_lock_bh(&curr_table->list_lock);
21991 +       for(count = 0; count < ip_list_tot; count++) {
21992 +               if(!curr_table->table[count].addr) continue;
21993 +               last_len = len;
21994 +               len += sprintf(buffer+len,"src=%u.%u.%u.%u ",NIPQUAD(curr_table->table[count].addr));
21995 +               len += sprintf(buffer+len,"ttl: %u ",curr_table->table[count].ttl);
21996 +               len += sprintf(buffer+len,"last_seen: %u ",curr_table->table[count].last_seen);
21997 +               len += sprintf(buffer+len,"oldest_pkt: %u ",curr_table->table[count].oldest_pkt);
21998 +               len += sprintf(buffer+len,"last_pkts: %u",curr_table->table[count].last_pkts[0]);
21999 +               for(pkt_count = 1; pkt_count < ip_pkt_list_tot; pkt_count++) {
22000 +                       if(!curr_table->table[count].last_pkts[pkt_count]) break;
22001 +                       len += sprintf(buffer+len,", %u",curr_table->table[count].last_pkts[pkt_count]);
22002 +               }
22003 +               len += sprintf(buffer+len,"\n");
22004 +               pos = begin + len;
22005 +               if(pos < offset) { len = 0; begin = pos; }
22006 +               if(pos > offset + length) { len = last_len; break; }
22007 +       }
22008 +
22009 +       *start = buffer + (offset - begin);
22010 +       len -= (offset - begin);
22011 +       if(len > length) len = length;
22012 +
22013 +       spin_unlock_bh(&curr_table->list_lock);
22014 +       return len;
22015 +}
22016 +
22017 +/* ip_recent_ctrl provides an interface for users to modify the table
22018 + * directly.  This allows adding entries, removing entries, and
22019 + * flushing the entire table.
22020 + * This is done by opening up the appropriate table for writing and
22021 + * sending one of:
22022 + * xx.xx.xx.xx   -- Add entry to table with current time
22023 + * +xx.xx.xx.xx  -- Add entry to table with current time
22024 + * -xx.xx.xx.xx  -- Remove entry from table
22025 + * clear         -- Flush table, remove all entries
22026 + */
22027 +
22028 +static int ip_recent_ctrl(struct file *file, const char *input, unsigned long size, void *data)
22029 +{
22030 +       static const u_int32_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
22031 +       u_int32_t val;
22032 +       int base, used = 0;
22033 +       char c, *cp;
22034 +       union iaddr {
22035 +               uint8_t bytes[4];
22036 +               uint32_t word;
22037 +       } res;
22038 +       uint8_t *pp = res.bytes;
22039 +       int digit;
22040 +
22041 +       char buffer[20];
22042 +       int len, check_set = 0, count;
22043 +       u_int32_t addr = 0;
22044 +       struct sk_buff *skb;
22045 +       struct ipt_recent_info *info;
22046 +       struct recent_ip_tables *curr_table;
22047 +
22048 +       curr_table = (struct recent_ip_tables*) data;
22049 +
22050 +       if(size > 20) len = 20; else len = size;
22051 +
22052 +       if(copy_from_user(buffer,input,len)) return -EFAULT;
22053 +
22054 +       if(len < 20) buffer[len] = '\0';
22055 +
22056 +#ifdef DEBUG
22057 +       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl len: %d, input: `%.20s'\n",len,buffer);
22058 +#endif
22059 +
22060 +       cp = buffer;
22061 +       while(isspace(*cp)) { cp++; used++; if(used >= len-5) return used; }
22062 +
22063 +       /* Check if we are asked to flush the entire table */
22064 +       if(!memcmp(cp,"clear",5)) {
22065 +               used += 5;
22066 +               spin_lock_bh(&curr_table->list_lock);
22067 +               curr_table->time_pos = 0;
22068 +               for(count = 0; count < ip_list_hash_size; count++) {
22069 +                       curr_table->hash_table[count] = -1;
22070 +               }
22071 +               for(count = 0; count < ip_list_tot; count++) {
22072 +                       curr_table->table[count].last_seen = 0;
22073 +                       curr_table->table[count].addr = 0;
22074 +                       curr_table->table[count].ttl = 0;
22075 +                       memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
22076 +                       curr_table->table[count].oldest_pkt = 0;
22077 +                       curr_table->table[count].time_pos = 0;
22078 +                       curr_table->time_info[count].position = count;
22079 +                       curr_table->time_info[count].time = 0;
22080 +               }
22081 +               spin_unlock_bh(&curr_table->list_lock);
22082 +               return used;
22083 +       }
22084 +
22085 +        check_set = IPT_RECENT_SET;
22086 +       switch(*cp) {
22087 +               case '+': check_set = IPT_RECENT_SET; cp++; used++; break;
22088 +               case '-': check_set = IPT_RECENT_REMOVE; cp++; used++; break;
22089 +               default: if(!isdigit(*cp)) return (used+1); break;
22090 +       }
22091 +
22092 +#ifdef DEBUG
22093 +       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl cp: `%c', check_set: %d\n",*cp,check_set);
22094 +#endif
22095 +       /* Get addr (effectively inet_aton()) */
22096 +       /* Shamelessly stolen from libc, a function in the kernel for doing
22097 +        * this would, of course, be greatly preferred, but our options appear
22098 +        * to be rather limited, so we will just do it ourselves here.
22099 +        */
22100 +       res.word = 0;
22101 +
22102 +       c = *cp;
22103 +       for(;;) {
22104 +               if(!isdigit(c)) return used;
22105 +               val = 0; base = 10; digit = 0;
22106 +               if(c == '0') {
22107 +                       c = *++cp;
22108 +                       if(c == 'x' || c == 'X') base = 16, c = *++cp;
22109 +                       else { base = 8; digit = 1; }
22110 +               }
22111 +               for(;;) {
22112 +                       if(isascii(c) && isdigit(c)) {
22113 +                               if(base == 8 && (c == '8' || c == '0')) return used;
22114 +                               val = (val * base) + (c - '0');
22115 +                               c = *++cp;
22116 +                               digit = 1;
22117 +                       } else if(base == 16 && isascii(c) && isxdigit(c)) {
22118 +                               val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
22119 +                               c = *++cp;
22120 +                               digit = 1;
22121 +                       } else break;
22122 +               }
22123 +               if(c == '.') {
22124 +                       if(pp > res.bytes + 2 || val > 0xff) return used;
22125 +                       *pp++ = val;
22126 +                       c = *++cp;
22127 +               } else break;
22128 +       }
22129 +       used = cp - buffer;
22130 +       if(c != '\0' && (!isascii(c) || !isspace(c))) return used;
22131 +       if(c == '\n') used++;
22132 +       if(!digit) return used;
22133 +
22134 +       if(val > max[pp - res.bytes]) return used;
22135 +       addr = res.word | htonl(val);
22136 +
22137 +       if(!addr && check_set == IPT_RECENT_SET) return used;
22138 +
22139 +#ifdef DEBUG
22140 +       if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl c: %c, addr: %u used: %d\n",c,addr,used);
22141 +#endif
22142 +
22143 +       /* Set up and just call match */
22144 +       info = kmalloc(sizeof(struct ipt_recent_info),GFP_KERNEL);
22145 +       if(!info) { return -ENOMEM; }
22146 +       info->seconds = 0;
22147 +       info->hit_count = 0;
22148 +       info->check_set = check_set;
22149 +       info->invert = 0;
22150 +       info->side = IPT_RECENT_SOURCE;
22151 +       strncpy(info->name,curr_table->name,IPT_RECENT_NAME_LEN);
22152 +       info->name[IPT_RECENT_NAME_LEN-1] = '\0';
22153 +
22154 +       skb = kmalloc(sizeof(struct sk_buff),GFP_KERNEL);
22155 +       if (!skb) {
22156 +               used = -ENOMEM;
22157 +               goto out_free_info;
22158 +       }
22159 +       skb->nh.iph = kmalloc(sizeof(struct iphdr),GFP_KERNEL);
22160 +       if (!skb->nh.iph) {
22161 +               used = -ENOMEM;
22162 +               goto out_free_skb;
22163 +       }
22164 +
22165 +       skb->nh.iph->saddr = addr;
22166 +       skb->nh.iph->daddr = 0;
22167 +       /* Clear ttl since we have no way of knowing it */
22168 +       skb->nh.iph->ttl = 0;
22169 +       match(skb,NULL,NULL,info,0,NULL,sizeof(struct ipt_recent_info),NULL);
22170 +
22171 +       kfree(skb->nh.iph);
22172 +out_free_skb:
22173 +       kfree(skb);
22174 +out_free_info:
22175 +       kfree(info);
22176 +
22177 +#ifdef DEBUG
22178 +       if(debug) printk(KERN_INFO RECENT_NAME ": Leaving ip_recent_ctrl addr: %u used: %d\n",addr,used);
22179 +#endif
22180 +       return used;
22181 +}
22182 +
22183 +#endif /* CONFIG_PROC_FS */
22184 +
22185 +/* 'match' is our primary function, called by the kernel whenever a rule is
22186 + * hit with our module as an option to it.
22187 + * What this function does depends on what was specifically asked of it by
22188 + * the user:
22189 + * --set -- Add or update last seen time of the source address of the packet
22190 + *   -- matchinfo->check_set == IPT_RECENT_SET
22191 + * --rcheck -- Just check if the source address is in the list
22192 + *   -- matchinfo->check_set == IPT_RECENT_CHECK
22193 + * --update -- If the source address is in the list, update last_seen
22194 + *   -- matchinfo->check_set == IPT_RECENT_UPDATE
22195 + * --remove -- If the source address is in the list, remove it
22196 + *   -- matchinfo->check_set == IPT_RECENT_REMOVE
22197 + * --seconds -- Option to --rcheck/--update, only match if last_seen within seconds
22198 + *   -- matchinfo->seconds
22199 + * --hitcount -- Option to --rcheck/--update, only match if seen hitcount times
22200 + *   -- matchinfo->hit_count
22201 + * --seconds and --hitcount can be combined
22202 + */
22203 +static int
22204 +match(const struct sk_buff *skb,
22205 +      const struct net_device *in,
22206 +      const struct net_device *out,
22207 +      const void *matchinfo,
22208 +      int offset,
22209 +      const void *hdr,
22210 +      u_int16_t datalen,
22211 +      int *hotdrop)
22212 +{
22213 +       int pkt_count, hits_found, ans;
22214 +       unsigned long now;
22215 +       const struct ipt_recent_info *info = matchinfo;
22216 +       u_int32_t addr = 0, time_temp;
22217 +       u_int8_t ttl = skb->nh.iph->ttl;
22218 +       int *hash_table;
22219 +       int orig_hash_result, hash_result, temp, location = 0, time_loc, end_collision_chain = -1;
22220 +       struct time_info_list *time_info;
22221 +       struct recent_ip_tables *curr_table;
22222 +       struct recent_ip_tables *last_table;
22223 +       struct recent_ip_list *r_list;
22224 +
22225 +#ifdef DEBUG
22226 +       if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");
22227 +#endif
22228 +
22229 +       /* Default is false ^ info->invert */
22230 +       ans = info->invert;
22231 +
22232 +#ifdef DEBUG
22233 +       if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);
22234 +#endif
22235 +
22236 +       /* if out != NULL then routing has been done and TTL changed.
22237 +        * We change it back here internally for match what came in before routing. */
22238 +       if(out) ttl++;
22239 +
22240 +       /* Find the right table */
22241 +       spin_lock_bh(&recent_lock);
22242 +       curr_table = r_tables;
22243 +       while( (last_table = curr_table) && strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (curr_table = curr_table->next) );
22244 +
22245 +#ifdef DEBUG
22246 +       if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);
22247 +#endif
22248 +
22249 +       spin_unlock_bh(&recent_lock);
22250 +
22251 +       /* Table with this name not found, match impossible */
22252 +       if(!curr_table) { return ans; }
22253 +
22254 +       /* Make sure no one is changing the list while we work with it */
22255 +       spin_lock_bh(&curr_table->list_lock);
22256 +
22257 +       r_list = curr_table->table;
22258 +       if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;
22259 +
22260 +       if(!addr) { 
22261 +#ifdef DEBUG
22262 +               if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);
22263 +#endif
22264 +               spin_unlock_bh(&curr_table->list_lock);
22265 +               return ans;
22266 +       }
22267 +
22268 +#ifdef DEBUG
22269 +       if(debug) printk(KERN_INFO RECENT_NAME ": match(): checking table, addr: %u, ttl: %u, orig_ttl: %u\n",addr,ttl,skb->nh.iph->ttl);
22270 +#endif
22271 +
22272 +       /* Get jiffies now in case they changed while we were waiting for a lock */
22273 +       now = jiffies;
22274 +       hash_table = curr_table->hash_table;
22275 +       time_info = curr_table->time_info;
22276 +
22277 +       orig_hash_result = hash_result = hash_func(addr,ip_list_hash_size);
22278 +       /* Hash entry at this result used */
22279 +       /* Check for TTL match if requested.  If TTL is zero then a match would never
22280 +        * happen, so match regardless of existing TTL in that case.  Zero means the
22281 +        * entry was added via the /proc interface anyway, so we will just use the
22282 +        * first TTL we get for that IP address. */
22283 +       if(info->check_set & IPT_RECENT_TTL) {
22284 +               while(hash_table[hash_result] != -1 && !(r_list[hash_table[hash_result]].addr == addr &&
22285 +                       (!r_list[hash_table[hash_result]].ttl || r_list[hash_table[hash_result]].ttl == ttl))) {
22286 +                       /* Collision in hash table */
22287 +                       hash_result = (hash_result + 1) % ip_list_hash_size;
22288 +               }
22289 +       } else {
22290 +               while(hash_table[hash_result] != -1 && r_list[hash_table[hash_result]].addr != addr) {
22291 +                       /* Collision in hash table */
22292 +                       hash_result = (hash_result + 1) % ip_list_hash_size;
22293 +               }
22294 +       }
22295 +
22296 +       if(hash_table[hash_result] == -1 && !(info->check_set & IPT_RECENT_SET)) {
22297 +               /* IP not in list and not asked to SET */
22298 +               spin_unlock_bh(&curr_table->list_lock);
22299 +               return ans;
22300 +       }
22301 +
22302 +       /* Check if we need to handle the collision, do not need to on REMOVE */
22303 +       if(orig_hash_result != hash_result && !(info->check_set & IPT_RECENT_REMOVE)) {
22304 +#ifdef DEBUG
22305 +               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision in hash table. (or: %d,hr: %d,oa: %u,ha: %u)\n",
22306 +                                orig_hash_result,
22307 +                                hash_result,
22308 +                                r_list[hash_table[orig_hash_result]].addr,
22309 +                                addr);
22310 +#endif
22311 +
22312 +               /* We had a collision.
22313 +                * orig_hash_result is where we started, hash_result is where we ended up.
22314 +                * So, swap them because we are likely to see the same guy again sooner */
22315 +#ifdef DEBUG
22316 +               if(debug) {
22317 +                 printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[orig_hash_result] = %d\n",hash_table[orig_hash_result]);
22318 +                 printk(KERN_INFO RECENT_NAME ": match(): Collision; r_list[hash_table[orig_hash_result]].hash_entry = %d\n",
22319 +                               r_list[hash_table[orig_hash_result]].hash_entry);
22320 +               }
22321 +#endif
22322 +
22323 +               r_list[hash_table[orig_hash_result]].hash_entry = hash_result;
22324 +
22325 +
22326 +               temp = hash_table[orig_hash_result];
22327 +#ifdef DEBUG
22328 +               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);
22329 +#endif
22330 +               hash_table[orig_hash_result] = hash_table[hash_result];
22331 +               hash_table[hash_result] = temp;
22332 +               temp = hash_result;
22333 +               hash_result = orig_hash_result;
22334 +               orig_hash_result = temp;
22335 +               time_info[r_list[hash_table[orig_hash_result]].time_pos].position = hash_table[orig_hash_result];
22336 +               if(hash_table[hash_result] != -1) {
22337 +                       r_list[hash_table[hash_result]].hash_entry = hash_result;
22338 +                       time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
22339 +               }
22340 +
22341 +#ifdef DEBUG
22342 +               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");
22343 +#endif
22344 +       }
22345 +
22346 +       if(hash_table[hash_result] == -1) {
22347 +#ifdef DEBUG
22348 +               if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",
22349 +                                hash_result, addr);
22350 +#endif
22351 +
22352 +               /* New item found and IPT_RECENT_SET, so we need to add it */
22353 +               location = time_info[curr_table->time_pos].position;
22354 +               hash_table[r_list[location].hash_entry] = -1;
22355 +               hash_table[hash_result] = location;
22356 +               memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
22357 +               r_list[location].time_pos = curr_table->time_pos;
22358 +               r_list[location].addr = addr;
22359 +               r_list[location].ttl = ttl;
22360 +               r_list[location].last_seen = now;
22361 +               r_list[location].oldest_pkt = 1;
22362 +               r_list[location].last_pkts[0] = now;
22363 +               r_list[location].hash_entry = hash_result;
22364 +               time_info[curr_table->time_pos].time = r_list[location].last_seen;
22365 +               curr_table->time_pos = (curr_table->time_pos + 1) % ip_list_tot;
22366 +
22367 +               ans = !info->invert;
22368 +       } else {
22369 +#ifdef DEBUG
22370 +               if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",
22371 +                                hash_result,
22372 +                                addr);
22373 +#endif
22374 +
22375 +               /* Existing item found */
22376 +               location = hash_table[hash_result];
22377 +               /* We have a match on address, now to make sure it meets all requirements for a
22378 +                * full match. */
22379 +               if(info->check_set & IPT_RECENT_CHECK || info->check_set & IPT_RECENT_UPDATE) {
22380 +                       if(!info->seconds && !info->hit_count) ans = !info->invert; else ans = info->invert;
22381 +                       if(info->seconds && !info->hit_count) {
22382 +                               if(time_before_eq(now,r_list[location].last_seen+info->seconds*HZ)) ans = !info->invert; else ans = info->invert;
22383 +                       }
22384 +                       if(info->seconds && info->hit_count) {
22385 +                               for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
22386 +                                       if(time_before_eq(now,r_list[location].last_pkts[pkt_count]+info->seconds*HZ)) hits_found++;
22387 +                               }
22388 +                               if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
22389 +                       }
22390 +                       if(info->hit_count && !info->seconds) {
22391 +                               for(pkt_count = 0, hits_found = 0; pkt_count < ip_pkt_list_tot; pkt_count++) {
22392 +                                       if(r_list[location].last_pkts[pkt_count] == 0) break;
22393 +                                       hits_found++;
22394 +                               }
22395 +                               if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
22396 +                       }
22397 +               }
22398 +#ifdef DEBUG
22399 +               if(debug) {
22400 +                       if(ans)
22401 +                               printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);
22402 +                       else
22403 +                               printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);
22404 +               }
22405 +#endif
22406 +
22407 +               /* If and only if we have been asked to SET, or to UPDATE (on match) do we add the
22408 +                * current timestamp to the last_seen. */
22409 +               if((info->check_set & IPT_RECENT_SET && (ans = !info->invert)) || (info->check_set & IPT_RECENT_UPDATE && ans)) {
22410 +#ifdef DEBUG
22411 +                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");
22412 +#endif
22413 +                       /* Have to update our time info */
22414 +                       time_loc = r_list[location].time_pos;
22415 +                       time_info[time_loc].time = now;
22416 +                       time_info[time_loc].position = location;
22417 +                       while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
22418 +                               time_temp = time_info[time_loc].time;
22419 +                               time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
22420 +                               time_info[(time_loc+1)%ip_list_tot].time = time_temp;
22421 +                               time_temp = time_info[time_loc].position;
22422 +                               time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
22423 +                               time_info[(time_loc+1)%ip_list_tot].position = time_temp;
22424 +                               r_list[time_info[time_loc].position].time_pos = time_loc;
22425 +                               r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
22426 +                               time_loc = (time_loc+1) % ip_list_tot;
22427 +                       }
22428 +                       r_list[location].time_pos = time_loc;
22429 +                       r_list[location].ttl = ttl;
22430 +                       r_list[location].last_pkts[r_list[location].oldest_pkt] = now;
22431 +                       r_list[location].oldest_pkt = ++r_list[location].oldest_pkt % ip_pkt_list_tot;
22432 +                       r_list[location].last_seen = now;
22433 +               }
22434 +               /* If we have been asked to remove the entry from the list, just set it to 0 */
22435 +               if(info->check_set & IPT_RECENT_REMOVE) {
22436 +#ifdef DEBUG
22437 +                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);
22438 +#endif
22439 +                       /* Check if this is part of a collision chain */
22440 +                       while(hash_table[(orig_hash_result+1) % ip_list_hash_size] != -1) {
22441 +                               orig_hash_result++;
22442 +                               if(hash_func(r_list[hash_table[orig_hash_result]].addr,ip_list_hash_size) == hash_result) {
22443 +                                       /* Found collision chain, how deep does this rabbit hole go? */
22444 +#ifdef DEBUG
22445 +                                       if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");
22446 +#endif
22447 +                                       end_collision_chain = orig_hash_result;
22448 +                               }
22449 +                       }
22450 +                       if(end_collision_chain != -1) {
22451 +#ifdef DEBUG
22452 +                               if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");
22453 +#endif
22454 +                               /* Part of a collision chain, swap it with the end of the chain
22455 +                                * before removing. */
22456 +                               r_list[hash_table[end_collision_chain]].hash_entry = hash_result;
22457 +                               temp = hash_table[end_collision_chain];
22458 +                               hash_table[end_collision_chain] = hash_table[hash_result];
22459 +                               hash_table[hash_result] = temp;
22460 +                               time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
22461 +                               hash_result = end_collision_chain;
22462 +                               r_list[hash_table[hash_result]].hash_entry = hash_result;
22463 +                               time_info[r_list[hash_table[hash_result]].time_pos].position = hash_table[hash_result];
22464 +                       }
22465 +                       location = hash_table[hash_result];
22466 +                       hash_table[r_list[location].hash_entry] = -1;
22467 +                       time_loc = r_list[location].time_pos;
22468 +                       time_info[time_loc].time = 0;
22469 +                       time_info[time_loc].position = location;
22470 +                       while((time_info[(time_loc+1) % ip_list_tot].time < time_info[time_loc].time) && ((time_loc+1) % ip_list_tot) != curr_table->time_pos) {
22471 +                               time_temp = time_info[time_loc].time;
22472 +                               time_info[time_loc].time = time_info[(time_loc+1)%ip_list_tot].time;
22473 +                               time_info[(time_loc+1)%ip_list_tot].time = time_temp;
22474 +                               time_temp = time_info[time_loc].position;
22475 +                               time_info[time_loc].position = time_info[(time_loc+1)%ip_list_tot].position;
22476 +                               time_info[(time_loc+1)%ip_list_tot].position = time_temp;
22477 +                               r_list[time_info[time_loc].position].time_pos = time_loc;
22478 +                               r_list[time_info[(time_loc+1)%ip_list_tot].position].time_pos = (time_loc+1)%ip_list_tot;
22479 +                               time_loc = (time_loc+1) % ip_list_tot;
22480 +                       }
22481 +                       r_list[location].time_pos = time_loc;
22482 +                       r_list[location].last_seen = 0;
22483 +                       r_list[location].addr = 0;
22484 +                       r_list[location].ttl = 0;
22485 +                       memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
22486 +                       r_list[location].oldest_pkt = 0;
22487 +                       ans = !info->invert;
22488 +               }
22489 +               spin_unlock_bh(&curr_table->list_lock);
22490 +               return ans;
22491 +       }
22492 +
22493 +       spin_unlock_bh(&curr_table->list_lock);
22494 +#ifdef DEBUG
22495 +       if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");
22496 +#endif
22497 +       return ans;
22498 +}
22499 +
22500 +/* This function is to verify that the rule given during the userspace iptables
22501 + * command is correct.
22502 + * If the command is valid then we check if the table name referred to by the
22503 + * rule exists, if not it is created.
22504 + */
22505 +static int
22506 +checkentry(const char *tablename,
22507 +           const struct ipt_ip *ip,
22508 +           void *matchinfo,
22509 +           unsigned int matchsize,
22510 +           unsigned int hook_mask)
22511 +{
22512 +       int flag = 0, c;
22513 +       u_int32_t *hold;
22514 +       const struct ipt_recent_info *info = matchinfo;
22515 +       struct recent_ip_tables *curr_table, *find_table, *last_table;
22516 +
22517 +#ifdef DEBUG
22518 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
22519 +#endif
22520 +
22521 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
22522 +
22523 +       /* seconds and hit_count only valid for CHECK/UPDATE */
22524 +       if(info->check_set & IPT_RECENT_SET) { flag++; if(info->seconds || info->hit_count) return 0; }
22525 +       if(info->check_set & IPT_RECENT_REMOVE) { flag++; if(info->seconds || info->hit_count) return 0; }
22526 +       if(info->check_set & IPT_RECENT_CHECK) flag++;
22527 +       if(info->check_set & IPT_RECENT_UPDATE) flag++;
22528 +
22529 +       /* One and only one of these should ever be set */
22530 +       if(flag != 1) return 0;
22531 +
22532 +       /* Name must be set to something */
22533 +       if(!info->name || !info->name[0]) return 0;
22534 +
22535 +       /* Things look good, create a list for this if it does not exist */
22536 +       /* Lock the linked list while we play with it */
22537 +       spin_lock_bh(&recent_lock);
22538 +
22539 +       /* Look for an entry with this name already created */
22540 +       /* Finds the end of the list and the entry before the end if current name does not exist */
22541 +       find_table = r_tables;
22542 +       while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
22543 +
22544 +       /* If a table already exists just increment the count on that table and return */
22545 +       if(find_table) { 
22546 +#ifdef DEBUG
22547 +               if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), incrementing count.\n",info->name);
22548 +#endif
22549 +               find_table->count++;
22550 +               spin_unlock_bh(&recent_lock);
22551 +               return 1;
22552 +       }
22553 +
22554 +       spin_unlock_bh(&recent_lock);
22555 +
22556 +       /* Table with this name not found */
22557 +       /* Allocate memory for new linked list item */
22558 +
22559 +#ifdef DEBUG
22560 +       if(debug) {
22561 +               printk(KERN_INFO RECENT_NAME ": checkentry: no table found (%s)\n",info->name);
22562 +               printk(KERN_INFO RECENT_NAME ": checkentry: Allocationg %d for link-list entry.\n",sizeof(struct recent_ip_tables));
22563 +       }
22564 +#endif
22565 +
22566 +       curr_table = vmalloc(sizeof(struct recent_ip_tables));
22567 +       if(curr_table == NULL) return -ENOMEM;
22568 +
22569 +       curr_table->list_lock = SPIN_LOCK_UNLOCKED;
22570 +       curr_table->next = NULL;
22571 +       curr_table->count = 1;
22572 +       curr_table->time_pos = 0;
22573 +       strncpy(curr_table->name,info->name,IPT_RECENT_NAME_LEN);
22574 +       curr_table->name[IPT_RECENT_NAME_LEN-1] = '\0';
22575 +
22576 +       /* Allocate memory for this table and the list of packets in each entry. */
22577 +#ifdef DEBUG
22578 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for table (%s).\n",
22579 +                       sizeof(struct recent_ip_list)*ip_list_tot,
22580 +                       info->name);
22581 +#endif
22582 +
22583 +       curr_table->table = vmalloc(sizeof(struct recent_ip_list)*ip_list_tot);
22584 +       if(curr_table->table == NULL) { vfree(curr_table); return -ENOMEM; }
22585 +       memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
22586 +#ifdef DEBUG
22587 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
22588 +                       sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
22589 +#endif
22590 +
22591 +       hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
22592 +#ifdef DEBUG
22593 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
22594 +#endif
22595 +       if(hold == NULL) { 
22596 +               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for pkt_list.\n");
22597 +               vfree(curr_table->table); 
22598 +               vfree(curr_table);
22599 +               return -ENOMEM;
22600 +       }
22601 +       for(c = 0; c < ip_list_tot; c++) {
22602 +               curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
22603 +       }
22604 +
22605 +       /* Allocate memory for the hash table */
22606 +#ifdef DEBUG
22607 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for hash_table.\n",
22608 +                       sizeof(int)*ip_list_hash_size);
22609 +#endif
22610 +
22611 +       curr_table->hash_table = vmalloc(sizeof(int)*ip_list_hash_size);
22612 +       if(!curr_table->hash_table) {
22613 +               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for hash_table.\n");
22614 +               vfree(hold);
22615 +               vfree(curr_table->table); 
22616 +               vfree(curr_table);
22617 +               return -ENOMEM;
22618 +       }
22619 +
22620 +       for(c = 0; c < ip_list_hash_size; c++) {
22621 +               curr_table->hash_table[c] = -1;
22622 +       }
22623 +
22624 +       /* Allocate memory for the time info */
22625 +#ifdef DEBUG
22626 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for time_info.\n",
22627 +                       sizeof(struct time_info_list)*ip_list_tot);
22628 +#endif
22629 +
22630 +       curr_table->time_info = vmalloc(sizeof(struct time_info_list)*ip_list_tot);
22631 +       if(!curr_table->time_info) {
22632 +               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for time_info.\n");
22633 +               vfree(curr_table->hash_table);
22634 +               vfree(hold);
22635 +               vfree(curr_table->table); 
22636 +               vfree(curr_table);
22637 +               return -ENOMEM;
22638 +       }
22639 +       for(c = 0; c < ip_list_tot; c++) {
22640 +               curr_table->time_info[c].position = c;
22641 +               curr_table->time_info[c].time = 0;
22642 +       }
22643 +
22644 +       /* Put the new table in place */
22645 +       spin_lock_bh(&recent_lock);
22646 +       find_table = r_tables;
22647 +       while( (last_table = find_table) && strncmp(info->name,find_table->name,IPT_RECENT_NAME_LEN) && (find_table = find_table->next) );
22648 +
22649 +       /* If a table already exists just increment the count on that table and return */
22650 +       if(find_table) { 
22651 +               find_table->count++;    
22652 +               spin_unlock_bh(&recent_lock);
22653 +#ifdef DEBUG
22654 +               if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), created by other process.\n",info->name);
22655 +#endif
22656 +               vfree(curr_table->time_info);
22657 +               vfree(curr_table->hash_table);
22658 +               vfree(hold);
22659 +               vfree(curr_table->table);
22660 +               vfree(curr_table);
22661 +               return 1;
22662 +       }
22663 +       if(!last_table) r_tables = curr_table; else last_table->next = curr_table;
22664 +
22665 +       spin_unlock_bh(&recent_lock);
22666 +
22667 +#ifdef CONFIG_PROC_FS
22668 +       /* Create our proc 'status' entry. */
22669 +       curr_table->status_proc = create_proc_entry(curr_table->name, ip_list_perms, proc_net_ipt_recent);
22670 +       if (!curr_table->status_proc) {
22671 +               printk(KERN_INFO RECENT_NAME ": checkentry: unable to allocate for /proc entry.\n");
22672 +               /* Destroy the created table */
22673 +               spin_lock_bh(&recent_lock);
22674 +               last_table = NULL;
22675 +               curr_table = r_tables;
22676 +               if(!curr_table) {
22677 +#ifdef DEBUG
22678 +                       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
22679 +#endif
22680 +                       spin_unlock_bh(&recent_lock);
22681 +                       return -ENOMEM;
22682 +               }
22683 +               while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
22684 +               if(!curr_table) {
22685 +#ifdef DEBUG
22686 +                       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
22687 +#endif
22688 +                       spin_unlock_bh(&recent_lock);
22689 +                       return -ENOMEM;
22690 +               }
22691 +               if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
22692 +               spin_unlock_bh(&recent_lock);
22693 +               vfree(curr_table->time_info);
22694 +               vfree(curr_table->hash_table);
22695 +               vfree(hold);
22696 +               vfree(curr_table->table);
22697 +               vfree(curr_table);
22698 +               return -ENOMEM;
22699 +       }
22700 +       
22701 +       curr_table->status_proc->owner = THIS_MODULE;
22702 +       curr_table->status_proc->data = curr_table;
22703 +       wmb();
22704 +       curr_table->status_proc->read_proc = ip_recent_get_info;
22705 +       curr_table->status_proc->write_proc = ip_recent_ctrl;
22706 +#endif /* CONFIG_PROC_FS */
22707 +
22708 +#ifdef DEBUG
22709 +       if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() left.\n");
22710 +#endif
22711 +
22712 +       return 1;
22713 +}
22714 +
22715 +/* This function is called in the event that a rule matching this module is
22716 + * removed.
22717 + * When this happens we need to check if there are no other rules matching
22718 + * the table given.  If that is the case then we remove the table and clean
22719 + * up its memory.
22720 + */
22721 +static void
22722 +destroy(void *matchinfo, unsigned int matchsize)
22723 +{
22724 +       const struct ipt_recent_info *info = matchinfo;
22725 +       struct recent_ip_tables *curr_table, *last_table;
22726 +
22727 +#ifdef DEBUG
22728 +       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() entered.\n");
22729 +#endif
22730 +
22731 +       if(matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return;
22732 +
22733 +       /* Lock the linked list while we play with it */
22734 +       spin_lock_bh(&recent_lock);
22735 +
22736 +       /* Look for an entry with this name already created */
22737 +       /* Finds the end of the list and the entry before the end if current name does not exist */
22738 +       last_table = NULL;
22739 +       curr_table = r_tables;
22740 +       if(!curr_table) { 
22741 +#ifdef DEBUG
22742 +               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() No tables found, leaving.\n");
22743 +#endif
22744 +               spin_unlock_bh(&recent_lock);
22745 +               return;
22746 +       }
22747 +       while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
22748 +
22749 +       /* If a table does not exist then do nothing and return */
22750 +       if(!curr_table) { 
22751 +#ifdef DEBUG
22752 +               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table not found, leaving.\n");
22753 +#endif
22754 +               spin_unlock_bh(&recent_lock);
22755 +               return;
22756 +       }
22757 +
22758 +       curr_table->count--;
22759 +
22760 +       /* If count is still non-zero then there are still rules referenceing it so we do nothing */
22761 +       if(curr_table->count) { 
22762 +#ifdef DEBUG
22763 +               if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, non-zero count, leaving.\n");
22764 +#endif
22765 +               spin_unlock_bh(&recent_lock);
22766 +               return;
22767 +       }
22768 +
22769 +#ifdef DEBUG
22770 +       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, zero count, removing.\n");
22771 +#endif
22772 +
22773 +       /* Count must be zero so we remove this table from the list */
22774 +       if(last_table) last_table->next = curr_table->next; else r_tables = curr_table->next;
22775 +
22776 +       spin_unlock_bh(&recent_lock);
22777 +
22778 +       /* lock to make sure any late-runners still using this after we removed it from
22779 +        * the list finish up then remove everything */
22780 +       spin_lock_bh(&curr_table->list_lock);
22781 +       spin_unlock_bh(&curr_table->list_lock);
22782 +
22783 +#ifdef CONFIG_PROC_FS
22784 +       if(curr_table->status_proc) remove_proc_entry(curr_table->name,proc_net_ipt_recent);
22785 +#endif /* CONFIG_PROC_FS */
22786 +       vfree(curr_table->table[0].last_pkts);
22787 +       vfree(curr_table->table);
22788 +       vfree(curr_table->hash_table);
22789 +       vfree(curr_table->time_info);
22790 +       vfree(curr_table);
22791 +
22792 +#ifdef DEBUG
22793 +       if(debug) printk(KERN_INFO RECENT_NAME ": destroy() left.\n");
22794 +#endif
22795 +
22796 +       return;
22797 +}
22798 +
22799 +/* This is the structure we pass to ipt_register to register our
22800 + * module with iptables.
22801 + */
22802 +static struct ipt_match recent_match = { 
22803 +  .name = "recent", 
22804 +  .match = &match, 
22805 +  .checkentry = &checkentry, 
22806 +  .destroy = &destroy, 
22807 +  .me = THIS_MODULE
22808 +};
22809 +
22810 +/* Kernel module initialization. */
22811 +static int __init init(void)
22812 +{
22813 +       int count;
22814 +
22815 +       printk(version);
22816 +#ifdef CONFIG_PROC_FS
22817 +       proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
22818 +       if(!proc_net_ipt_recent) return -ENOMEM;
22819 +#endif
22820 +
22821 +       if(ip_list_hash_size && ip_list_hash_size <= ip_list_tot) {
22822 +         printk(KERN_WARNING RECENT_NAME ": ip_list_hash_size too small, resetting to default.\n");
22823 +         ip_list_hash_size = 0;
22824 +       }
22825 +
22826 +       if(!ip_list_hash_size) {
22827 +               ip_list_hash_size = ip_list_tot*3;
22828 +               count = 2*2;
22829 +               while(ip_list_hash_size > count) count = count*2;
22830 +               ip_list_hash_size = count;
22831 +       }
22832 +
22833 +#ifdef DEBUG
22834 +       if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
22835 +#endif
22836 +
22837 +       return ipt_register_match(&recent_match);
22838 +}
22839 +
22840 +/* Kernel module destruction. */
22841 +static void __exit fini(void)
22842 +{
22843 +       ipt_unregister_match(&recent_match);
22844 +
22845 +       remove_proc_entry("ipt_recent",proc_net);
22846 +}
22847 +
22848 +/* Register our module with the kernel. */
22849 +module_init(init);
22850 +module_exit(fini);
22851 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_rpc.c linux-2.4.20/net/ipv4/netfilter/ipt_rpc.c
22852 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_rpc.c       Thu Jan  1 00:00:00 1970
22853 +++ linux-2.4.20/net/ipv4/netfilter/ipt_rpc.c   Wed Sep 24 09:18:01 2003
22854 @@ -0,0 +1,428 @@
22855 +/* RPC extension for IP connection matching, Version 2.2
22856 + * (C) 2000 by Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>
22857 + *     - original rpc tracking module
22858 + *     - "recent" connection handling for kernel 2.3+ netfilter
22859 + *
22860 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
22861 + *     - upgraded conntrack modules to oldnat api - kernel 2.4.0+
22862 + *
22863 + * (C) 2002,2003 by Ian (Larry) Latter <Ian.Latter@mq.edu.au>
22864 + *     - upgraded conntrack modules to newnat api - kernel 2.4.20+
22865 + *     - extended matching to support filtering on procedures
22866 + *
22867 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
22868 + *
22869 + *     This program is free software; you can redistribute it and/or
22870 + *     modify it under the terms of the GNU General Public License
22871 + *     as published by the Free Software Foundation; either version
22872 + *     2 of the License, or (at your option) any later version.
22873 + **
22874 + *     Module load syntax:
22875 + *     insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
22876 + *
22877 + *     Please give the ports of all RPC servers you wish to connect to.
22878 + *     If you don't specify ports, the default will be port 111.
22879 + **
22880 + *     Note to all:
22881 + *
22882 + *     RPCs should not be exposed to the internet - ask the Pentagon;
22883 + *
22884 + *       "The unidentified crackers pleaded guilty in July to charges
22885 + *        of juvenile delinquency stemming from a string of Pentagon
22886 + *        network intrusions in February.
22887 + *
22888 + *        The youths, going by the names TooShort and Makaveli, used
22889 + *        a common server security hole to break in, according to
22890 + *        Dane Jasper, owner of the California Internet service
22891 + *        provider, Sonic. They used the hole, known as the 'statd'
22892 + *        exploit, to attempt more than 800 break-ins, Jasper said."
22893 + *
22894 + *     From: Wired News; "Pentagon Kids Kicked Off Grid" - Nov 6, 1998
22895 + *     URL:  http://www.wired.com/news/politics/0,1283,16098,00.html
22896 + **
22897 + */
22898 +
22899 +#include <linux/module.h>
22900 +#include <linux/skbuff.h>
22901 +#include <linux/list.h>
22902 +#include <linux/udp.h>
22903 +#include <linux/tcp.h>
22904 +#include <linux/netfilter_ipv4/ip_conntrack.h>
22905 +#include <linux/netfilter_ipv4/ip_tables.h>
22906 +#include <linux/netfilter_ipv4/ip_conntrack_rpc.h>
22907 +#include <linux/netfilter_ipv4/lockhelp.h>
22908 +#include <linux/netfilter_ipv4/ipt_rpc.h>
22909 +
22910 +#define MAX_PORTS 8
22911 +static int ports[MAX_PORTS];
22912 +static int ports_n_c = 0;
22913 +
22914 +#ifdef MODULE_PARM
22915 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
22916 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
22917 +#endif
22918 +
22919 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
22920 +MODULE_DESCRIPTION("RPC connection matching module");
22921 +MODULE_LICENSE("GPL");
22922 +
22923 +#if 0
22924 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
22925 +                                       format, ## args)
22926 +#else
22927 +#define DEBUGP(format, args...)
22928 +#endif
22929 +
22930 +EXPORT_NO_SYMBOLS;
22931 +
22932 +/* vars from ip_conntrack_rpc_tcp */
22933 +extern struct list_head request_p_list_tcp;
22934 +extern struct module *ip_conntrack_rpc_tcp;
22935 +
22936 +/* vars from ip_conntrack_rpc_udp */
22937 +extern struct list_head request_p_list_udp;
22938 +extern struct module *ip_conntrack_rpc_udp;
22939 +
22940 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
22941 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
22942 +
22943 +#define ASSERT_READ_LOCK(x)                                    \
22944 +do {                                                           \
22945 +       if (x == &request_p_list_udp)                           \
22946 +               MUST_BE_READ_LOCKED(&ipct_rpc_udp_lock);        \
22947 +       else if (x == &request_p_list_tcp)                      \
22948 +               MUST_BE_READ_LOCKED(&ipct_rpc_tcp_lock);        \
22949 +} while (0)
22950 +
22951 +#define ASSERT_WRITE_LOCK(x)                                   \
22952 +do {                                                           \
22953 +       if (x == &request_p_list_udp)                           \
22954 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_udp_lock);       \
22955 +       else if (x == &request_p_list_tcp)                      \
22956 +               MUST_BE_WRITE_LOCKED(&ipct_rpc_tcp_lock);       \
22957 +} while (0)
22958 +
22959 +#include <linux/netfilter_ipv4/listhelp.h>
22960 +
22961 +const int IPT_RPC_CHAR_LEN = 11;
22962 +
22963 +
22964 +static int k_atoi(char *string)
22965 +{
22966 +       unsigned int result = 0;
22967 +       int maxoctet = IPT_RPC_CHAR_LEN;
22968 +
22969 +       for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
22970 +               if (*string < 0)
22971 +                       return(0);
22972 +               if (*string == 0)
22973 +                       break;
22974 +               if (*string < 48 || *string > 57) {
22975 +                       return(0);
22976 +               }
22977 +               result = result * 10 + ( *string - 48 );
22978 +       }
22979 +       return(result);
22980 +}
22981 +
22982 +
22983 +static int match_rpcs(char *c_procs, int i_procs, int proc)
22984 +{
22985 +       int   proc_ctr;
22986 +       char *proc_ptr;
22987 +       unsigned int proc_num;
22988 +
22989 +       DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
22990 +
22991 +       if (i_procs == -1)
22992 +               return 1;
22993 +
22994 +       for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
22995 +
22996 +               proc_ptr = c_procs;
22997 +               proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
22998 +               proc_num = k_atoi(proc_ptr);
22999 +
23000 +               if (proc_num == proc)
23001 +                       return 1;
23002 +       }
23003 +
23004 +       return 0;
23005 +}
23006 +
23007 +
23008 +static int check_rpc_packet(const u_int32_t *data, const void *matchinfo,
23009 +                       int *hotdrop, int dir, struct ip_conntrack *ct,
23010 +                       int offset, struct list_head request_p_list)
23011 +{
23012 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
23013 +       struct request_p *req_p;
23014 +       u_int32_t xid;
23015 +
23016 +
23017 +       /* Get XID */
23018 +       xid = *data;
23019 +
23020 +       /* This does sanity checking on RPC payloads,
23021 +        * and permits only the RPC "get port" (3)
23022 +        * in authorised procedures in client
23023 +        * communications with the portmapper.
23024 +        */
23025 +
23026 +       data += 5;
23027 +
23028 +       /* Get RPC requestor */
23029 +       if (IXDR_GET_INT32(data) != 3) {
23030 +               DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
23031 +               if(rpcinfo->strict == 1)
23032 +                       *hotdrop = 1;
23033 +               return 0;
23034 +       }
23035 +       DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
23036 +
23037 +       data++;
23038 +
23039 +       /* Jump Credentials and Verfifier */
23040 +       data = data + IXDR_GET_INT32(data) + 2;
23041 +       data = data + IXDR_GET_INT32(data) + 2;
23042 +
23043 +       /* Get RPC procedure */
23044 +       if (match_rpcs((char *)&rpcinfo->c_procs,
23045 +           rpcinfo->i_procs, IXDR_GET_INT32(data)) == 0) {
23046 +               DEBUGP("RPC packet contains illegal procedure request [%u]. [drop]\n",
23047 +                       (unsigned int)IXDR_GET_INT32(data));
23048 +
23049 +               /* If the RPC conntrack half entry already exists .. */
23050 +
23051 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
23052 +                       case IPPROTO_UDP:
23053 +                               WRITE_LOCK(&ipct_rpc_udp_lock);
23054 +                       case IPPROTO_TCP:
23055 +                               WRITE_LOCK(&ipct_rpc_tcp_lock);
23056 +               }
23057 +               req_p = LIST_FIND(&request_p_list, request_p_cmp,
23058 +                                 struct request_p *, xid,
23059 +                                 ct->tuplehash[dir].tuple.src.ip,
23060 +                                 ct->tuplehash[dir].tuple.src.u.all);
23061 +
23062 +               if (req_p) {
23063 +                       DEBUGP("found req_p for xid=%u proto=%u %u.%u.%u.%u:%u\n",
23064 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
23065 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
23066 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
23067 +
23068 +                       /* .. remove it */
23069 +                       if (del_timer(&req_p->timeout))
23070 +                               req_p->timeout.expires = 0;
23071 +
23072 +                               LIST_DELETE(&request_p_list, req_p);
23073 +                       DEBUGP("RPC req_p removed. [done]\n");
23074 +
23075 +               } else {
23076 +                       DEBUGP("no req_p found for xid=%u proto=%u %u.%u.%u.%u:%u\n",
23077 +                               xid, ct->tuplehash[dir].tuple.dst.protonum,
23078 +                               NIPQUAD(ct->tuplehash[dir].tuple.src.ip),
23079 +                               ntohs(ct->tuplehash[dir].tuple.src.u.all));
23080 +
23081 +               }
23082 +               switch (ct->tuplehash[0].tuple.dst.protonum) {
23083 +                       case IPPROTO_UDP:
23084 +                               WRITE_UNLOCK(&ipct_rpc_udp_lock);
23085 +                       case IPPROTO_TCP:
23086 +                               WRITE_UNLOCK(&ipct_rpc_tcp_lock);
23087 +               }
23088 +
23089 +               if(rpcinfo->strict == 1)
23090 +                       *hotdrop = 1;
23091 +               return 0;
23092 +       }
23093 +
23094 +       DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
23095 +               (unsigned int)IXDR_GET_INT32(data));
23096 +       return (1 && (!offset));
23097 +}
23098 +
23099 +
23100 +static int match(const struct sk_buff *skb, const struct net_device *in,
23101 +                const struct net_device *out, const void *matchinfo,
23102 +                int offset, const void *hdr, u_int16_t datalen, int *hotdrop)
23103 +{
23104 +       struct ip_conntrack *ct;
23105 +       enum ip_conntrack_info ctinfo;
23106 +       const u_int32_t *data;
23107 +       enum ip_conntrack_dir dir;
23108 +       const struct tcphdr *tcp;
23109 +       const struct ipt_rpc_info *rpcinfo = matchinfo;
23110 +       int port, portsok;
23111 +       int tval;
23112 +
23113 +
23114 +       DEBUGP("new packet to evaluate ..\n");
23115 +
23116 +       ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
23117 +       if (!ct) {
23118 +               DEBUGP("no ct available [skip]\n");
23119 +               return 0;
23120 +       }
23121 +
23122 +       DEBUGP("ct detected. [cont]\n");
23123 +       dir = CTINFO2DIR(ctinfo);
23124 +
23125 +       /* we only want the client to server packets for matching */
23126 +       if (dir != IP_CT_DIR_ORIGINAL)
23127 +               return 0;
23128 +
23129 +       /* This does sanity checking on UDP or TCP packets,
23130 +        * like their respective modules.
23131 +        */
23132 +
23133 +       switch (ct->tuplehash[0].tuple.dst.protonum) {
23134 +
23135 +               case IPPROTO_UDP:
23136 +                       DEBUGP("PROTO_UDP [cont]\n");
23137 +                       if (offset == 0 && datalen < sizeof(struct udphdr)) {
23138 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
23139 +                               return 0;
23140 +                       }
23141 +
23142 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
23143 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
23144 +                                       portsok++;
23145 +                                       break;
23146 +                               }
23147 +                       }
23148 +                       if (portsok == 0) {
23149 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
23150 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
23151 +                               return 0;
23152 +                       }
23153 +
23154 +                       if ((datalen - sizeof(struct udphdr)) != 56) {
23155 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
23156 +                               if (rpcinfo->strict == 1)
23157 +                                       *hotdrop = 1;
23158 +                               return 0;
23159 +                       }
23160 +                       DEBUGP("packet length is correct. [cont]\n");
23161 +
23162 +                       /* Get to the data */
23163 +                       data = (const u_int32_t *)hdr + 2;
23164 +
23165 +                       /* Check the RPC data */
23166 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
23167 +                                               dir, ct, offset,
23168 +                                               request_p_list_udp);
23169 +
23170 +                       return tval;
23171 +                       
23172 +               
23173 +               case IPPROTO_TCP:
23174 +                       DEBUGP("PROTO_TCP [cont]\n");
23175 +                       if (offset == 0 && datalen < sizeof(struct tcphdr)) {
23176 +                               DEBUGP("packet does not contain a complete header. [drop]\n");
23177 +                               return 0;
23178 +                       }
23179 +       
23180 +                       for (port=0,portsok=0; port <= ports_n_c; port++) {
23181 +                               if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
23182 +                                       portsok++;
23183 +                                       break;
23184 +                               }
23185 +                       }
23186 +                       if (portsok == 0) {
23187 +                               DEBUGP("packet is not destined for a portmapper [%u]. [skip]\n",
23188 +                                       ntohs(ct->tuplehash[dir].tuple.dst.u.all));
23189 +                               return 0;
23190 +                       }
23191 +
23192 +                       tcp = hdr;
23193 +                       if (datalen == (tcp->doff * 4)) {
23194 +                               DEBUGP("packet does not contain any data. [match]\n");
23195 +                               return (1 && (!offset));
23196 +                       }
23197 +
23198 +                       /* Tests if packet len is ok */
23199 +                       if ((datalen - (tcp->doff * 4)) != 60) {
23200 +                               DEBUGP("packet length is not correct for RPC content. [skip]\n");
23201 +                               if(rpcinfo->strict == 1)
23202 +                                       *hotdrop = 1;
23203 +                               return 0;
23204 +                       }
23205 +                       DEBUGP("packet length is correct. [cont]\n");
23206 +
23207 +                       /* Get to the data */
23208 +                       data = (const u_int32_t *)tcp + tcp->doff + 1;  
23209 +
23210 +                       /* Check the RPC data */
23211 +                       tval = check_rpc_packet(data, matchinfo, hotdrop,
23212 +                                               dir, ct, offset,
23213 +                                               request_p_list_tcp);
23214 +
23215 +                       return tval;
23216 +
23217 +       }
23218 +
23219 +       DEBUGP("transport protocol=%u, is not supported [skip]\n",
23220 +               ct->tuplehash[0].tuple.dst.protonum);
23221 +       return 0;
23222 +}
23223 +
23224 +
23225 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
23226 +                  unsigned int matchsize, unsigned int hook_mask)
23227 +{
23228 +       if (hook_mask
23229 +           & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_FORWARD) | (1 << NF_IP_POST_ROUTING)
23230 +               | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {
23231 +               printk("ipt_rpc: only valid for PRE_ROUTING, FORWARD, POST_ROUTING, LOCAL_IN and/or LOCAL_OUT targets.\n");
23232 +               return 0;
23233 +       }
23234 +
23235 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
23236 +               return 0;
23237 +
23238 +       return 1;
23239 +}
23240 +
23241 +
23242 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
23243 +                                       &match, &checkentry, NULL,
23244 +                                       THIS_MODULE };
23245 +
23246 +
23247 +static int __init init(void)
23248 +{
23249 +       int port;
23250 +
23251 +       DEBUGP("incrementing usage counts\n");
23252 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
23253 +       __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
23254 +
23255 +       /* If no port given, default to standard RPC port */
23256 +       if (ports[0] == 0)
23257 +               ports[0] = RPC_PORT;
23258 +
23259 +       DEBUGP("registering match [%s] for;\n", rpc_match.name);
23260 +       for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
23261 +               DEBUGP("  port %i (UDP|TCP);\n", ports[port]);
23262 +               ports_n_c++;
23263 +       }
23264 +       
23265 +       return ipt_register_match(&rpc_match);
23266 +}
23267 +
23268 +
23269 +static void fini(void)
23270 +{
23271 +       DEBUGP("unregistering match\n");
23272 +       ipt_unregister_match(&rpc_match);
23273 +
23274 +       DEBUGP("decrementing usage counts\n");
23275 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
23276 +       __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
23277 +}
23278 +
23279 +
23280 +module_init(init);
23281 +module_exit(fini);
23282 +
23283 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_state.c linux-2.4.20/net/ipv4/netfilter/ipt_state.c
23284 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_state.c     Sun Sep 30 19:26:08 2001
23285 +++ linux-2.4.20/net/ipv4/netfilter/ipt_state.c Wed Sep 24 09:18:12 2003
23286 @@ -21,7 +21,9 @@
23287         enum ip_conntrack_info ctinfo;
23288         unsigned int statebit;
23289  
23290 -       if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
23291 +       if (skb->nfct == &ip_conntrack_untracked.infos[IP_CT_NEW])
23292 +               statebit = IPT_STATE_UNTRACKED;
23293 +       else if (!ip_conntrack_get((struct sk_buff *)skb, &ctinfo))
23294                 statebit = IPT_STATE_INVALID;
23295         else
23296                 statebit = IPT_STATE_BIT(ctinfo);
23297 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_string.c linux-2.4.20/net/ipv4/netfilter/ipt_string.c
23298 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_string.c    Thu Jan  1 00:00:00 1970
23299 +++ linux-2.4.20/net/ipv4/netfilter/ipt_string.c        Wed Sep 24 09:18:05 2003
23300 @@ -0,0 +1,218 @@
23301 +/* Kernel module to match a string into a packet.
23302 + *
23303 + * Copyright (C) 2000 Emmanuel Roger  <winfield@freegates.be>
23304 + * 
23305 + * ChangeLog
23306 + *     19.02.2002: Gianni Tedesco <gianni@ecsc.co.uk>
23307 + *             Fixed SMP re-entrancy problem using per-cpu data areas
23308 + *             for the skip/shift tables.
23309 + *     02.05.2001: Gianni Tedesco <gianni@ecsc.co.uk>
23310 + *             Fixed kernel panic, due to overrunning boyer moore string
23311 + *             tables. Also slightly tweaked heuristic for deciding what
23312 + *             search algo to use.
23313 + *     27.01.2001: Gianni Tedesco <gianni@ecsc.co.uk>
23314 + *             Implemented Boyer Moore Sublinear search algorithm
23315 + *             alongside the existing linear search based on memcmp().
23316 + *             Also a quick check to decide which method to use on a per
23317 + *             packet basis.
23318 + */
23319 +
23320 +#include <linux/smp.h>
23321 +#include <linux/module.h>
23322 +#include <linux/skbuff.h>
23323 +#include <linux/file.h>
23324 +#include <net/sock.h>
23325 +
23326 +#include <linux/netfilter_ipv4/ip_tables.h>
23327 +#include <linux/netfilter_ipv4/ipt_string.h>
23328 +
23329 +MODULE_LICENSE("GPL");
23330 +
23331 +struct string_per_cpu {
23332 +       int *skip;
23333 +       int *shift;
23334 +       int *len;
23335 +};
23336 +
23337 +struct string_per_cpu *bm_string_data=NULL;
23338 +
23339 +/* Boyer Moore Sublinear string search - VERY FAST */
23340 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len) 
23341 +{
23342 +       int M1, right_end, sk, sh;  
23343 +       int ended, j, i;
23344 +
23345 +       int *skip, *shift, *len;
23346 +       
23347 +       /* use data suitable for this CPU */
23348 +       shift=bm_string_data[smp_processor_id()].shift;
23349 +       skip=bm_string_data[smp_processor_id()].skip;
23350 +       len=bm_string_data[smp_processor_id()].len;
23351 +       
23352 +       /* Setup skip/shift tables */
23353 +       M1 = right_end = needle_len-1;
23354 +       for (i = 0; i < BM_MAX_HLEN; i++) skip[i] = needle_len;  
23355 +       for (i = 0; needle[i]; i++) skip[needle[i]] = M1 - i;  
23356 +
23357 +       for (i = 1; i < needle_len; i++) {   
23358 +               for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);  
23359 +               len[i] = j;  
23360 +       }  
23361 +
23362 +       shift[0] = 1;  
23363 +       for (i = 1; i < needle_len; i++) shift[i] = needle_len;  
23364 +       for (i = M1; i > 0; i--) shift[len[i]] = i;  
23365 +       ended = 0;  
23366 +       
23367 +       for (i = 0; i < needle_len; i++) {  
23368 +               if (len[i] == M1 - i) ended = i;  
23369 +               if (ended) shift[i] = ended;  
23370 +       }  
23371 +
23372 +       /* Do the search*/  
23373 +       while (right_end < haystack_len)
23374 +       {
23375 +               for (i = 0; i < needle_len && haystack[right_end - i] == needle[M1 - i]; i++);  
23376 +               if (i == needle_len) {
23377 +                       return haystack+(right_end - M1);
23378 +               }
23379 +               
23380 +               sk = skip[haystack[right_end - i]];  
23381 +               sh = shift[i];
23382 +               right_end = max(right_end - i + sk, right_end + sh);  
23383 +       }
23384 +
23385 +       return NULL;
23386 +}  
23387 +
23388 +/* Linear string search based on memcmp() */
23389 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len) 
23390 +{
23391 +       char *k = haystack + (haystack_len-needle_len);
23392 +       char *t = haystack;
23393 +       
23394 +       while ( t <= k ) {
23395 +               if (memcmp(t, needle, needle_len) == 0)
23396 +                       return t;
23397 +               t++;
23398 +       }
23399 +
23400 +       return NULL;
23401 +}
23402 +
23403 +
23404 +static int
23405 +match(const struct sk_buff *skb,
23406 +      const struct net_device *in,
23407 +      const struct net_device *out,
23408 +      const void *matchinfo,
23409 +      int offset,
23410 +      const void *hdr,
23411 +      u_int16_t datalen,
23412 +      int *hotdrop)
23413 +{
23414 +       const struct ipt_string_info *info = matchinfo;
23415 +       struct iphdr *ip = skb->nh.iph;
23416 +       int hlen, nlen;
23417 +       char *needle, *haystack;
23418 +       proc_ipt_search search=search_linear;
23419 +
23420 +       if ( !ip ) return 0;
23421 +
23422 +       /* get lenghts, and validate them */
23423 +       nlen=info->len;
23424 +       hlen=ntohs(ip->tot_len)-(ip->ihl*4);
23425 +       if ( nlen > hlen ) return 0;
23426 +
23427 +       needle=(char *)&info->string;
23428 +       haystack=(char *)ip+(ip->ihl*4);
23429 +
23430 +       /* The sublinear search comes in to its own
23431 +        * on the larger packets */
23432 +       if ( (hlen>IPT_STRING_HAYSTACK_THRESH) &&
23433 +               (nlen>IPT_STRING_NEEDLE_THRESH) ) {
23434 +               if ( hlen < BM_MAX_HLEN ) {
23435 +                       search=search_sublinear;
23436 +               }else{
23437 +                       if (net_ratelimit())
23438 +                               printk(KERN_INFO "ipt_string: Packet too big "
23439 +                                       "to attempt sublinear string search "
23440 +                                       "(%d bytes)\n", hlen );
23441 +               }
23442 +       }
23443 +       
23444 +    return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
23445 +}
23446 +
23447 +static int
23448 +checkentry(const char *tablename,
23449 +           const struct ipt_ip *ip,
23450 +           void *matchinfo,
23451 +           unsigned int matchsize,
23452 +           unsigned int hook_mask)
23453 +{
23454 +
23455 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
23456 +               return 0;
23457 +
23458 +       return 1;
23459 +}
23460 +
23461 +void string_freeup_data(void)
23462 +{
23463 +       int c;
23464 +       
23465 +       if ( bm_string_data ) {
23466 +               for(c=0; c<smp_num_cpus; c++) {
23467 +                       if ( bm_string_data[c].shift ) kfree(bm_string_data[c].shift);
23468 +                       if ( bm_string_data[c].skip ) kfree(bm_string_data[c].skip);
23469 +                       if ( bm_string_data[c].len ) kfree(bm_string_data[c].len);
23470 +               }
23471 +               kfree(bm_string_data);
23472 +       }
23473 +}
23474 +
23475 +static struct ipt_match string_match
23476 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
23477 +
23478 +static int __init init(void)
23479 +{
23480 +       int c;
23481 +       size_t tlen;
23482 +       size_t alen;
23483 +
23484 +       tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
23485 +       alen=sizeof(int)*BM_MAX_HLEN;
23486 +       
23487 +       /* allocate array of structures */
23488 +       if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
23489 +               return 0;
23490 +       }
23491 +       
23492 +       memset(bm_string_data, 0, tlen);
23493 +       
23494 +       /* allocate our skip/shift tables */
23495 +       for(c=0; c<smp_num_cpus; c++) {
23496 +               if ( !(bm_string_data[c].shift=kmalloc(alen, GFP_KERNEL)) )
23497 +                       goto alloc_fail;
23498 +               if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
23499 +                       goto alloc_fail;
23500 +               if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
23501 +                       goto alloc_fail;
23502 +       }
23503 +       
23504 +       return ipt_register_match(&string_match);
23505 +
23506 +alloc_fail:
23507 +       string_freeup_data();
23508 +       return 0;
23509 +}
23510 +
23511 +static void __exit fini(void)
23512 +{
23513 +       ipt_unregister_match(&string_match);
23514 +       string_freeup_data();
23515 +}
23516 +
23517 +module_init(init);
23518 +module_exit(fini);
23519 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_time.c linux-2.4.20/net/ipv4/netfilter/ipt_time.c
23520 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_time.c      Thu Jan  1 00:00:00 1970
23521 +++ linux-2.4.20/net/ipv4/netfilter/ipt_time.c  Wed Sep 24 09:17:10 2003
23522 @@ -0,0 +1,185 @@
23523 +/*
23524 +  This is a module which is used for time matching
23525 +  It is using some modified code from dietlibc (localtime() function)
23526 +  that you can find at http://www.fefe.de/dietlibc/
23527 +  This file is distributed under the terms of the GNU General Public
23528 +  License (GPL). Copies of the GPL can be obtained from: ftp://prep.ai.mit.edu/pub/gnu/GPL
23529 +  2001-05-04 Fabrice MARIE <fabrice@netfilter.org> : initial development.
23530 +  2001-21-05 Fabrice MARIE <fabrice@netfilter.org> : bug fix in the match code,
23531 +     thanks to "Zeng Yu" <zengy@capitel.com.cn> for bug report.
23532 +  2001-26-09 Fabrice MARIE <fabrice@netfilter.org> : force the match to be in LOCAL_IN or PRE_ROUTING only.
23533 +  2001-30-11 Fabrice : added the possibility to use the match in FORWARD/OUTPUT with a little hack,
23534 +     added Nguyen Dang Phuoc Dong <dongnd@tlnet.com.vn> patch to support timezones.
23535 +*/
23536 +
23537 +#include <linux/module.h>
23538 +#include <linux/skbuff.h>
23539 +#include <linux/netfilter_ipv4/ip_tables.h>
23540 +#include <linux/netfilter_ipv4/ipt_time.h>
23541 +#include <linux/time.h>
23542 +
23543 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
23544 +MODULE_DESCRIPTION("Match arrival timestamp");
23545 +MODULE_LICENSE("GPL");
23546 +
23547 +struct tm
23548 +{
23549 +       int tm_sec;                   /* Seconds.     [0-60] (1 leap second) */
23550 +       int tm_min;                   /* Minutes.     [0-59] */
23551 +       int tm_hour;                  /* Hours.       [0-23] */
23552 +       int tm_mday;                  /* Day.         [1-31] */
23553 +       int tm_mon;                   /* Month.       [0-11] */
23554 +       int tm_year;                  /* Year - 1900.  */
23555 +       int tm_wday;                  /* Day of week. [0-6] */
23556 +       int tm_yday;                  /* Days in year.[0-365] */
23557 +       int tm_isdst;                 /* DST.         [-1/0/1]*/
23558 +
23559 +       long int tm_gmtoff;           /* we don't care, we count from GMT */
23560 +       const char *tm_zone;          /* we don't care, we count from GMT */
23561 +};
23562 +
23563 +void
23564 +localtime(const time_t *timepr, struct tm *r);
23565 +
23566 +static int
23567 +match(const struct sk_buff *skb,
23568 +      const struct net_device *in,
23569 +      const struct net_device *out,
23570 +      const void *matchinfo,
23571 +      int offset,
23572 +      const void *hdr,
23573 +      u_int16_t datalen,
23574 +      int *hotdrop)
23575 +{
23576 +       const struct ipt_time_info *info = matchinfo;   /* match info for rule */
23577 +       struct tm currenttime;                          /* time human readable */
23578 +       u_int8_t days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
23579 +       u_int16_t packet_time;
23580 +       struct timeval kerneltimeval;
23581 +       time_t packet_local_time;
23582 +
23583 +       /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
23584 +       if (info->kerneltime)
23585 +       {
23586 +               do_gettimeofday(&kerneltimeval);
23587 +               packet_local_time = kerneltimeval.tv_sec;
23588 +       }
23589 +       else
23590 +               packet_local_time = skb->stamp.tv_sec;
23591 +
23592 +       /* Transform the timestamp of the packet, in a human readable form */
23593 +       localtime(&packet_local_time, &currenttime);
23594 +
23595 +       /* check if we match this timestamp, we start by the days... */
23596 +       if ((days_of_week[currenttime.tm_wday] & info->days_match) != days_of_week[currenttime.tm_wday])
23597 +               return 0; /* the day doesn't match */
23598 +
23599 +       /* ... check the time now */
23600 +       packet_time = (currenttime.tm_hour * 60) + currenttime.tm_min;
23601 +       if ((packet_time < info->time_start) || (packet_time > info->time_stop))
23602 +               return 0;
23603 +
23604 +       /* here we match ! */
23605 +       return 1;
23606 +}
23607 +
23608 +static int
23609 +checkentry(const char *tablename,
23610 +           const struct ipt_ip *ip,
23611 +           void *matchinfo,
23612 +           unsigned int matchsize,
23613 +           unsigned int hook_mask)
23614 +{
23615 +       struct ipt_time_info *info = matchinfo;   /* match info for rule */
23616 +
23617 +       /* First, check that we are in the correct hook */
23618 +       /* PRE_ROUTING, LOCAL_IN or FROWARD */
23619 +       if (hook_mask
23620 +            & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
23621 +       {
23622 +               printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
23623 +               return 0;
23624 +       }
23625 +       /* we use the kerneltime if we are in forward or output */
23626 +       info->kerneltime = 1;
23627 +       if (hook_mask & ~((1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT))) 
23628 +               /* if not, we use the skb time */
23629 +               info->kerneltime = 0;
23630 +
23631 +       /* Check the size */
23632 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
23633 +               return 0;
23634 +       /* Now check the coherence of the data ... */
23635 +       if ((info->time_start > 1439) ||        /* 23*60+59 = 1439*/
23636 +           (info->time_stop  > 1439))
23637 +       {
23638 +               printk(KERN_WARNING "ipt_time: invalid argument\n");
23639 +               return 0;
23640 +       }
23641 +
23642 +       return 1;
23643 +}
23644 +
23645 +static struct ipt_match time_match
23646 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
23647 +
23648 +static int __init init(void)
23649 +{
23650 +       printk("ipt_time loading\n");
23651 +       return ipt_register_match(&time_match);
23652 +}
23653 +
23654 +static void __exit fini(void)
23655 +{
23656 +       ipt_unregister_match(&time_match);
23657 +       printk("ipt_time unloaded\n");
23658 +}
23659 +
23660 +module_init(init);
23661 +module_exit(fini);
23662 +
23663 +
23664 +/* The part below is borowed and modified from dietlibc */
23665 +
23666 +/* seconds per day */
23667 +#define SPD 24*60*60
23668 +
23669 +void
23670 +localtime(const time_t *timepr, struct tm *r) {
23671 +       time_t i;
23672 +       time_t timep;
23673 +       extern struct timezone sys_tz;
23674 +       const unsigned int __spm[12] =
23675 +               { 0,
23676 +                 (31),
23677 +                 (31+28),
23678 +                 (31+28+31),
23679 +                 (31+28+31+30),
23680 +                 (31+28+31+30+31),
23681 +                 (31+28+31+30+31+30),
23682 +                 (31+28+31+30+31+30+31),
23683 +                 (31+28+31+30+31+30+31+31),
23684 +                 (31+28+31+30+31+30+31+31+30),
23685 +                 (31+28+31+30+31+30+31+31+30+31),
23686 +                 (31+28+31+30+31+30+31+31+30+31+30),
23687 +               };
23688 +       register time_t work;
23689 +
23690 +       timep = (*timepr) - (sys_tz.tz_minuteswest * 60);
23691 +       work=timep%(SPD);
23692 +       r->tm_sec=work%60; work/=60;
23693 +       r->tm_min=work%60; r->tm_hour=work/60;
23694 +       work=timep/(SPD);
23695 +       r->tm_wday=(4+work)%7;
23696 +       for (i=1970; ; ++i) {
23697 +               register time_t k= (!(i%4) && ((i%100) || !(i%400)))?366:365;
23698 +               if (work>k)
23699 +                       work-=k;
23700 +               else
23701 +                       break;
23702 +       }
23703 +       r->tm_year=i-1900;
23704 +       for (i=11; i && __spm[i]>work; --i) ;
23705 +       r->tm_mon=i;
23706 +       r->tm_mday=work-__spm[i]+1;
23707 +}
23708 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_u32.c linux-2.4.20/net/ipv4/netfilter/ipt_u32.c
23709 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_u32.c       Thu Jan  1 00:00:00 1970
23710 +++ linux-2.4.20/net/ipv4/netfilter/ipt_u32.c   Wed Sep 24 09:17:12 2003
23711 @@ -0,0 +1,211 @@
23712 +/* Kernel module to match u32 packet content. */
23713 +
23714 +/* 
23715 +U32 tests whether quantities of up to 4 bytes extracted from a packet 
23716 +have specified values.  The specification of what to extract is general 
23717 +enough to find data at given offsets from tcp headers or payloads.
23718 +
23719 + --u32 tests
23720 + The argument amounts to a program in a small language described below.
23721 + tests := location = value |  tests && location = value
23722 + value := range | value , range
23723 + range := number | number : number
23724 +  a single number, n, is interpreted the same as n:n
23725 +  n:m is interpreted as the range of numbers >=n and <=m
23726 + location := number | location operator number
23727 + operator := & | << | >> | @
23728 +
23729 + The operators &, <<, >>, && mean the same as in c.  The = is really a set
23730 + membership operator and the value syntax describes a set.  The @ operator
23731 + is what allows moving to the next header and is described further below.
23732 +
23733 + *** Until I can find out how to avoid it, there are some artificial limits
23734 + on the size of the tests:
23735 + - no more than 10 ='s (and 9 &&'s) in the u32 argument
23736 + - no more than 10 ranges (and 9 commas) per value
23737 + - no more than 10 numbers (and 9 operators) per location
23738 +
23739 + To describe the meaning of location, imagine the following machine that
23740 + interprets it.  There are three registers:
23741 +  A is of type char*, initially the address of the IP header
23742 +  B and C are unsigned 32 bit integers, initially zero
23743 +
23744 +  The instructions are:
23745 +   number      B = number;
23746 +               C = (*(A+B)<<24)+(*(A+B+1)<<16)+(*(A+B+2)<<8)+*(A+B+3)
23747 +   &number     C = C&number
23748 +   <<number    C = C<<number
23749 +   >>number    C = C>>number
23750 +   @number     A = A+C; then do the instruction number
23751 +  Any access of memory outside [skb->head,skb->end] causes the match to fail.
23752 +  Otherwise the result of the computation is the final value of C.
23753 +
23754 + Whitespace is allowed but not required in the tests.
23755 + However the characters that do occur there are likely to require
23756 + shell quoting, so it's a good idea to enclose the arguments in quotes.
23757 +
23758 +Example:
23759 + match IP packets with total length >= 256
23760 + The IP header contains a total length field in bytes 2-3.
23761 + --u32 "0&0xFFFF=0x100:0xFFFF" 
23762 + read bytes 0-3
23763 + AND that with FFFF (giving bytes 2-3),
23764 + and test whether that's in the range [0x100:0xFFFF]
23765 +
23766 +Example: (more realistic, hence more complicated)
23767 + match icmp packets with icmp type 0
23768 + First test that it's an icmp packet, true iff byte 9 (protocol) = 1
23769 + --u32 "6&0xFF=1 && ...
23770 + read bytes 6-9, use & to throw away bytes 6-8 and compare the result to 1
23771 + Next test that it's not a fragment.
23772 +  (If so it might be part of such a packet but we can't always tell.)
23773 +  n.b. This test is generally needed if you want to match anything
23774 +  beyond the IP header.
23775 + The last 6 bits of byte 6 and all of byte 7 are 0 iff this is a complete
23776 + packet (not a fragment).  Alternatively, you can allow first fragments
23777 + by only testing the last 5 bits of byte 6.
23778 + ... 4&0x3FFF=0 && ...
23779 + Last test: the first byte past the IP header (the type) is 0
23780 + This is where we have to use the @syntax.  The length of the IP header
23781 + (IHL) in 32 bit words is stored in the right half of byte 0 of the
23782 + IP header itself.
23783 + ... 0>>22&0x3C@0>>24=0"
23784 + The first 0 means read bytes 0-3,
23785 + >>22 means shift that 22 bits to the right.  Shifting 24 bits would give
23786 +   the first byte, so only 22 bits is four times that plus a few more bits.
23787 + &3C then eliminates the two extra bits on the right and the first four 
23788 + bits of the first byte.
23789 + For instance, if IHL=5 then the IP header is 20 (4 x 5) bytes long.
23790 + In this case bytes 0-1 are (in binary) xxxx0101 yyzzzzzz, 
23791 + >>22 gives the 10 bit value xxxx0101yy and &3C gives 010100.
23792 + @ means to use this number as a new offset into the packet, and read
23793 + four bytes starting from there.  This is the first 4 bytes of the icmp
23794 + payload, of which byte 0 is the icmp type.  Therefore we simply shift
23795 + the value 24 to the right to throw out all but the first byte and compare
23796 + the result with 0.
23797 +
23798 +Example: 
23799 + tcp payload bytes 8-12 is any of 1, 2, 5 or 8
23800 + First we test that the packet is a tcp packet (similar to icmp).
23801 + --u32 "6&0xFF=6 && ...
23802 + Next, test that it's not a fragment (same as above).
23803 + ... 0>>22&0x3C@12>>26&0x3C@8=1,2,5,8"
23804 + 0>>22&3C as above computes the number of bytes in the IP header.
23805 + @ makes this the new offset into the packet, which is the start of the
23806 + tcp header.  The length of the tcp header (again in 32 bit words) is
23807 + the left half of byte 12 of the tcp header.  The 12>>26&3C
23808 + computes this length in bytes (similar to the IP header before).
23809 + @ makes this the new offset, which is the start of the tcp payload.
23810 + Finally 8 reads bytes 8-12 of the payload and = checks whether the
23811 + result is any of 1, 2, 5 or 8
23812 +*/
23813 +
23814 +#include <linux/module.h>
23815 +#include <linux/skbuff.h>
23816 +
23817 +#include <linux/netfilter_ipv4/ipt_u32.h>
23818 +#include <linux/netfilter_ipv4/ip_tables.h>
23819 +
23820 +/* #include <asm-i386/timex.h> for timing */
23821 +
23822 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
23823 +MODULE_DESCRIPTION("IP tables u32 matching module");
23824 +MODULE_LICENSE("GPL");
23825 +
23826 +static int
23827 +match(const struct sk_buff *skb,
23828 +      const struct net_device *in,
23829 +      const struct net_device *out,
23830 +      const void *matchinfo,
23831 +      int offset,
23832 +      const void *hdr,
23833 +      u_int16_t datalen,
23834 +      int *hotdrop)
23835 +{
23836 +       const struct ipt_u32 *data = matchinfo;
23837 +       int testind, i;
23838 +       unsigned char* origbase = (char*)skb->nh.iph;
23839 +       unsigned char* base = origbase;
23840 +       unsigned char* head = skb->head;
23841 +       unsigned char* end = skb->end;
23842 +       int nnums, nvals;
23843 +       u_int32_t pos, val;
23844 +       /* unsigned long long cycles1, cycles2, cycles3, cycles4;
23845 +          cycles1 = get_cycles(); */
23846 +
23847 +       for (testind=0; testind < data->ntests; testind++) {
23848 +               base = origbase; /* reset for each test */
23849 +               pos = data->tests[testind].location[0].number;
23850 +               if (base+pos+3 > end || base+pos < head) 
23851 +                       return 0;
23852 +               val = (base[pos]<<24) + (base[pos+1]<<16) +
23853 +                       (base[pos+2]<<8) + base[pos+3];
23854 +               nnums = data->tests[testind].nnums;
23855 +               for (i=1; i < nnums; i++) {
23856 +                       u_int32_t number = data->tests[testind].location[i].number;
23857 +                       switch (data->tests[testind].location[i].nextop) {
23858 +                       case IPT_U32_AND: 
23859 +                               val = val & number; 
23860 +                               break;
23861 +                       case IPT_U32_LEFTSH: 
23862 +                               val = val << number;
23863 +                               break;
23864 +                       case IPT_U32_RIGHTSH: 
23865 +                               val = val >> number; 
23866 +                               break;
23867 +                       case IPT_U32_AT:
23868 +                               base = base + val;
23869 +                               pos = number;
23870 +                               if (base+pos+3 > end || base+pos < head) 
23871 +                                       return 0;
23872 +                               val = (base[pos]<<24) + (base[pos+1]<<16) +
23873 +                                       (base[pos+2]<<8) + base[pos+3];
23874 +                               break;
23875 +                       }
23876 +               }
23877 +               nvals = data->tests[testind].nvalues;
23878 +               for (i=0; i < nvals; i++) {
23879 +                       if ((data->tests[testind].value[i].min <= val) &&
23880 +                           (val <= data->tests[testind].value[i].max)) {
23881 +                               break;
23882 +                       }
23883 +               }
23884 +               if (i >= data->tests[testind].nvalues) {
23885 +                       /* cycles2 = get_cycles(); 
23886 +                          printk("failed %d in %d cycles\n", testind, 
23887 +                                 cycles2-cycles1); */
23888 +                       return 0;
23889 +               }
23890 +       }
23891 +       /* cycles2 = get_cycles();
23892 +          printk("succeeded in %d cycles\n", cycles2-cycles1); */
23893 +       return 1;
23894 +}
23895 +
23896 +static int
23897 +checkentry(const char *tablename,
23898 +           const struct ipt_ip *ip,
23899 +           void *matchinfo,
23900 +           unsigned int matchsize,
23901 +           unsigned int hook_mask)
23902 +{
23903 +       if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
23904 +               return 0;
23905 +       return 1;
23906 +}
23907 +
23908 +static struct ipt_match u32_match
23909 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
23910 +
23911 +static int __init init(void)
23912 +{
23913 +       return ipt_register_match(&u32_match);
23914 +}
23915 +
23916 +static void __exit fini(void)
23917 +{
23918 +       ipt_unregister_match(&u32_match);
23919 +}
23920 +
23921 +module_init(init);
23922 +module_exit(fini);
23923 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/ipt_unclean.c linux-2.4.20/net/ipv4/netfilter/ipt_unclean.c
23924 --- linux-2.4.20.org/net/ipv4/netfilter/ipt_unclean.c   Thu Nov 28 23:53:15 2002
23925 +++ linux-2.4.20/net/ipv4/netfilter/ipt_unclean.c       Wed Sep 24 09:16:24 2003
23926 @@ -259,6 +259,24 @@
23927  #define        TH_ECE  0x40
23928  #define        TH_CWR  0x80
23929  
23930 +/* table of valid flag combinations - ECE and CWR are always valid */
23931 +static u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG) + 1] =
23932 +{
23933 +       [TH_SYN]                        = 1,
23934 +       [TH_SYN|TH_ACK]                 = 1,
23935 +       [TH_RST]                        = 1,
23936 +       [TH_RST|TH_ACK]                 = 1,
23937 +       [TH_RST|TH_ACK|TH_PUSH]         = 1,
23938 +       [TH_FIN|TH_ACK]                 = 1,
23939 +       [TH_ACK]                        = 1,
23940 +       [TH_ACK|TH_PUSH]                = 1,
23941 +       [TH_ACK|TH_URG]                 = 1,
23942 +       [TH_ACK|TH_URG|TH_PUSH]         = 1,
23943 +       [TH_FIN|TH_ACK|TH_PUSH]         = 1,
23944 +       [TH_FIN|TH_ACK|TH_URG]          = 1,
23945 +       [TH_FIN|TH_ACK|TH_URG|TH_PUSH]  = 1
23946 +};
23947 +
23948  /* TCP-specific checks. */
23949  static int
23950  check_tcp(const struct iphdr *iph,
23951 @@ -330,19 +348,7 @@
23952  
23953         /* CHECK: TCP flags. */
23954         tcpflags = (((u_int8_t *)tcph)[13] & ~(TH_ECE|TH_CWR));
23955 -       if (tcpflags != TH_SYN
23956 -           && tcpflags != (TH_SYN|TH_ACK)
23957 -               && tcpflags != TH_RST
23958 -           && tcpflags != (TH_RST|TH_ACK)
23959 -           && tcpflags != (TH_RST|TH_ACK|TH_PUSH)
23960 -           && tcpflags != (TH_FIN|TH_ACK)
23961 -           && tcpflags != TH_ACK
23962 -           && tcpflags != (TH_ACK|TH_PUSH)
23963 -           && tcpflags != (TH_ACK|TH_URG)
23964 -           && tcpflags != (TH_ACK|TH_URG|TH_PUSH)
23965 -           && tcpflags != (TH_FIN|TH_ACK|TH_PUSH)
23966 -           && tcpflags != (TH_FIN|TH_ACK|TH_URG)
23967 -           && tcpflags != (TH_FIN|TH_ACK|TH_URG|TH_PUSH)) {
23968 +       if (!tcp_valid_flags[tcpflags]) {
23969                 limpk("TCP flags bad: %u\n", tcpflags);
23970                 return 0;
23971         }
23972 @@ -521,6 +527,16 @@
23973                 return 0;
23974         }
23975  
23976 +       /* CHECK: Do not use what is unused.
23977 +        * First bit of fragmentation flags should be unused.
23978 +        * May be used by OS fingerprinting tools.
23979 +        * 04 Jun 2002, Maciej Soltysiak, solt@dns.toxicfilms.tv
23980 +        */
23981 +       if (ntohs(iph->frag_off)>>15) {
23982 +               limpk("IP unused bit set\n");
23983 +               return 0;
23984 +       }
23985 +
23986         /* Per-protocol checks. */
23987         switch (iph->protocol) {
23988         case IPPROTO_ICMP:
23989 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/iptable_mangle.c linux-2.4.20/net/ipv4/netfilter/iptable_mangle.c
23990 --- linux-2.4.20.org/net/ipv4/netfilter/iptable_mangle.c        Mon Feb 25 19:38:14 2002
23991 +++ linux-2.4.20/net/ipv4/netfilter/iptable_mangle.c    Wed Sep 24 09:16:14 2003
23992 @@ -170,7 +170,7 @@
23993  static struct nf_hook_ops ipt_ops[]
23994  = { { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_PRE_ROUTING, 
23995         NF_IP_PRI_MANGLE },
23996 -    { { NULL, NULL }, ipt_local_hook, PF_INET, NF_IP_LOCAL_IN,
23997 +    { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_LOCAL_IN,
23998         NF_IP_PRI_MANGLE },
23999      { { NULL, NULL }, ipt_route_hook, PF_INET, NF_IP_FORWARD,
24000         NF_IP_PRI_MANGLE },
24001 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/iptable_raw.c linux-2.4.20/net/ipv4/netfilter/iptable_raw.c
24002 --- linux-2.4.20.org/net/ipv4/netfilter/iptable_raw.c   Thu Jan  1 00:00:00 1970
24003 +++ linux-2.4.20/net/ipv4/netfilter/iptable_raw.c       Wed Sep 24 09:18:12 2003
24004 @@ -0,0 +1,151 @@
24005 +/* 
24006 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
24007 + *
24008 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
24009 + */
24010 +#include <linux/module.h>
24011 +#include <linux/netfilter_ipv4/ip_tables.h>
24012 +
24013 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
24014 +
24015 +/* Standard entry. */
24016 +struct ipt_standard
24017 +{
24018 +       struct ipt_entry entry;
24019 +       struct ipt_standard_target target;
24020 +};
24021 +
24022 +struct ipt_error_target
24023 +{
24024 +       struct ipt_entry_target target;
24025 +       char errorname[IPT_FUNCTION_MAXNAMELEN];
24026 +};
24027 +
24028 +struct ipt_error
24029 +{
24030 +       struct ipt_entry entry;
24031 +       struct ipt_error_target target;
24032 +};
24033 +
24034 +static struct
24035 +{
24036 +       struct ipt_replace repl;
24037 +       struct ipt_standard entries[2];
24038 +       struct ipt_error term;
24039 +} initial_table __initdata
24040 += { { "raw", RAW_VALID_HOOKS, 3,
24041 +      sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
24042 +      { [NF_IP_PRE_ROUTING] 0,
24043 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
24044 +      { [NF_IP_PRE_ROUTING] 0,
24045 +       [NF_IP_LOCAL_OUT] sizeof(struct ipt_standard) },
24046 +      0, NULL, { } },
24047 +    {
24048 +           /* PRE_ROUTING */
24049 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
24050 +               0,
24051 +               sizeof(struct ipt_entry),
24052 +               sizeof(struct ipt_standard),
24053 +               0, { 0, 0 }, { } },
24054 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
24055 +               -NF_ACCEPT - 1 } },
24056 +           /* LOCAL_OUT */
24057 +           { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
24058 +               0,
24059 +               sizeof(struct ipt_entry),
24060 +               sizeof(struct ipt_standard),
24061 +               0, { 0, 0 }, { } },
24062 +             { { { { IPT_ALIGN(sizeof(struct ipt_standard_target)), "" } }, { } },
24063 +               -NF_ACCEPT - 1 } }
24064 +    },
24065 +    /* ERROR */
24066 +    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
24067 +       0,
24068 +       sizeof(struct ipt_entry),
24069 +       sizeof(struct ipt_error),
24070 +       0, { 0, 0 }, { } },
24071 +      { { { { IPT_ALIGN(sizeof(struct ipt_error_target)), IPT_ERROR_TARGET } },
24072 +         { } },
24073 +       "ERROR"
24074 +      }
24075 +    }
24076 +};
24077 +
24078 +static struct ipt_table packet_raw = { 
24079 +       .list = { NULL, NULL }, 
24080 +       .name = "raw", 
24081 +       .table = &initial_table.repl,
24082 +       .valid_hooks =  RAW_VALID_HOOKS, 
24083 +       .lock = RW_LOCK_UNLOCKED, 
24084 +       .private = NULL, 
24085 +       .me = THIS_MODULE
24086 +};
24087 +
24088 +/* The work comes in here from netfilter.c. */
24089 +static unsigned int
24090 +ipt_hook(unsigned int hook,
24091 +        struct sk_buff **pskb,
24092 +        const struct net_device *in,
24093 +        const struct net_device *out,
24094 +        int (*okfn)(struct sk_buff *))
24095 +{
24096 +       return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
24097 +}
24098 +
24099 +/* 'raw' is the very first table. */
24100 +static struct nf_hook_ops ipt_ops[] = {
24101 +       /* PRE_ROUTING hook */
24102 +       { .list = { NULL, NULL }, 
24103 +         .hook = ipt_hook, 
24104 +         .pf = PF_INET, 
24105 +         .hooknum = NF_IP_PRE_ROUTING, 
24106 +         .priority = NF_IP_PRI_FIRST },
24107 +       /* LOCAL_OUT hook */
24108 +       { .list = { NULL, NULL }, 
24109 +         .hook = ipt_hook, 
24110 +         .pf = PF_INET, 
24111 +         .hooknum = NF_IP_LOCAL_OUT, 
24112 +         .priority = NF_IP_PRI_FIRST }
24113 +};
24114 +
24115 +static int __init init(void)
24116 +{
24117 +       int ret;
24118 +
24119 +       /* Register table */
24120 +       ret = ipt_register_table(&packet_raw);
24121 +       if (ret < 0)
24122 +               return ret;
24123 +
24124 +       /* Register hooks */
24125 +       ret = nf_register_hook(&ipt_ops[0]);
24126 +       if (ret < 0)
24127 +               goto cleanup_table;
24128 +
24129 +       ret = nf_register_hook(&ipt_ops[1]);
24130 +       if (ret < 0)
24131 +               goto cleanup_hook0;
24132 +
24133 +       return ret;
24134 +
24135 + cleanup_hook0:
24136 +       nf_unregister_hook(&ipt_ops[0]);
24137 + cleanup_table:
24138 +       ipt_unregister_table(&packet_raw);
24139 +
24140 +       return ret;
24141 +}
24142 +
24143 +static void __exit fini(void)
24144 +{
24145 +       unsigned int i;
24146 +
24147 +       for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
24148 +               nf_unregister_hook(&ipt_ops[i]);
24149 +
24150 +       ipt_unregister_table(&packet_raw);
24151 +}
24152 +
24153 +module_init(init);
24154 +module_exit(fini);
24155 +MODULE_LICENSE("GPL");
24156 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/nfnetlink.c linux-2.4.20/net/ipv4/netfilter/nfnetlink.c
24157 --- linux-2.4.20.org/net/ipv4/netfilter/nfnetlink.c     Thu Jan  1 00:00:00 1970
24158 +++ linux-2.4.20/net/ipv4/netfilter/nfnetlink.c Wed Sep 24 09:17:51 2003
24159 @@ -0,0 +1,344 @@
24160 +/* Netfilter messages via netlink socket. Allows for user space
24161 + * protocol helpers and general trouble making from userspace.
24162 + *
24163 + * (C) 2001 by Jay Schulist <jschlst@samba.org>,
24164 + * (C) 2002 by Harald Welte <laforge@gnumonks.org>
24165 + *
24166 + * Initial netfilter messages via netlink development funded and
24167 + * generally made possible by Network Robots, Inc. (www.networkrobots.com)
24168 + *
24169 + * Further development of this code funded by Astaro AG (http://www.astaro.com)
24170 + *
24171 + * This software may be used and distributed according to the terms
24172 + * of the GNU General Public License, incorporated herein by reference.
24173 + */
24174 +
24175 +#include <linux/config.h>
24176 +#include <linux/module.h>
24177 +#include <linux/types.h>
24178 +#include <linux/socket.h>
24179 +#include <linux/kernel.h>
24180 +#include <linux/major.h>
24181 +#include <linux/sched.h>
24182 +#include <linux/timer.h>
24183 +#include <linux/string.h>
24184 +#include <linux/sockios.h>
24185 +#include <linux/net.h>
24186 +#include <linux/fcntl.h>
24187 +#include <linux/skbuff.h>
24188 +#include <asm/uaccess.h>
24189 +#include <asm/system.h>
24190 +#include <net/sock.h>
24191 +#include <linux/init.h>
24192 +#include <linux/spinlock.h>
24193 +#include <linux/list.h>
24194 +
24195 +#include <linux/netfilter.h>
24196 +#include <linux/netlink.h>
24197 +#include <linux/nfnetlink.h>
24198 +
24199 +MODULE_LICENSE("GPL");
24200 +
24201 +char nfversion[] = "0.11";
24202 +int nf_debug_level = 1;
24203 +#define nf_debug(level, format, arg...) \
24204 +        if(nf_debug_level > level)  \
24205 +                printk(__FUNCTION__ ": " format, ## arg)
24206 +
24207 +static struct sock *nfnl = NULL;
24208 +static LIST_HEAD(subsys_list);
24209 +static struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
24210 +DECLARE_MUTEX(nfnl_sem);
24211 +
24212 +void nfnl_lock(void)
24213 +{
24214 +       nfnl_shlock();
24215 +       nfnl_exlock();
24216 +}
24217 +
24218 +void nfnl_unlock(void)
24219 +{
24220 +       nfnl_exunlock();
24221 +       nfnl_shunlock();
24222 +}
24223 +
24224 +struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count)
24225 +{
24226 +       int size;
24227 +       struct nfnetlink_subsystem *ss;
24228 +
24229 +       size = sizeof(struct nfnetlink_subsystem)
24230 +               + (cb_count * sizeof(struct nfnl_callback));
24231 +
24232 +       ss = kmalloc(size, GFP_KERNEL);
24233 +       if (!ss)
24234 +               return NULL;
24235 +       memset(ss, 0, size);
24236 +
24237 +       return ss;
24238 +}
24239 +
24240 +int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
24241 +{
24242 +       MOD_INC_USE_COUNT;
24243 +
24244 +       nf_debug(0, "registering subsystem ID %u\n", n->subsys_id);
24245 +
24246 +       nfnl_lock();
24247 +       list_add(&n->list, &subsys_list);
24248 +       subsys_table[n->subsys_id] = n;
24249 +       nfnl_unlock();
24250 +
24251 +       return 0;
24252 +}
24253 +
24254 +int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
24255 +{
24256 +       nf_debug(0, "unregistering subsystem ID %u\n", n->subsys_id);
24257 +
24258 +       nfnl_lock();
24259 +       subsys_table[n->subsys_id] = NULL;
24260 +       list_del(&n->list);
24261 +       nfnl_unlock();
24262 +
24263 +       MOD_DEC_USE_COUNT;
24264 +
24265 +       return 0;
24266 +}
24267 +
24268 +struct nfnl_callback *nfnetlink_find_client(u_int16_t nlmsg_type)
24269 +{
24270 +       struct nfnetlink_subsystem *ss;
24271 +       u_int8_t subsys_id = NFNL_SUBSYS_ID(nlmsg_type);
24272 +       u_int8_t type = NFNL_MSG_TYPE(nlmsg_type);
24273 +
24274 +       if (subsys_id >= NFNL_SUBSYS_COUNT
24275 +           || subsys_table[subsys_id] == NULL)
24276 +               return NULL;
24277 +
24278 +       ss = subsys_table[subsys_id];
24279 +
24280 +       if (type >= ss->cb_count) {
24281 +               nf_debug(0, "msgtype %u >= %u, returning\n", type, 
24282 +                        ss->cb_count);
24283 +               return NULL;
24284 +       }
24285 +
24286 +       return &ss->cb[type];
24287 +}
24288 +
24289 +void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
24290 +               const void *data)
24291 +{
24292 +       struct nfattr *nfa;
24293 +       int size = NFA_LENGTH(attrlen);
24294 +
24295 +       nfa = (struct nfattr *)skb_put(skb, NFA_ALIGN(size));
24296 +       nfa->nfa_type = attrtype;
24297 +       nfa->nfa_len  = size;
24298 +       memcpy(NFA_DATA(nfa), data, attrlen);
24299 +}
24300 +
24301 +int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
24302 +{
24303 +       memset(tb, 0, sizeof(struct nfattr *)*maxattr);
24304 +
24305 +       while (NFA_OK(nfa, len)) {
24306 +               unsigned flavor = nfa->nfa_type;
24307 +               if (flavor && flavor <= maxattr)
24308 +                       tb[flavor-1] = nfa;
24309 +               nfa = NFA_NEXT(nfa, len);
24310 +       }
24311 +
24312 +       return 0;
24313 +}
24314 +
24315 +/**
24316 + * nfnetlink_check_attributes - check and parse nfnetlink attributes
24317 + *
24318 + * subsys: nfnl subsystem for which this message is to be parsed
24319 + * nlmsghdr: netlink message to be checked/parsed
24320 + * cda: array of pointers, needs to be at least subsys->attr_count big
24321 + *
24322 + */
24323 +int
24324 +nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
24325 +                          struct nlmsghdr *nlh, struct nfattr *cda[])
24326 +{
24327 +       int min_len;
24328 +
24329 +       /* check attribute lengths. */
24330 +       min_len = sizeof(struct nfgenmsg);
24331 +       if (nlh->nlmsg_len < min_len)
24332 +               return -EINVAL;
24333 +
24334 +       if (nlh->nlmsg_len > min_len) {
24335 +               struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
24336 +               int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
24337 +
24338 +               while (NFA_OK(attr, attrlen)) {
24339 +                       unsigned flavor = attr->nfa_type;
24340 +                       if (flavor) {
24341 +                               if (flavor > subsys->attr_count)
24342 +                                       return -EINVAL;
24343 +                               cda[flavor - 1] = attr;
24344 +                       }
24345 +                       attr = NFA_NEXT(attr, attrlen);
24346 +               }
24347 +       } else
24348 +               return -EINVAL;
24349 +
24350 +        return 0;
24351 +}
24352 +
24353 +int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
24354 +{
24355 +       int err = 0;
24356 +
24357 +       NETLINK_CB(skb).dst_groups = group;
24358 +       if (echo)
24359 +               atomic_inc(&skb->users);
24360 +       netlink_broadcast(nfnl, skb, pid, group, GFP_KERNEL);
24361 +       if (echo)
24362 +               err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
24363 +
24364 +       return err;
24365 +}
24366 +
24367 +/* Process one complete nfnetlink message. */
24368 +static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
24369 +                                   struct nlmsghdr *nlh, int *errp)
24370 +{
24371 +       struct nfnl_callback *nc;
24372 +       int type, err = 0;
24373 +
24374 +       nf_debug(0, "entered; subsys=%u, msgtype=%u\n",
24375 +                NFNL_SUBSYS_ID(nlh->nlmsg_type),
24376 +                NFNL_MSG_TYPE(nlh->nlmsg_type));
24377 +
24378 +       /* Only requests are handled by kernel now. */
24379 +       if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
24380 +               nf_debug(0, "received non-request message\n");
24381 +               return 0;
24382 +       }
24383 +
24384 +       /* Unknown message: reply with EINVAL */
24385 +       type = nlh->nlmsg_type;
24386 +       if (NFNL_SUBSYS_ID(type) > NFNL_SUBSYS_COUNT) {
24387 +               nf_debug(0, "subsys_id > subsys_count\n");
24388 +               goto err_inval;
24389 +       }
24390 +
24391 +       /* All the messages must have at least 1 byte length */
24392 +       if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
24393 +               nf_debug(0, "received message was too short\n");
24394 +               return 0;
24395 +       }
24396 +
24397 +       nc = nfnetlink_find_client(type);
24398 +       if (!nc) {
24399 +               nf_debug(0, "unable to find client for type %d\n", type);
24400 +               goto err_inval;
24401 +       }
24402 +
24403 +       if (nc->cap_required && 
24404 +           !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) {
24405 +               nf_debug(0, "permission denied for type %d\n", type);
24406 +               *errp = -EPERM;
24407 +               return -1;
24408 +       }
24409 +
24410 +       err = nc->call(nfnl, skb, nlh, errp);
24411 +       *errp = err;
24412 +       return err;
24413 +
24414 +err_inval:
24415 +       *errp = -EINVAL;
24416 +       return -1;
24417 +}
24418 +
24419 +/* Process one packet of messages. */
24420 +static inline int nfnetlink_rcv_skb(struct sk_buff *skb)
24421 +{
24422 +       int err;
24423 +       struct nlmsghdr *nlh;
24424 +
24425 +       while (skb->len >= NLMSG_SPACE(0)) {
24426 +               u32 rlen;
24427 +
24428 +               nlh = (struct nlmsghdr *)skb->data;
24429 +               if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
24430 +                   || skb->len < nlh->nlmsg_len)
24431 +                       return 0;
24432 +               rlen = NLMSG_ALIGN(nlh->nlmsg_len);
24433 +               if (rlen > skb->len)
24434 +                       rlen = skb->len;
24435 +               if (nfnetlink_rcv_msg(skb, nlh, &err)) {
24436 +                       if (!err)
24437 +                               return -1;
24438 +                       netlink_ack(skb, nlh, err);
24439 +               } else
24440 +                       if (nlh->nlmsg_flags & NLM_F_ACK)
24441 +                               netlink_ack(skb, nlh, 0);
24442 +               skb_pull(skb, rlen);
24443 +       }
24444 +
24445 +       return 0;
24446 +}
24447 +
24448 +static void nfnetlink_rcv(struct sock *sk, int len)
24449 +{
24450 +       do {
24451 +               struct sk_buff *skb;
24452 +
24453 +               if (nfnl_shlock_nowait())
24454 +                       return;
24455 +
24456 +               while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
24457 +                       if (nfnetlink_rcv_skb(skb)) {
24458 +                               if (skb->len)
24459 +                                       skb_queue_head(&sk->receive_queue, skb);
24460 +                               else
24461 +                                       kfree_skb(skb);
24462 +                               break;
24463 +                       }
24464 +                       kfree_skb(skb);
24465 +               }
24466 +
24467 +               up(&nfnl_sem);
24468 +       } while(nfnl && nfnl->receive_queue.qlen);
24469 +}
24470 +
24471 +void __exit nfnetlink_exit(void)
24472 +{
24473 +       printk("Netfilter removing netlink socket.\n");
24474 +       sock_release(nfnl->socket);
24475 +       return;
24476 +}
24477 +
24478 +int __init nfnetlink_init(void)
24479 +{
24480 +       int i;
24481 +       printk("Netfilter messages via NETLINK v%s.\n", nfversion);
24482 +
24483 +       for (i = 0; i < NFNL_SUBSYS_COUNT; i++)
24484 +               subsys_table[i] = NULL;
24485 +
24486 +       nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
24487 +       if (!nfnl) {
24488 +               printk(KERN_ERR "cannot initialize nfnetlink!\n");
24489 +               return -1;
24490 +       }
24491 +
24492 +       return 0;
24493 +}
24494 +
24495 +module_init(nfnetlink_init);
24496 +module_exit(nfnetlink_exit);
24497 +
24498 +EXPORT_SYMBOL_GPL(nfnetlink_subsys_alloc);
24499 +EXPORT_SYMBOL_GPL(nfnetlink_subsys_register);
24500 +EXPORT_SYMBOL_GPL(nfnetlink_subsys_unregister);
24501 +EXPORT_SYMBOL_GPL(nfnetlink_check_attributes);
24502 +EXPORT_SYMBOL_GPL(nfnetlink_send);
24503 +EXPORT_SYMBOL_GPL(__nfa_fill);
24504 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv4/netfilter/nfnetlink_conntrack.c linux-2.4.20/net/ipv4/netfilter/nfnetlink_conntrack.c
24505 --- linux-2.4.20.org/net/ipv4/netfilter/nfnetlink_conntrack.c   Thu Jan  1 00:00:00 1970
24506 +++ linux-2.4.20/net/ipv4/netfilter/nfnetlink_conntrack.c       Wed Sep 24 09:17:51 2003
24507 @@ -0,0 +1,715 @@
24508 +/* Connection tracking via netlink socket. Allows for user space
24509 + * protocol helpers and general trouble making from userspace.
24510 + *
24511 + * (C) 2001 by Jay Schulist <jschlst@samba.org>
24512 + * (C) 2002 by Harald Welte <laforge@gnumonks.org>
24513 + *
24514 + * Initial connection tracking via netlink development funded and 
24515 + * generally made possible by Network Robots, Inc. (www.networkrobots.com)
24516 + *
24517 + * Further development of this code funded by Astaro AG (http://www.asaro.com)
24518 + *
24519 + * This software may be used and distributed according to the terms
24520 + * of the GNU General Public License, incorporated herein by reference.
24521 + */
24522 +
24523 +#include <linux/config.h>
24524 +#include <linux/module.h>
24525 +#include <linux/types.h>
24526 +#include <linux/socket.h>
24527 +#include <linux/kernel.h>
24528 +#include <linux/major.h>
24529 +#include <linux/sched.h>
24530 +#include <linux/timer.h>
24531 +#include <linux/string.h>
24532 +#include <linux/sockios.h>
24533 +#include <linux/net.h>
24534 +#include <linux/fcntl.h>
24535 +#include <linux/skbuff.h>
24536 +#include <asm/uaccess.h>
24537 +#include <asm/system.h>
24538 +#include <net/sock.h>
24539 +#include <linux/init.h>
24540 +#include <linux/netlink.h>
24541 +#include <linux/spinlock.h>
24542 +#include <linux/rtnetlink.h>
24543 +
24544 +#include <linux/netfilter.h>
24545 +#include <linux/netfilter_ipv4.h>
24546 +#include <linux/netfilter_ipv4/ip_tables.h>
24547 +#include <linux/netfilter_ipv4/ip_conntrack.h>
24548 +#include <linux/netfilter_ipv4/ip_conntrack_core.h>
24549 +
24550 +#include <linux/nfnetlink.h>
24551 +#include <linux/nfnetlink_conntrack.h>
24552 +
24553 +#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
24554 +#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
24555 +#include <linux/netfilter_ipv4/listhelp.h>
24556 +
24557 +MODULE_LICENSE("GPL");
24558 +
24559 +char ctversion[] = "0.11";
24560 +int ct_debug_level = 1;
24561 +#define ct_debug(level, format, arg...) \
24562 +       if(ct_debug_level > level)  \
24563 +               printk(__FUNCTION__ ": " format, ## arg)
24564 +
24565 +/* FIXME: this define is just needed for DUMP_TUPLE */
24566 +#define DEBUGP(format, args...)        ct_debug(0, format, ## args)
24567 +
24568 +static struct nfnetlink_subsystem *ctnl_subsys;
24569 +
24570 +static int
24571 +ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
24572 +                   int event, 
24573 +                   int nowait, 
24574 +                   const struct ip_conntrack *ct, 
24575 +                   const enum ip_conntrack_info *ctinfo, 
24576 +                   unsigned char proto,
24577 +                   const struct net_device *in,
24578 +                   const struct net_device *out)
24579 +{
24580 +       struct nlmsghdr *nlh;
24581 +       struct nfgenmsg *nfmsg;
24582 +       struct cta_proto cp;
24583 +       unsigned long s;
24584 +       unsigned char *b;
24585 +
24586 +       b = skb->tail;
24587 +       nlh = NLMSG_PUT(skb, pid, seq, (NFNL_SUBSYS_CTNETLINK<<8)|event, 
24588 +                       sizeof(struct nfgenmsg));
24589 +       nfmsg = NLMSG_DATA(nlh);
24590 +
24591 +       nlh->nlmsg_flags        = (nowait && pid) ? NLM_F_MULTI : 0;
24592 +       nfmsg->nfgen_family     = AF_INET;
24593 +       NFA_PUT(skb, CTA_ORIG, sizeof(struct ip_conntrack_tuple), 
24594 +               &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
24595 +       NFA_PUT(skb, CTA_RPLY, sizeof(struct ip_conntrack_tuple),
24596 +               &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
24597 +       s = ct->status;
24598 +       NFA_PUT(skb, CTA_STATUS, sizeof(unsigned long), &s);
24599 +       if (in)
24600 +               NFA_PUT(skb, CTA_IIF, IFNAMSIZ, in->name);
24601 +       if (out)
24602 +               NFA_PUT(skb, CTA_OIF, IFNAMSIZ, out->name);
24603 +       if (ctinfo)
24604 +               NFA_PUT(skb, CTA_INFO, sizeof(unsigned long), ctinfo);
24605 +
24606 +       cp.num_proto = proto;
24607 +       memcpy(&cp.proto, &ct->proto, sizeof (cp.proto));
24608 +       NFA_PUT(skb, CTA_PROTOINFO, sizeof(cp), &cp);
24609 +
24610 +       if (ct->helper) {
24611 +               struct cta_help ch;
24612 +
24613 +               memcpy(&ch.tuple, &ct->helper->tuple, 
24614 +                       sizeof(struct ip_conntrack_tuple));
24615 +               memcpy(&ch.mask, &ct->helper->mask,
24616 +                       sizeof(struct ip_conntrack_tuple));
24617 +               strncpy((char *)&ch.name, ct->helper->name, sizeof(ch.name));
24618 +               memcpy(&ch.help, &ct->help, sizeof(ch.help));
24619 +               NFA_PUT(skb, CTA_HELPINFO, sizeof(ch), &ch);
24620 +       }
24621 +
24622 +#ifdef CONFIG_IP_NF_NAT_NEEDED
24623 +       if (ct->nat.info.initialized && ct->nat.info.num_manips) {
24624 +               const struct ip_nat_info *nat = &ct->nat.info;
24625 +               struct cta_nat cn;
24626 +
24627 +               cn.num_manips = nat->num_manips;
24628 +               memcpy(&cn.manips, &nat->manips, (nat->num_manips 
24629 +                       * sizeof(struct ip_nat_info_manip)));
24630 +               NFA_PUT(skb, CTA_NATINFO, sizeof(struct cta_nat), &cn);
24631 +       }
24632 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
24633 +
24634 +       nlh->nlmsg_len = skb->tail - b;
24635 +       return skb->len;
24636 +
24637 +nlmsg_failure:
24638 +nfattr_failure:
24639 +       skb_trim(skb, b - skb->data);
24640 +       return -1;
24641 +}
24642 +
24643 +static inline struct sk_buff *
24644 +ctnetlink_event_build_msg(const struct ip_conntrack *ct, 
24645 +                         const enum ip_conntrack_info ctinfo, 
24646 +                         const unsigned char proto,
24647 +                         const struct net_device *in,
24648 +                         const struct net_device *out)
24649 +{
24650 +       struct sk_buff *skb;
24651 +       int err;
24652 +
24653 +       skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24654 +       if (!skb)
24655 +               return NULL;
24656 +
24657 +       err = ctnetlink_fill_info(skb, 0, 0, CTNL_MSG_NEWCONNTRACK, 1, ct,
24658 +                                 &ctinfo, proto, in, out);
24659 +       if (err <= 0)
24660 +               goto nlmsg_failure;
24661 +       return skb;
24662 +
24663 +nlmsg_failure:
24664 +       return NULL;
24665 +}
24666 +
24667 +static void
24668 +ctnetlink_create(struct ip_conntrack *ct,
24669 +                enum ip_conntrack_info ctinfo,
24670 +                const struct net_device *in, 
24671 +                const struct net_device *out)
24672 +{
24673 +       u16 proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
24674 +       struct sk_buff *skb;
24675 +
24676 +       skb = ctnetlink_event_build_msg(ct, ctinfo, proto, in, out);
24677 +       if (!skb)
24678 +               return;
24679 +
24680 +       if (proto == IPPROTO_TCP) {
24681 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
24682 +               return;
24683 +               } else if (proto == IPPROTO_UDP) {
24684 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
24685 +               return;
24686 +               } else if (proto == IPPROTO_ICMP) {
24687 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
24688 +               return;
24689 +       } else {
24690 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
24691 +               return;
24692 +       }
24693 +       kfree_skb(skb);
24694 +       return;
24695 +}
24696 +
24697 +#if 0
24698 +static void ctnetlink_destroy(struct ip_conntrack *ct)
24699 +{
24700 +        ctnetlink_create(ct, IP_CT_DELETE, NULL, NULL);
24701 +}
24702 +#endif
24703 +
24704 +static inline int ctnetlink_kill(const struct ip_conntrack *i, void *data)
24705 +{
24706 +       struct ip_conntrack *t = (struct ip_conntrack *)data;
24707 +
24708 +       if (!memcmp(&i->tuplehash[IP_CT_DIR_ORIGINAL], 
24709 +           &t->tuplehash[IP_CT_DIR_ORIGINAL], 
24710 +           sizeof(struct ip_conntrack_tuple_hash))) {
24711 +               //ip_conntrack_put(t);
24712 +               nf_conntrack_put(&t->infos[0]);
24713 +               return 1;
24714 +       }
24715 +
24716 +       return 0;
24717 +}
24718 +
24719 +static int
24720 +ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb, 
24721 +                       struct nlmsghdr *nlh, int *errp)
24722 +{
24723 +        struct ip_conntrack_tuple_hash *h;
24724 +       struct ip_conntrack_tuple *tuple;
24725 +       struct nfattr *cda[CTA_MAX];
24726 +
24727 +       ct_debug(0, "entered\n");
24728 +
24729 +       if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24730 +               return -EINVAL;
24731 +
24732 +       if (cda[CTA_ORIG-1])
24733 +               tuple = NFA_DATA(cda[CTA_ORIG-1]);
24734 +       else {
24735 +               if (cda[CTA_RPLY-1])
24736 +                       tuple = NFA_DATA(cda[CTA_RPLY-1]);
24737 +               else {
24738 +                       ct_debug(0, "no tuple found in request\n");
24739 +                       return -EINVAL;
24740 +               }
24741 +       }
24742 +
24743 +       h = ip_conntrack_find_get(tuple, NULL);
24744 +        if (!h) {
24745 +               ct_debug(0, "tuple not found in conntrack hash:");
24746 +               DUMP_TUPLE(tuple);
24747 +               return -ENOENT;
24748 +       }
24749 +
24750 +       ct_debug(0, "calling selective_cleanup\n");
24751 +       ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack);
24752 +
24753 +       return 0;
24754 +}
24755 +
24756 +static int ctnetlink_done(struct netlink_callback *cb)
24757 +{
24758 +       ct_debug(0, "entering\n");
24759 +        return 0;
24760 +}
24761 +
24762 +static int
24763 +ctnetlink_dump_build_msg(const struct ip_conntrack_tuple_hash *hash,
24764 +                        struct sk_buff *skb, u32 pid, u32 seq)
24765 +{
24766 +       struct ip_conntrack *ct;
24767 +       int err, proto;
24768 +
24769 +       /* Only count originals */
24770 +       if (DIRECTION(hash))
24771 +               return 0;
24772 +
24773 +       ct = hash->ctrack;
24774 +       if (!ct)
24775 +               goto nlmsg_failure;
24776 +
24777 +       proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
24778 +       err = ctnetlink_fill_info(skb, pid, seq, CTNL_MSG_NEWCONNTRACK, 1,
24779 +                                 ct, NULL, proto, NULL, NULL);
24780 +       if (err <= 0)
24781 +               goto nlmsg_failure;
24782 +       return 0;
24783 +
24784 +nlmsg_failure:
24785 +       if (skb)
24786 +               kfree_skb(skb);
24787 +       return -1;
24788 +}
24789 +
24790 +static int
24791 +ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
24792 +{
24793 +       int i;
24794 +       int idx;
24795 +       int s_idx = cb->args[0];
24796 +
24797 +       /* Traverse hash; send originals then reply. */
24798 +       READ_LOCK(&ip_conntrack_lock);
24799 +        for (i = 0, idx = 0; i < ip_conntrack_htable_size; i++, idx++) {
24800 +               if (idx < s_idx)
24801 +                       continue;
24802 +               if (LIST_FIND(&ip_conntrack_hash[i], ctnetlink_dump_build_msg,
24803 +                             struct ip_conntrack_tuple_hash *, skb,
24804 +                             NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq))
24805 +                       continue;
24806 +       }
24807 +       READ_UNLOCK(&ip_conntrack_lock);
24808 +
24809 +       cb->args[0] = idx;
24810 +       return skb->len;
24811 +}
24812 +
24813 +static int
24814 +ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, 
24815 +                       struct nlmsghdr *nlh, int *errp)
24816 +{
24817 +       struct ip_conntrack_tuple_hash *h;
24818 +       struct ip_conntrack_tuple *tuple;
24819 +       struct nfattr *cda[CTA_MAX];
24820 +       struct ip_conntrack *ct;
24821 +       struct sk_buff *skb2 = NULL;
24822 +       int err, proto;
24823 +
24824 +       ct_debug(0, "entered\n");
24825 +
24826 +       if (nlh->nlmsg_flags & NLM_F_DUMP) {
24827 +               struct nfgenmsg *msg = NLMSG_DATA(nlh);
24828 +               u32 rlen;
24829 +
24830 +               if (msg->nfgen_family != AF_INET)
24831 +                       return -EAFNOSUPPORT;
24832 +
24833 +               ct_debug(0, "starting dump\n");
24834 +                if ((*errp = netlink_dump_start(ctnl, skb, nlh,
24835 +                                               ctnetlink_dump_table,
24836 +                                               ctnetlink_done)) != 0)
24837 +                       return -EINVAL;
24838 +               rlen = NLMSG_ALIGN(nlh->nlmsg_len);
24839 +               if (rlen > skb->len)
24840 +                       rlen = skb->len;
24841 +               skb_pull(skb, rlen);
24842 +               return 0;
24843 +       }
24844 +
24845 +       if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24846 +               return -EINVAL;
24847 +
24848 +       if (cda[CTA_ORIG-1])
24849 +               tuple = NFA_DATA(cda[CTA_ORIG-1]);
24850 +       else {
24851 +               if (cda[CTA_RPLY-1])
24852 +                       tuple = NFA_DATA(cda[CTA_RPLY-1]);
24853 +               else
24854 +                       return -EINVAL;
24855 +       }
24856 +
24857 +       h = ip_conntrack_find_get(tuple, NULL);
24858 +       if (!h)
24859 +               return -ENOENT;
24860 +
24861 +       ct = h->ctrack;
24862 +       if (!ct)
24863 +               goto nlmsg_failure;
24864 +
24865 +       skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24866 +       if (!skb2)
24867 +               return -ENOMEM;
24868 +       NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
24869 +
24870 +        proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
24871 +       err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
24872 +                                 CTNL_MSG_NEWCONNTRACK, 1, ct, NULL, 
24873 +                                 proto, NULL, NULL);
24874 +       ip_conntrack_put(ct);
24875 +       if (err <= 0)
24876 +               goto nlmsg_failure;
24877 +
24878 +       err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
24879 +       if (err < 0)
24880 +               return err;
24881 +       return 0;
24882 +
24883 +nlmsg_failure:
24884 +       if (skb2)
24885 +               kfree_skb(skb2);
24886 +       return -1;
24887 +}
24888 +
24889 +/* Finish me: should support NLM_F_CREATE and NLM_F_REPLACE. */
24890 +static int 
24891 +ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, 
24892 +                       struct nlmsghdr *nlh, int *errp)
24893 +{
24894 +       return -EOPNOTSUPP;
24895 +}
24896 +
24897 +
24898 +/* EXPECT */
24899 +
24900 +static int
24901 +ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
24902 +                   int event, 
24903 +                   int nowait, 
24904 +                   const struct ip_conntrack_expect *exp)
24905 +{
24906 +       struct nlmsghdr *nlh;
24907 +       struct nfgenmsg *nfmsg;
24908 +       unsigned char *b;
24909 +
24910 +       b = skb->tail;
24911 +       nlh = NLMSG_PUT(skb, pid, seq, (NFNL_SUBSYS_CTNETLINK<<8)|event, 
24912 +                       sizeof(struct nfgenmsg));
24913 +       nlh->nlmsg_flags        = (nowait && pid) ? NLM_F_MULTI : 0;
24914 +       nfmsg = NLMSG_DATA(nlh);
24915 +       nfmsg->nfgen_family = AF_INET;
24916 +
24917 +       NFA_PUT(skb, CTA_EXP_TUPLE, sizeof(struct ip_conntrack_tuple),
24918 +               &exp->tuple);
24919 +       NFA_PUT(skb, CTA_EXP_MASK, sizeof(struct ip_conntrack_tuple),
24920 +               &exp->mask);
24921 +       NFA_PUT(skb, CTA_EXP_SEQNO, sizeof(u_int32_t), &exp->seq);
24922 +       NFA_PUT(skb, CTA_EXP_HELP, sizeof(union ip_conntrack_expect_help),
24923 +               &exp->help);
24924 +
24925 +       /* FIXME: proto */
24926 +
24927 +#ifdef CONFIG_IP_NF_NAT_NEEDED
24928 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
24929 +
24930 +       nlh->nlmsg_len = skb->tail - b;
24931 +       return skb->len;
24932 +
24933 +nlmsg_failure:
24934 +nfattr_failure:
24935 +       skb_trim(skb, b - skb->data);
24936 +       return -1;
24937 +}
24938 +
24939 +static inline struct sk_buff *
24940 +ctnetlink_exp_event_build_msg(const struct ip_conntrack_expect *exp)
24941 +{
24942 +       struct sk_buff *skb;
24943 +       int err;
24944 +
24945 +       skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24946 +       if (!skb)
24947 +               return NULL;
24948 +
24949 +       err = ctnetlink_exp_fill_info(skb, 0, 0, CTNL_MSG_NEWEXPECT, 1, exp);
24950 +       if (err <= 0)
24951 +               goto nlmsg_failure;
24952 +       return skb;
24953 +
24954 +nlmsg_failure:
24955 +       if (skb)
24956 +               kfree_skb(skb);
24957 +        return NULL;
24958 +}
24959 +
24960 +static void
24961 +ctnetlink_exp_create(struct ip_conntrack_expect *exp)
24962 +{
24963 +       u16 proto = exp->tuple.dst.protonum;
24964 +       struct sk_buff *skb;
24965 +
24966 +       skb = ctnetlink_exp_event_build_msg(exp);
24967 +       if (!skb)
24968 +               return;
24969 +
24970 +       if (proto == IPPROTO_TCP) {
24971 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
24972 +               return;
24973 +               } else if (proto == IPPROTO_UDP) {
24974 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
24975 +               return;
24976 +               } else if (proto == IPPROTO_ICMP) {
24977 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
24978 +               return;
24979 +       } else {
24980 +               nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
24981 +               return;
24982 +       }
24983 +       kfree_skb(skb);
24984 +       return;
24985 +}
24986 +
24987 +
24988 +static int
24989 +ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
24990 +                    struct nlmsghdr *nlh, int *errp)
24991 +{
24992 +        struct ip_conntrack_expect *exp;
24993 +       struct ip_conntrack_tuple *tuple;
24994 +       struct nfattr *cda[CTA_MAX];
24995 +
24996 +       if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24997 +               return -EINVAL;
24998 +
24999 +       if (cda[CTA_ORIG-1])
25000 +               tuple = NFA_DATA(cda[CTA_ORIG-1]);
25001 +       else {
25002 +               if (cda[CTA_RPLY-1])
25003 +                       tuple = NFA_DATA(cda[CTA_RPLY-1]);
25004 +               else
25005 +                       return -EINVAL;
25006 +       }
25007 +
25008 +       /* bump usage count to 2 */
25009 +       exp = ip_conntrack_expect_find_get(tuple);
25010 +       if (!exp)
25011 +               return -ENOENT;
25012 +
25013 +       /* after list removal, usage count == 1 */
25014 +       ip_conntrack_unexpect_related(exp);
25015 +       /* we have put what we 'get' above. after this line usage count == 0 */
25016 +       ip_conntrack_expect_put(exp);
25017 +
25018 +       return 0;
25019 +}
25020 +
25021 +static int
25022 +ctnetlink_exp_dump_build_msg(const struct ip_conntrack_expect *exp,
25023 +                        struct sk_buff *skb, u32 pid, u32 seq)
25024 +{
25025 +       int err, proto;
25026 +
25027 +       proto = exp->tuple.dst.protonum;
25028 +       err = ctnetlink_exp_fill_info(skb, pid, seq, CTNL_MSG_NEWEXPECT, 1, 
25029 +                                     exp);
25030 +       if (err <= 0)
25031 +               goto nlmsg_failure;
25032 +       return 0;
25033 +
25034 +nlmsg_failure:
25035 +       if (skb)
25036 +               kfree_skb(skb);
25037 +       return -1;
25038 +}
25039 +
25040 +static int
25041 +ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
25042 +{
25043 +       ct_debug(0, "entered\n");
25044 +       if (cb->args[0] == 0) {
25045 +               READ_LOCK(&ip_conntrack_lock);
25046 +               LIST_FIND(&ip_conntrack_expect_list, 
25047 +                         ctnetlink_exp_dump_build_msg,
25048 +                         struct ip_conntrack_expect *, skb,
25049 +                         NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq);
25050 +               READ_UNLOCK(&ip_conntrack_lock);
25051 +               cb->args[0] = 1;
25052 +       }
25053 +       ct_debug(0, "returning\n");
25054 +
25055 +       return skb->len;
25056 +}
25057 +
25058 +
25059 +static int
25060 +ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, 
25061 +                    struct nlmsghdr *nlh, int *errp)
25062 +{
25063 +       struct ip_conntrack_expect *exp;
25064 +       struct ip_conntrack_tuple *tuple;
25065 +       struct nfattr *cda[CTA_MAX];
25066 +       struct sk_buff *skb2 = NULL;
25067 +       int err, proto;
25068 +
25069 +       ct_debug(0, "entered\n");
25070 +
25071 +       if (nlh->nlmsg_flags & NLM_F_DUMP) {
25072 +               struct nfgenmsg *msg = NLMSG_DATA(nlh);
25073 +               u32 rlen;
25074 +
25075 +               if (msg->nfgen_family != AF_INET)
25076 +                       return -EAFNOSUPPORT;
25077 +
25078 +               ct_debug(0, "starting dump\n");
25079 +                if ((*errp = netlink_dump_start(ctnl, skb, nlh,
25080 +                                               ctnetlink_exp_dump_table,
25081 +                                               ctnetlink_done)) != 0)
25082 +                       return -EINVAL;
25083 +               rlen = NLMSG_ALIGN(nlh->nlmsg_len);
25084 +               if (rlen > skb->len)
25085 +                       rlen = skb->len;
25086 +               skb_pull(skb, rlen);
25087 +               return 0;
25088 +       }
25089 +
25090 +       if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
25091 +               return -EINVAL;
25092 +
25093 +       if (cda[CTA_ORIG-1])
25094 +               tuple = NFA_DATA(cda[CTA_ORIG-1]);
25095 +       else {
25096 +               if (cda[CTA_RPLY-1])
25097 +                       tuple = NFA_DATA(cda[CTA_RPLY-1]);
25098 +               else
25099 +                       return -EINVAL;
25100 +       }
25101 +
25102 +       exp = ip_conntrack_expect_find_get(tuple);
25103 +       if (!exp)
25104 +               return -ENOENT;
25105 +
25106 +       skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
25107 +       if (!skb2)
25108 +               return -ENOMEM;
25109 +       NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
25110 +       proto = exp->tuple.dst.protonum;
25111 +       
25112 +       err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid, 
25113 +                                     nlh->nlmsg_seq, CTNL_MSG_NEWEXPECT,
25114 +                                     1, exp);
25115 +       if (err <= 0)
25116 +               goto nlmsg_failure;
25117 +
25118 +       err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
25119 +       if (err < 0)
25120 +               return err;
25121 +       return 0;
25122 +
25123 +nlmsg_failure:
25124 +       if (skb2)
25125 +               kfree_skb(skb2);
25126 +       return -1;
25127 +}
25128 +
25129 +static int
25130 +ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
25131 +                    struct nlmsghdr *nlh, int *errp)
25132 +{
25133 +       return -EOPNOTSUPP;
25134 +}
25135 +
25136 +/* struct conntrack_expect stuff */
25137 +
25138 +#if 0
25139 +static struct ip_conntrack_notify ctnl_notify = { { NULL, NULL },
25140 +                                               ctnetlink_destroy,
25141 +                                               ctnetlink_create };
25142 +
25143 +static struct ip_conntrack_notify ctnl_exp_notify;
25144 +#endif
25145 +
25146 +static void __exit ctnetlink_exit(void)
25147 +{
25148 +       printk("ctnetlink: unregistering with nfnetlink.\n");
25149 +//     ip_conntrack_notify_unregister(&ctnl_exp_notify);
25150 +//     ip_conntrack_notify_unregister(&ctnl_notify);
25151 +       nfnetlink_subsys_unregister(ctnl_subsys);
25152 +       kfree(ctnl_subsys);
25153 +       return;
25154 +}
25155 +
25156 +static int __init ctnetlink_init(void)
25157 +{
25158 +       int ret;
25159 +
25160 +       ctnl_subsys = nfnetlink_subsys_alloc(CTNL_MSG_COUNT);
25161 +       if (!ctnl_subsys) {
25162 +               ret = -ENOMEM;
25163 +               goto err_out; 
25164 +       }
25165 +
25166 +       ctnl_subsys->name = "conntrack";
25167 +       ctnl_subsys->subsys_id = NFNL_SUBSYS_CTNETLINK;
25168 +       ctnl_subsys->cb_count = CTNL_MSG_COUNT;
25169 +       ctnl_subsys->attr_count = CTA_MAX;
25170 +       ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].call = ctnetlink_new_conntrack;
25171 +       ctnl_subsys->cb[CTNL_MSG_NEWCONNTRACK].cap_required = CAP_NET_ADMIN;
25172 +       ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].call = ctnetlink_del_conntrack;
25173 +       ctnl_subsys->cb[CTNL_MSG_DELCONNTRACK].cap_required = CAP_NET_ADMIN;
25174 +       ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].call = ctnetlink_get_conntrack;
25175 +       ctnl_subsys->cb[CTNL_MSG_GETCONNTRACK].cap_required = 0;
25176 +       ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].call = ctnetlink_new_expect;
25177 +       ctnl_subsys->cb[CTNL_MSG_NEWEXPECT].cap_required = CAP_NET_ADMIN;
25178 +       ctnl_subsys->cb[CTNL_MSG_DELEXPECT].call = ctnetlink_del_expect;
25179 +       ctnl_subsys->cb[CTNL_MSG_DELEXPECT].cap_required = CAP_NET_ADMIN;
25180 +       ctnl_subsys->cb[CTNL_MSG_GETEXPECT].call = ctnetlink_get_expect;
25181 +       ctnl_subsys->cb[CTNL_MSG_GETEXPECT].cap_required = 0;
25182 +       // FIXME: CONFIRM
25183 +
25184 +       printk("ctnetlink: registering with nfnetlink v%s.\n", ctversion);
25185 +       if (nfnetlink_subsys_register(ctnl_subsys) < 0) {
25186 +               printk("ctnetlink_init: cannot register with nfnetlink.\n");
25187 +               ret = -1;
25188 +               goto err_free_subsys;
25189 +       }
25190 +
25191 +
25192 +#if 0
25193 +       if (ip_conntrack_notify_register(&ctnl_notify) < 0) {
25194 +               printk("ctnetlink_init: cannot register notifier.\n");
25195 +               ret = -1;
25196 +               goto err_unreg_subsys;
25197 +       }
25198 +
25199 +       if (ip_conntrack_notify_register(&ctnl_exp_notify) < 0) {
25200 +               printk("ctnetlink_init: cannot register exp notifier\n");
25201 +               ret = -1;
25202 +               goto err_unreg_notify;
25203 +       }
25204 +#endif
25205 +
25206 +
25207 +       return 0;
25208 +       
25209 +#if 0
25210 +err_unreg_notify:
25211 +       ip_conntrack_notify_unregister(&ctnl_notify);
25212 +#endif 
25213 +err_unreg_subsys:
25214 +       nfnetlink_subsys_unregister(ctnl_subsys);
25215 +err_free_subsys:
25216 +       kfree(ctnl_subsys);
25217 +err_out:
25218 +       return ret;
25219 +}
25220 +
25221 +module_init(ctnetlink_init);
25222 +module_exit(ctnetlink_exit);
25223 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/ip6_output.c linux-2.4.20/net/ipv6/ip6_output.c
25224 --- linux-2.4.20.org/net/ipv6/ip6_output.c      Thu Nov 28 23:53:15 2002
25225 +++ linux-2.4.20/net/ipv6/ip6_output.c  Wed Sep 24 09:16:14 2003
25226 @@ -132,7 +132,7 @@
25227  
25228  
25229  #ifdef CONFIG_NETFILTER
25230 -static int route6_me_harder(struct sk_buff *skb)
25231 +int ip6_route_me_harder(struct sk_buff *skb)
25232  {
25233         struct ipv6hdr *iph = skb->nh.ipv6h;
25234         struct dst_entry *dst;
25235 @@ -150,7 +150,7 @@
25236  
25237         if (dst->error) {
25238                 if (net_ratelimit())
25239 -                       printk(KERN_DEBUG "route6_me_harder: No more route.\n");
25240 +                       printk(KERN_DEBUG "ip6_route_me_harder: No more route.\n");
25241                 return -EINVAL;
25242         }
25243  
25244 @@ -166,7 +166,7 @@
25245  {
25246  #ifdef CONFIG_NETFILTER
25247         if (skb->nfcache & NFC_ALTERED){
25248 -               if (route6_me_harder(skb) != 0){
25249 +               if (ip6_route_me_harder(skb) != 0){
25250                         kfree_skb(skb);
25251                         return -EINVAL;
25252                 }
25253 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/Config.in linux-2.4.20/net/ipv6/netfilter/Config.in
25254 --- linux-2.4.20.org/net/ipv6/netfilter/Config.in       Thu Nov 28 23:53:15 2002
25255 +++ linux-2.4.20/net/ipv6/netfilter/Config.in   Wed Sep 24 09:18:15 2003
25256 @@ -15,15 +15,40 @@
25257  
25258  tristate 'IP6 tables support (required for filtering/masq/NAT)' CONFIG_IP6_NF_IPTABLES
25259  if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
25260 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25261 +    tristate 'raw table support (required for TRACE)' CONFIG_IP6_NF_RAW $CONFIG_IP6_NF_IPTABLES
25262 +  fi
25263  # The simple matches.
25264    dep_tristate '  limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
25265    dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
25266 +  dep_tristate '  Condition variable match support' CONFIG_IP6_NF_MATCH_CONDITION $CONFIG_IP6_NF_IPTABLES
25267 +  dep_tristate '  Random match support' CONFIG_IP6_NF_MATCH_RANDOM $CONFIG_IP6_NF_IPTABLES
25268 +  dep_tristate '  Nth match support' CONFIG_IP6_NF_MATCH_NTH $CONFIG_IP6_NF_IPTABLES
25269 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25270 +    dep_tristate '    Fuzzy match support' CONFIG_IP6_NF_MATCH_FUZZY $CONFIG_IP6_NF_FILTER
25271 +  fi
25272 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25273 +    dep_tristate '  Routing header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_RT $CONFIG_IP6_NF_IPTABLES
25274 +  fi
25275 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25276 +    dep_tristate '  Hop-by-Hop and Dst opts header match (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OPTS $CONFIG_IP6_NF_IPTABLES
25277 +  fi
25278 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25279 +    dep_tristate '  Fragmentation header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_FRAG $CONFIG_IP6_NF_IPTABLES
25280 +  fi
25281 +  dep_tristate '  HL match support' CONFIG_IP6_NF_MATCH_HL $CONFIG_IP6_NF_IPTABLES
25282    dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
25283    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25284      dep_tristate '  Owner match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OWNER $CONFIG_IP6_NF_IPTABLES
25285    fi
25286  #  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
25287    dep_tristate '  netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES
25288 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25289 +    dep_tristate '  IPv6 Extension Headers Match (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_IPV6HEADER $CONFIG_IP6_NF_IPTABLES
25290 +  fi
25291 +  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25292 +    dep_tristate '  AH/ESP match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_AHESP $CONFIG_IP6_NF_IPTABLES
25293 +  fi
25294    dep_tristate '  Packet Length match support' CONFIG_IP6_NF_MATCH_LENGTH $CONFIG_IP6_NF_IPTABLES
25295    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25296      dep_tristate '  EUI64 address check (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_EUI64 $CONFIG_IP6_NF_IPTABLES
25297 @@ -39,8 +64,20 @@
25298  #  fi
25299  
25300  # The targets
25301 +  if [ "$CONFIG_IP6_NF_RAW" != "n" ]; then
25302 +    dep_tristate '    TRACE target support' CONFIG_IP6_NF_TARGET_TRACE $CONFIG_IP6_NF_RAW
25303 +    if [ "$CONFIG_IP6_NF_TARGET_TRACE" != "n" ]; then
25304 +      define_bool CONFIG_IP6_NF_TARGET_TRACE_NEEDED y
25305 +    fi
25306 +  fi
25307    dep_tristate '  Packet filtering' CONFIG_IP6_NF_FILTER $CONFIG_IP6_NF_IPTABLES 
25308    if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
25309 +    dep_tristate '    REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
25310 +  fi
25311 +  if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
25312 +    dep_tristate '    HL target support' CONFIG_IP6_NF_TARGET_HL $CONFIG_IP6_NF_FILTER
25313 +  fi
25314 +  if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
25315      dep_tristate '    LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_FILTER
25316    fi
25317  
25318 @@ -55,6 +92,8 @@
25319    if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
25320  #    dep_tristate '    TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
25321      dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
25322 +    dep_mbool '    ROUTE target support' CONFIG_IP6_NF_TARGET_ROUTE $CONFIG_IP6_NF_MANGLE
25323 +    dep_tristate '    IMQ target support' CONFIG_IP6_NF_TARGET_IMQ $CONFIG_IP6_NF_MANGLE
25324    fi
25325    #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
25326  fi
25327 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/Makefile linux-2.4.20/net/ipv6/netfilter/Makefile
25328 --- linux-2.4.20.org/net/ipv6/netfilter/Makefile        Thu Nov 28 23:53:15 2002
25329 +++ linux-2.4.20/net/ipv6/netfilter/Makefile    Wed Sep 24 09:18:15 2003
25330 @@ -15,15 +15,33 @@
25331  obj-$(CONFIG_IP6_NF_IPTABLES) += ip6_tables.o
25332  obj-$(CONFIG_IP6_NF_MATCH_LIMIT) += ip6t_limit.o
25333  obj-$(CONFIG_IP6_NF_MATCH_MARK) += ip6t_mark.o
25334 +obj-$(CONFIG_IP6_NF_MATCH_CONDITION) += ip6t_condition.o
25335  obj-$(CONFIG_IP6_NF_MATCH_LENGTH) += ip6t_length.o
25336  obj-$(CONFIG_IP6_NF_MATCH_MAC) += ip6t_mac.o
25337 +obj-$(CONFIG_IP6_NF_MATCH_FUZZY) += ip6t_fuzzy.o
25338 +obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
25339 +obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o ip6t_dst.o
25340 +obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
25341 +obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
25342 +obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t_esp.o ip6t_ah.o
25343  obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
25344  obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
25345  obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
25346  obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
25347  obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
25348  obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
25349 +obj-$(CONFIG_IP6_NF_TARGET_ROUTE) += ip6t_ROUTE.o
25350 +obj-$(CONFIG_IP6_NF_TARGET_IMQ) += ip6t_IMQ.o
25351 +obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
25352  obj-$(CONFIG_IP6_NF_QUEUE) += ip6_queue.o
25353  obj-$(CONFIG_IP6_NF_TARGET_LOG) += ip6t_LOG.o
25354 +obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
25355 +obj-$(CONFIG_IP6_NF_TARGET_TRACE) += ip6t_TRACE.o
25356 +
25357 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
25358 +
25359 +obj-$(CONFIG_IP6_NF_MATCH_NTH) += ip6t_nth.o
25360 +obj-$(CONFIG_IP6_NF_TARGET_HL) += ip6t_HL.o
25361 +obj-$(CONFIG_IP6_NF_MATCH_HL) += ip6t_hl.o
25362  
25363  include $(TOPDIR)/Rules.make
25364 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6_queue.c linux-2.4.20/net/ipv6/netfilter/ip6_queue.c
25365 --- linux-2.4.20.org/net/ipv6/netfilter/ip6_queue.c     Thu Nov 28 23:53:15 2002
25366 +++ linux-2.4.20/net/ipv6/netfilter/ip6_queue.c Wed Sep 24 09:16:14 2003
25367 @@ -305,8 +305,9 @@
25368         write_lock_bh(&queue_lock);
25369         
25370         if (!peer_pid)
25371 -               goto err_out_unlock;
25372 +               goto err_out_free_nskb; 
25373  
25374 +       /* netlink_unicast will either free the nskb or attach it to a socket */ 
25375         status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
25376         if (status < 0)
25377                 goto err_out_unlock;
25378 @@ -318,6 +319,9 @@
25379         write_unlock_bh(&queue_lock);
25380         return status;
25381         
25382 +err_out_free_nskb:
25383 +       kfree_skb(nskb); 
25384 +       
25385  err_out_unlock:
25386         write_unlock_bh(&queue_lock);
25387  
25388 @@ -326,45 +330,6 @@
25389         return status;
25390  }
25391  
25392 -/*
25393 - * Taken from net/ipv6/ip6_output.c
25394 - *
25395 - * We should use the one there, but is defined static
25396 - * so we put this just here and let the things as
25397 - * they are now.
25398 - *
25399 - * If that one is modified, this one should be modified too.
25400 - */
25401 -static int
25402 -route6_me_harder(struct sk_buff *skb)
25403 -{
25404 -       struct ipv6hdr *iph = skb->nh.ipv6h;
25405 -       struct dst_entry *dst;
25406 -       struct flowi fl;
25407 -
25408 -       fl.proto = iph->nexthdr;
25409 -       fl.fl6_dst = &iph->daddr;
25410 -       fl.fl6_src = &iph->saddr;
25411 -       fl.oif = skb->sk ? skb->sk->bound_dev_if : 0;
25412 -       fl.fl6_flowlabel = 0;
25413 -       fl.uli_u.ports.dport = 0;
25414 -       fl.uli_u.ports.sport = 0;
25415 -
25416 -       dst = ip6_route_output(skb->sk, &fl);
25417 -
25418 -       if (dst->error) {
25419 -               if (net_ratelimit())
25420 -                       printk(KERN_DEBUG "route6_me_harder: No more route.\n");
25421 -               return -EINVAL;
25422 -       }
25423 -
25424 -       /* Drop old route. */
25425 -       dst_release(skb->dst);
25426 -
25427 -       skb->dst = dst;
25428 -       return 0;
25429 -}
25430 -
25431  static int
25432  ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
25433  {
25434 @@ -410,7 +375,7 @@
25435                 struct ipv6hdr *iph = e->skb->nh.ipv6h;
25436                 if (ipv6_addr_cmp(&iph->daddr, &e->rt_info.daddr) ||
25437                     ipv6_addr_cmp(&iph->saddr, &e->rt_info.saddr))
25438 -                       return route6_me_harder(e->skb);
25439 +                       return ip6_route_me_harder(e->skb);
25440         }
25441         return 0;
25442  }
25443 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6_tables.c linux-2.4.20/net/ipv6/netfilter/ip6_tables.c
25444 --- linux-2.4.20.org/net/ipv6/netfilter/ip6_tables.c    Thu Nov 28 23:53:15 2002
25445 +++ linux-2.4.20/net/ipv6/netfilter/ip6_tables.c        Wed Sep 24 09:18:14 2003
25446 @@ -25,10 +25,21 @@
25447  #include <linux/proc_fs.h>
25448  
25449  #include <linux/netfilter_ipv6/ip6_tables.h>
25450 +#include <linux/netfilter_ipv6/ip6_logging.h>
25451  
25452  #define IPV6_HDR_LEN   (sizeof(struct ipv6hdr))
25453  #define IPV6_OPTHDR_LEN        (sizeof(struct ipv6_opt_hdr))
25454  
25455 +#ifdef CONFIG_IP6_NF_TARGET_TRACE_NEEDED
25456 +static const char *hook6names[] = { 
25457 +       [NF_IP6_PRE_ROUTING] "PREROUTING",
25458 +       [NF_IP6_LOCAL_IN] "INPUT",
25459 +       [NF_IP6_FORWARD] "FORWARD",
25460 +       [NF_IP6_LOCAL_OUT] "OUTPUT",
25461 +       [NF_IP6_POST_ROUTING] "POSTROUTING",
25462 +};
25463 +#endif
25464 +
25465  /*#define DEBUG_IP_FIREWALL*/
25466  /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
25467  /*#define DEBUG_IP_FIREWALL_USER*/
25468 @@ -101,10 +112,8 @@
25469         unsigned int hook_entry[NF_IP6_NUMHOOKS];
25470         unsigned int underflow[NF_IP6_NUMHOOKS];
25471  
25472 -       char padding[SMP_ALIGN((NF_IP6_NUMHOOKS*2+2)*sizeof(unsigned int))];
25473 -
25474         /* ip6t_entry tables: one per CPU */
25475 -       char entries[0];
25476 +       char entries[0] ____cacheline_aligned;
25477  };
25478  
25479  static LIST_HEAD(ip6t_target);
25480 @@ -322,6 +331,39 @@
25481         return (struct ip6t_entry *)(base + offset);
25482  }
25483  
25484 +static inline int
25485 +get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
25486 +                     char **chainname, u_int16_t *rulenum)
25487 +{
25488 +       struct ip6t_entry_target *t;
25489 +
25490 +       (*rulenum)++;
25491 +
25492 +       if (s == e)
25493 +               return 1;
25494 +
25495 +       t = ip6t_get_target(s);
25496 +       if (strcmp(t->u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
25497 +               *chainname = t->data;
25498 +               (*rulenum) = 0;
25499 +       }
25500 +       
25501 +       return 0;
25502 +}
25503 +
25504 +/* All zeroes == unconditional rule. */
25505 +static inline int
25506 +unconditional(const struct ip6t_ip6 *ipv6)
25507 +{
25508 +       unsigned int i;
25509 +
25510 +       for (i = 0; i < sizeof(*ipv6); i++)
25511 +               if (((char *)ipv6)[i])
25512 +                       break;
25513 +
25514 +       return (i == sizeof(*ipv6));
25515 +}
25516 +
25517  /* Returns one of the generic firewall policies, like NF_ACCEPT. */
25518  unsigned int
25519  ip6t_do_table(struct sk_buff **pskb,
25520 @@ -398,6 +440,27 @@
25521  
25522                         t = ip6t_get_target(e);
25523                         IP_NF_ASSERT(t->u.kernel.target);
25524 +#ifdef CONFIG_IP6_NF_TARGET_TRACE_NEEDED
25525 +                       /* The packet traced and the rule isn't an unconditional return/END. */
25526 +                       if (((*pskb)->nfcache & NFC_TRACE)
25527 +                           && !(e->target_offset == sizeof(struct ip6t_entry)
25528 +                                && (strcmp(t->u.kernel.target->name,
25529 +                                      IP6T_STANDARD_TARGET) == 0)
25530 +                                && !t->u.kernel.target->target
25531 +                                && ((struct ip6t_standard_target *)t)->verdict < 0
25532 +                                && unconditional(&e->ipv6))) {
25533 +                               char *chainname = (char *) hook6names[hook];
25534 +                               u_int16_t rulenum = 0;
25535 +                               
25536 +                               IP6T_ENTRY_ITERATE(get_entry(table_base, table->private->hook_entry[hook]),
25537 +                                                  table->private->size,
25538 +                                                  get_chainname_rulenum,
25539 +                                                  e, &chainname, &rulenum);
25540 +                                                 
25541 +                               nf_log_ip6_packet(pskb, hook, in, out, "TRACE: %s/%s/%u ",
25542 +                                                 table->name, chainname, rulenum);
25543 +                       }
25544 +#endif
25545                         /* Standard target? */
25546                         if (!t->u.kernel.target->target) {
25547                                 int v;
25548 @@ -554,19 +617,6 @@
25549         return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
25550  }
25551  
25552 -/* All zeroes == unconditional rule. */
25553 -static inline int
25554 -unconditional(const struct ip6t_ip6 *ipv6)
25555 -{
25556 -       unsigned int i;
25557 -
25558 -       for (i = 0; i < sizeof(*ipv6); i++)
25559 -               if (((char *)ipv6)[i])
25560 -                       break;
25561 -
25562 -       return (i == sizeof(*ipv6));
25563 -}
25564 -
25565  /* Figures out from what hook each rule can be called: returns 0 if
25566     there are loops.  Puts hook bitmask in comefrom. */
25567  static int
25568 @@ -1450,7 +1500,7 @@
25569         int ret;
25570         struct ip6t_table_info *newinfo;
25571         static struct ip6t_table_info bootstrap
25572 -               = { 0, 0, 0, { 0 }, { 0 }, { }, { } };
25573 +               = { 0, 0, 0, { 0 }, { 0 }, { } };
25574  
25575         MOD_INC_USE_COUNT;
25576         newinfo = vmalloc(sizeof(struct ip6t_table_info)
25577 @@ -1767,14 +1817,15 @@
25578  = { { NULL, NULL }, "icmp6", &icmp6_match, &icmp6_checkentry, NULL };
25579  
25580  #ifdef CONFIG_PROC_FS
25581 -static inline int print_name(const struct ip6t_table *t,
25582 +static inline int print_name(const char *i,
25583                              off_t start_offset, char *buffer, int length,
25584                              off_t *pos, unsigned int *count)
25585  {
25586         if ((*count)++ >= start_offset) {
25587                 unsigned int namelen;
25588  
25589 -               namelen = sprintf(buffer + *pos, "%s\n", t->name);
25590 +               namelen = sprintf(buffer + *pos, "%s\n",
25591 +                                 i + sizeof(struct list_head));
25592                 if (*pos + namelen > length) {
25593                         /* Stop iterating */
25594                         return 1;
25595 @@ -1792,7 +1843,7 @@
25596         if (down_interruptible(&ip6t_mutex) != 0)
25597                 return 0;
25598  
25599 -       LIST_FIND(&ip6t_tables, print_name, struct ip6t_table *,
25600 +       LIST_FIND(&ip6t_tables, print_name, char *,
25601                   offset, buffer, length, &pos, &count);
25602  
25603         up(&ip6t_mutex);
25604 @@ -1801,6 +1852,46 @@
25605         *start=(char *)((unsigned long)count-offset);
25606         return pos;
25607  }
25608 +
25609 +static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
25610 +{
25611 +       off_t pos = 0;
25612 +       unsigned int count = 0;
25613 +
25614 +       if (down_interruptible(&ip6t_mutex) != 0)
25615 +               return 0;
25616 +
25617 +       LIST_FIND(&ip6t_target, print_name, char *,
25618 +                 offset, buffer, length, &pos, &count);
25619 +
25620 +       up(&ip6t_mutex);
25621 +
25622 +       *start = (char *)((unsigned long)count - offset);
25623 +       return pos;
25624 +}
25625 +
25626 +static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
25627 +{
25628 +       off_t pos = 0;
25629 +       unsigned int count = 0;
25630 +
25631 +       if (down_interruptible(&ip6t_mutex) != 0)
25632 +               return 0;
25633 +
25634 +       LIST_FIND(&ip6t_match, print_name, char *,
25635 +                 offset, buffer, length, &pos, &count);
25636 +
25637 +       up(&ip6t_mutex);
25638 +
25639 +       *start = (char *)((unsigned long)count - offset);
25640 +       return pos;
25641 +}
25642 +
25643 +static struct { char *name; get_info_t *get_info; } ip6t_proc_entry[] =
25644 +{ { "ip6_tables_names", ip6t_get_tables },
25645 +  { "ip6_tables_targets", ip6t_get_targets },
25646 +  { "ip6_tables_matches", ip6t_get_matches },
25647 +  { NULL, NULL} };
25648  #endif /*CONFIG_PROC_FS*/
25649  
25650  static int __init init(void)
25651 @@ -1826,13 +1917,19 @@
25652  #ifdef CONFIG_PROC_FS
25653         {
25654                 struct proc_dir_entry *proc;
25655 -               proc = proc_net_create("ip6_tables_names", 0,
25656 -                                       ip6t_get_tables);
25657 -               if (!proc) {
25658 -                       nf_unregister_sockopt(&ip6t_sockopts);
25659 -                       return -ENOMEM;
25660 +               int i;
25661 +
25662 +               for (i = 0; ip6t_proc_entry[i].name; i++) {
25663 +                       proc = proc_net_create(ip6t_proc_entry[i].name, 0,
25664 +                                              ip6t_proc_entry[i].get_info);
25665 +                       if (!proc) {
25666 +                               while (--i >= 0)
25667 +                                      proc_net_remove(ip6t_proc_entry[i].name);
25668 +                               nf_unregister_sockopt(&ip6t_sockopts);
25669 +                               return -ENOMEM;
25670 +                       }
25671 +                       proc->owner = THIS_MODULE;
25672                 }
25673 -               proc->owner = THIS_MODULE;
25674         }
25675  #endif
25676  
25677 @@ -1844,7 +1941,11 @@
25678  {
25679         nf_unregister_sockopt(&ip6t_sockopts);
25680  #ifdef CONFIG_PROC_FS
25681 -       proc_net_remove("ip6_tables_names");
25682 +       {
25683 +               int i;
25684 +               for (i = 0; ip6t_proc_entry[i].name; i++)
25685 +                       proc_net_remove(ip6t_proc_entry[i].name);
25686 +       }
25687  #endif
25688  }
25689  
25690 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_HL.c linux-2.4.20/net/ipv6/netfilter/ip6t_HL.c
25691 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_HL.c       Thu Jan  1 00:00:00 1970
25692 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_HL.c   Wed Sep 24 09:16:28 2003
25693 @@ -0,0 +1,105 @@
25694 +/* 
25695 + * Hop Limit modification target for ip6tables
25696 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
25697 + * Based on HW's TTL module
25698 + *
25699 + * This software is distributed under the terms of GNU GPL
25700 + */
25701 +
25702 +#include <linux/module.h>
25703 +#include <linux/skbuff.h>
25704 +#include <linux/ip.h>
25705 +
25706 +#include <linux/netfilter_ipv6/ip6_tables.h>
25707 +#include <linux/netfilter_ipv6/ip6t_HL.h>
25708 +
25709 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
25710 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
25711 +MODULE_LICENSE("GPL");
25712 +
25713 +static unsigned int ip6t_hl_target(struct sk_buff **pskb, unsigned int hooknum,
25714 +               const struct net_device *in, const struct net_device *out,
25715 +               const void *targinfo, void *userinfo)
25716 +{
25717 +       struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
25718 +       const struct ip6t_HL_info *info = targinfo;
25719 +       u_int16_t diffs[2];
25720 +       int new_hl;
25721 +                        
25722 +       switch (info->mode) {
25723 +               case IP6T_HL_SET:
25724 +                       new_hl = info->hop_limit;
25725 +                       break;
25726 +               case IP6T_HL_INC:
25727 +                       new_hl = ip6h->hop_limit + info->hop_limit;
25728 +                       if (new_hl > 255)
25729 +                               new_hl = 255;
25730 +                       break;
25731 +               case IP6T_HL_DEC:
25732 +                       new_hl = ip6h->hop_limit + info->hop_limit;
25733 +                       if (new_hl < 0)
25734 +                               new_hl = 0;
25735 +                       break;
25736 +               default:
25737 +                       new_hl = ip6h->hop_limit;
25738 +                       break;
25739 +       }
25740 +
25741 +       if (new_hl != ip6h->hop_limit) {
25742 +               diffs[0] = htons(((unsigned)ip6h->hop_limit) << 8) ^ 0xFFFF;
25743 +               ip6h->hop_limit = new_hl;
25744 +               diffs[1] = htons(((unsigned)ip6h->hop_limit) << 8);
25745 +       }
25746 +
25747 +       return IP6T_CONTINUE;
25748 +}
25749 +
25750 +static int ip6t_hl_checkentry(const char *tablename,
25751 +               const struct ip6t_entry *e,
25752 +               void *targinfo,
25753 +               unsigned int targinfosize,
25754 +               unsigned int hook_mask)
25755 +{
25756 +       struct ip6t_HL_info *info = targinfo;
25757 +
25758 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
25759 +               printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
25760 +                               targinfosize,
25761 +                               IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
25762 +               return 0;       
25763 +       }       
25764 +
25765 +       if (strcmp(tablename, "mangle")) {
25766 +               printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
25767 +               return 0;
25768 +       }
25769 +
25770 +       if (info->mode > IP6T_HL_MAXMODE) {
25771 +               printk(KERN_WARNING "HL: invalid or unknown Mode %u\n", 
25772 +                       info->mode);
25773 +               return 0;
25774 +       }
25775 +
25776 +       if ((info->mode != IP6T_HL_SET) && (info->hop_limit == 0)) {
25777 +               printk(KERN_WARNING "HL: increment/decrement doesn't make sense with value 0\n");
25778 +               return 0;
25779 +       }
25780 +       
25781 +       return 1;
25782 +}
25783 +
25784 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL", 
25785 +       ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
25786 +
25787 +static int __init init(void)
25788 +{
25789 +       return ip6t_register_target(&ip6t_HL);
25790 +}
25791 +
25792 +static void __exit fini(void)
25793 +{
25794 +       ip6t_unregister_target(&ip6t_HL);
25795 +}
25796 +
25797 +module_init(init);
25798 +module_exit(fini);
25799 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_IMQ.c linux-2.4.20/net/ipv6/netfilter/ip6t_IMQ.c
25800 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_IMQ.c      Thu Jan  1 00:00:00 1970
25801 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_IMQ.c  Wed Sep 24 09:17:21 2003
25802 @@ -0,0 +1,78 @@
25803 +/* This target marks packets to be enqueued to an imq device */
25804 +#include <linux/module.h>
25805 +#include <linux/skbuff.h>
25806 +#include <linux/netfilter_ipv6/ip6_tables.h>
25807 +#include <linux/netfilter_ipv6/ip6t_IMQ.h>
25808 +#include <linux/imq.h>
25809 +
25810 +static unsigned int imq_target(struct sk_buff **pskb,
25811 +                              unsigned int hooknum,
25812 +                              const struct net_device *in,
25813 +                              const struct net_device *out,
25814 +                              const void *targinfo,
25815 +                              void *userinfo)
25816 +{
25817 +       struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
25818 +
25819 +       (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
25820 +       (*pskb)->nfcache |= NFC_ALTERED;
25821 +
25822 +       return IP6T_CONTINUE;
25823 +}
25824 +
25825 +static int imq_checkentry(const char *tablename,
25826 +                         const struct ip6t_entry *e,
25827 +                         void *targinfo,
25828 +                         unsigned int targinfosize,
25829 +                         unsigned int hook_mask)
25830 +{
25831 +       struct ip6t_imq_info *mr;
25832 +
25833 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
25834 +               printk(KERN_WARNING "IMQ: invalid targinfosize\n");
25835 +               return 0;
25836 +       }
25837 +       mr = (struct ip6t_imq_info*)targinfo;
25838 +
25839 +       if (strcmp(tablename, "mangle") != 0) {
25840 +               printk(KERN_WARNING
25841 +                      "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
25842 +                      tablename);
25843 +               return 0;
25844 +       }
25845 +       
25846 +       if (mr->todev > IMQ_MAX_DEVS) {
25847 +               printk(KERN_WARNING
25848 +                      "IMQ: invalid device specified, highest is %u\n",
25849 +                      IMQ_MAX_DEVS);
25850 +               return 0;
25851 +       }
25852 +       
25853 +       return 1;
25854 +}
25855 +
25856 +static struct ip6t_target ip6t_imq_reg = {
25857 +       { NULL, NULL},
25858 +       "IMQ",
25859 +       imq_target,
25860 +       imq_checkentry,
25861 +       NULL,
25862 +       THIS_MODULE
25863 +};
25864 +
25865 +static int __init init(void)
25866 +{
25867 +       if (ip6t_register_target(&ip6t_imq_reg))
25868 +               return -EINVAL;
25869 +
25870 +       return 0;
25871 +}
25872 +
25873 +static void __exit fini(void)
25874 +{
25875 +       ip6t_unregister_target(&ip6t_imq_reg);
25876 +}
25877 +
25878 +module_init(init);
25879 +module_exit(fini);
25880 +MODULE_LICENSE("GPL");
25881 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_LOG.c linux-2.4.20/net/ipv6/netfilter/ip6t_LOG.c
25882 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_LOG.c      Thu Nov 28 23:53:15 2002
25883 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_LOG.c  Wed Sep 24 09:16:23 2003
25884 @@ -10,6 +10,7 @@
25885  #include <net/tcp.h>
25886  #include <net/ipv6.h>
25887  #include <linux/netfilter_ipv6/ip6_tables.h>
25888 +#include <linux/netfilter_ipv6/ip6_logging.h>
25889  
25890  MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
25891  MODULE_DESCRIPTION("IP6 tables LOG target module");
25892 @@ -89,7 +90,7 @@
25893         printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
25894  
25895         /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
25896 -       printk("LEN=%u TC=%u HOPLIMIT=%u FLOWLBL=%u ",
25897 +       printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
25898                ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr),
25899                (ntohl(*(u_int32_t *)ipv6h) & 0x0ff00000) >> 20,
25900                ipv6h->hop_limit,
25901 @@ -266,23 +267,21 @@
25902         }
25903  }
25904  
25905 -static unsigned int
25906 -ip6t_log_target(struct sk_buff **pskb,
25907 +static void
25908 +ip6t_log_packet(struct sk_buff **pskb,
25909                 unsigned int hooknum,
25910                 const struct net_device *in,
25911                 const struct net_device *out,
25912 -               const void *targinfo,
25913 -               void *userinfo)
25914 +               const struct ip6t_log_info *loginfo,
25915 +               const char *level_string,
25916 +               const char *prefix)
25917  {
25918         struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
25919 -       const struct ip6t_log_info *loginfo = targinfo;
25920 -       char level_string[4] = "< >";
25921  
25922 -       level_string[1] = '0' + (loginfo->level % 8);
25923         spin_lock_bh(&log_lock);
25924         printk(level_string);
25925         printk("%sIN=%s OUT=%s ",
25926 -               loginfo->prefix,
25927 +               prefix == NULL ? loginfo->prefix : prefix,
25928                 in ? in->name : "",
25929                 out ? out->name : "");
25930         if (in && !out) {
25931 @@ -329,10 +328,59 @@
25932         dump_packet(loginfo, ipv6h, 1);
25933         printk("\n");
25934         spin_unlock_bh(&log_lock);
25935 +}
25936 +
25937 +static unsigned int
25938 +ip6t_log_target(struct sk_buff **pskb,
25939 +               unsigned int hooknum,
25940 +               const struct net_device *in,
25941 +               const struct net_device *out,
25942 +               const void *targinfo,
25943 +               void *userinfo)
25944 +{
25945 +       const struct ip6t_log_info *loginfo = targinfo;
25946 +       char level_string[4] = "< >";
25947 +
25948 +       level_string[1] = '0' + (loginfo->level % 8);
25949 +       ip6t_log_packet(pskb, hooknum, in, out, loginfo, level_string, NULL);
25950  
25951         return IP6T_CONTINUE;
25952  }
25953  
25954 +static void
25955 +ip6_log_packet_fn(struct sk_buff **pskb,
25956 +                 unsigned int hooknum,
25957 +                 const struct net_device *in,
25958 +                 const struct net_device *out,
25959 +                 const char *prefix)
25960 +{
25961 +       struct ip6t_log_info loginfo = { 
25962 +               .level = 0,
25963 +               .logflags = IP6T_LOG_MASK,
25964 +               .prefix = ""
25965 +       };
25966 +
25967 +       ip6t_log_packet(pskb, hooknum, in, out, &loginfo, KERN_WARNING, prefix);
25968 +}
25969 +
25970 +static void
25971 +ip6_log_fn(char *pfh, size_t len,
25972 +          const char *prefix)
25973 +{
25974 +       struct ipv6hdr *ipv6h = (struct ipv6hdr *)pfh;
25975 +       struct ip6t_log_info loginfo = { 
25976 +               .level = 0,
25977 +               .logflags = IP6T_LOG_MASK,
25978 +               .prefix = ""
25979 +       };
25980 +
25981 +       spin_lock_bh(&log_lock);
25982 +       printk(KERN_WARNING "%s", prefix);
25983 +       dump_packet(&loginfo, ipv6h, 1);
25984 +       printk("\n");
25985 +       spin_unlock_bh(&log_lock);
25986 +}
25987 +
25988  static int ip6t_log_checkentry(const char *tablename,
25989                                const struct ip6t_entry *e,
25990                                void *targinfo,
25991 @@ -364,17 +412,21 @@
25992  static struct ip6t_target ip6t_log_reg
25993  = { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, 
25994      THIS_MODULE };
25995 +static struct nf_logging_t ip6_logging_fn
25996 += { ip6_log_packet_fn, ip6_log_fn };
25997  
25998  static int __init init(void)
25999  {
26000         if (ip6t_register_target(&ip6t_log_reg))
26001                 return -EINVAL;
26002 +       nf_ip6_log_register(&ip6_logging_fn);
26003  
26004         return 0;
26005  }
26006  
26007  static void __exit fini(void)
26008  {
26009 +       nf_ip6_log_unregister(&ip6_logging_fn);
26010         ip6t_unregister_target(&ip6t_log_reg);
26011  }
26012  
26013 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_REJECT.c linux-2.4.20/net/ipv6/netfilter/ip6t_REJECT.c
26014 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_REJECT.c   Thu Jan  1 00:00:00 1970
26015 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_REJECT.c       Wed Sep 24 09:16:36 2003
26016 @@ -0,0 +1,274 @@
26017 +/*
26018 + * This is a module which is used for rejecting packets.
26019 + *     Added support for customized reject packets (Jozsef Kadlecsik).
26020 + * Sun 12 Nov 2000
26021 + *     Port to IPv6 / ip6tables (Harald Welte <laforge@gnumonks.org>)
26022 + */
26023 +#include <linux/config.h>
26024 +#include <linux/module.h>
26025 +#include <linux/skbuff.h>
26026 +#include <linux/icmpv6.h>
26027 +#include <net/tcp.h>
26028 +#include <linux/netfilter_ipv6/ip6_tables.h>
26029 +#include <linux/netfilter_ipv6/ip6t_REJECT.h>
26030 +
26031 +#if 1
26032 +#define DEBUGP printk
26033 +#else
26034 +#define DEBUGP(format, args...)
26035 +#endif
26036 +
26037 +#if 0
26038 +/* Send RST reply */
26039 +static void send_reset(struct sk_buff *oldskb)
26040 +{
26041 +       struct sk_buff *nskb;
26042 +       struct tcphdr *otcph, *tcph;
26043 +       struct rtable *rt;
26044 +       unsigned int otcplen;
26045 +       int needs_ack;
26046 +
26047 +       /* IP header checks: fragment, too short. */
26048 +       if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
26049 +           || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr))
26050 +               return;
26051 +
26052 +       otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
26053 +       otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
26054 +
26055 +       /* No RST for RST. */
26056 +       if (otcph->rst)
26057 +               return;
26058 +
26059 +       /* Check checksum. */
26060 +       if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr,
26061 +                        oldskb->nh.iph->daddr,
26062 +                        csum_partial((char *)otcph, otcplen, 0)) != 0)
26063 +               return;
26064 +
26065 +       /* Copy skb (even if skb is about to be dropped, we can't just
26066 +           clone it because there may be other things, such as tcpdump,
26067 +           interested in it) */
26068 +       nskb = skb_copy(oldskb, GFP_ATOMIC);
26069 +       if (!nskb)
26070 +               return;
26071 +
26072 +       /* This packet will not be the same as the other: clear nf fields */
26073 +       nf_conntrack_put(nskb->nfct);
26074 +       nskb->nfct = NULL;
26075 +       nskb->nfcache = 0;
26076 +#ifdef CONFIG_NETFILTER_DEBUG
26077 +       nskb->nf_debug = 0;
26078 +#endif
26079 +
26080 +       tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
26081 +
26082 +       nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
26083 +       tcph->source = xchg(&tcph->dest, tcph->source);
26084 +
26085 +       /* Truncate to length (no data) */
26086 +       tcph->doff = sizeof(struct tcphdr)/4;
26087 +       skb_trim(nskb, nskb->nh.iph->ihl*4 + sizeof(struct tcphdr));
26088 +       nskb->nh.iph->tot_len = htons(nskb->len);
26089 +
26090 +       if (tcph->ack) {
26091 +               needs_ack = 0;
26092 +               tcph->seq = otcph->ack_seq;
26093 +               tcph->ack_seq = 0;
26094 +       } else {
26095 +               needs_ack = 1;
26096 +               tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
26097 +                                     + otcplen - (otcph->doff<<2));
26098 +               tcph->seq = 0;
26099 +       }
26100 +
26101 +       /* Reset flags */
26102 +       ((u_int8_t *)tcph)[13] = 0;
26103 +       tcph->rst = 1;
26104 +       tcph->ack = needs_ack;
26105 +
26106 +       tcph->window = 0;
26107 +       tcph->urg_ptr = 0;
26108 +
26109 +       /* Adjust TCP checksum */
26110 +       tcph->check = 0;
26111 +       tcph->check = tcp_v4_check(tcph, sizeof(struct tcphdr),
26112 +                                  nskb->nh.iph->saddr,
26113 +                                  nskb->nh.iph->daddr,
26114 +                                  csum_partial((char *)tcph,
26115 +                                               sizeof(struct tcphdr), 0));
26116 +
26117 +       /* Adjust IP TTL, DF */
26118 +       nskb->nh.iph->ttl = MAXTTL;
26119 +       /* Set DF, id = 0 */
26120 +       nskb->nh.iph->frag_off = htons(IP_DF);
26121 +       nskb->nh.iph->id = 0;
26122 +
26123 +       /* Adjust IP checksum */
26124 +       nskb->nh.iph->check = 0;
26125 +       nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
26126 +                                          nskb->nh.iph->ihl);
26127 +
26128 +       /* Routing */
26129 +       if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
26130 +                           RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
26131 +                           0) != 0)
26132 +               goto free_nskb;
26133 +
26134 +       dst_release(nskb->dst);
26135 +       nskb->dst = &rt->u.dst;
26136 +
26137 +       /* "Never happens" */
26138 +       if (nskb->len > nskb->dst->pmtu)
26139 +               goto free_nskb;
26140 +
26141 +       NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
26142 +               ip_finish_output);
26143 +       return;
26144 +
26145 + free_nskb:
26146 +       kfree_skb(nskb);
26147 +}
26148 +#endif
26149 +
26150 +static unsigned int reject6_target(struct sk_buff **pskb,
26151 +                          unsigned int hooknum,
26152 +                          const struct net_device *in,
26153 +                          const struct net_device *out,
26154 +                          const void *targinfo,
26155 +                          void *userinfo)
26156 +{
26157 +       const struct ip6t_reject_info *reject = targinfo;
26158 +
26159 +       /* WARNING: This code causes reentry within ip6tables.
26160 +          This means that the ip6tables jump stack is now crap.  We
26161 +          must return an absolute verdict. --RR */
26162 +       DEBUGP("REJECTv6: calling icmpv6_send\n");
26163 +       switch (reject->with) {
26164 +       case IP6T_ICMP6_NO_ROUTE:
26165 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOROUTE, 0, out);
26166 +               break;
26167 +       case IP6T_ICMP6_ADM_PROHIBITED:
26168 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
26169 +               break;
26170 +       case IP6T_ICMP6_NOT_NEIGHBOUR:
26171 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
26172 +               break;
26173 +       case IP6T_ICMP6_ADDR_UNREACH:
26174 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
26175 +               break;
26176 +       case IP6T_ICMP6_PORT_UNREACH:
26177 +               icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
26178 +               break;
26179 +#if 0
26180 +       case IPT_ICMP_ECHOREPLY: {
26181 +               struct icmp6hdr *icmph  = (struct icmphdr *)
26182 +                       ((u_int32_t *)(*pskb)->nh.iph + (*pskb)->nh.iph->ihl);
26183 +               unsigned int datalen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
26184 +
26185 +               /* Not non-head frags, or truncated */
26186 +               if (((ntohs((*pskb)->nh.iph->frag_off) & IP_OFFSET) == 0)
26187 +                   && datalen >= 4) {
26188 +                       /* Usually I don't like cut & pasting code,
26189 +                           but dammit, my party is starting in 45
26190 +                           mins! --RR */
26191 +                       struct icmp_bxm icmp_param;
26192 +
26193 +                       icmp_param.icmph=*icmph;
26194 +                       icmp_param.icmph.type=ICMP_ECHOREPLY;
26195 +                       icmp_param.data_ptr=(icmph+1);
26196 +                       icmp_param.data_len=datalen;
26197 +                       icmp_reply(&icmp_param, *pskb);
26198 +               }
26199 +       }
26200 +       break;
26201 +       case IPT_TCP_RESET:
26202 +               send_reset(*pskb);
26203 +               break;
26204 +#endif
26205 +       default:
26206 +               printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
26207 +               break;
26208 +       }
26209 +
26210 +       return NF_DROP;
26211 +}
26212 +
26213 +static inline int find_ping_match(const struct ip6t_entry_match *m)
26214 +{
26215 +       const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
26216 +
26217 +       if (strcmp(m->u.kernel.match->name, "icmp6") == 0
26218 +           && icmpinfo->type == ICMPV6_ECHO_REQUEST
26219 +           && !(icmpinfo->invflags & IP6T_ICMP_INV))
26220 +               return 1;
26221 +
26222 +       return 0;
26223 +}
26224 +
26225 +static int check(const char *tablename,
26226 +                const struct ip6t_entry *e,
26227 +                void *targinfo,
26228 +                unsigned int targinfosize,
26229 +                unsigned int hook_mask)
26230 +{
26231 +       const struct ip6t_reject_info *rejinfo = targinfo;
26232 +
26233 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
26234 +               DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
26235 +               return 0;
26236 +       }
26237 +
26238 +       /* Only allow these for packet filtering. */
26239 +       if (strcmp(tablename, "filter") != 0) {
26240 +               DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
26241 +               return 0;
26242 +       }
26243 +       if ((hook_mask & ~((1 << NF_IP6_LOCAL_IN)
26244 +                          | (1 << NF_IP6_FORWARD)
26245 +                          | (1 << NF_IP6_LOCAL_OUT))) != 0) {
26246 +               DEBUGP("REJECTv6: bad hook mask %X\n", hook_mask);
26247 +               return 0;
26248 +       }
26249 +
26250 +       if (rejinfo->with == IP6T_ICMP6_ECHOREPLY) {
26251 +               /* Must specify that it's an ICMP ping packet. */
26252 +               if (e->ipv6.proto != IPPROTO_ICMPV6
26253 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
26254 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-icmp\n");
26255 +                       return 0;
26256 +               }
26257 +               /* Must contain ICMP match. */
26258 +               if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
26259 +                       DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
26260 +                       return 0;
26261 +               }
26262 +       } else if (rejinfo->with == IP6T_TCP_RESET) {
26263 +               /* Must specify that it's a TCP packet */
26264 +               if (e->ipv6.proto != IPPROTO_TCP
26265 +                   || (e->ipv6.invflags & IP6T_INV_PROTO)) {
26266 +                       DEBUGP("REJECTv6: TCP_RESET illegal for non-tcp\n");
26267 +                       return 0;
26268 +               }
26269 +       }
26270 +
26271 +       return 1;
26272 +}
26273 +
26274 +static struct ip6t_target ip6t_reject_reg
26275 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
26276 +
26277 +static int __init init(void)
26278 +{
26279 +       if (ip6t_register_target(&ip6t_reject_reg))
26280 +               return -EINVAL;
26281 +       return 0;
26282 +}
26283 +
26284 +static void __exit fini(void)
26285 +{
26286 +       ip6t_unregister_target(&ip6t_reject_reg);
26287 +}
26288 +
26289 +module_init(init);
26290 +module_exit(fini);
26291 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_ROUTE.c linux-2.4.20/net/ipv6/netfilter/ip6t_ROUTE.c
26292 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_ROUTE.c    Thu Jan  1 00:00:00 1970
26293 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_ROUTE.c        Wed Sep 24 09:17:27 2003
26294 @@ -0,0 +1,289 @@
26295 +/*
26296 + * This implements the ROUTE v6 target, which enables you to setup unusual
26297 + * routes not supported by the standard kernel routing table.
26298 + *
26299 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
26300 + *
26301 + * v 1.0 2003/08/05
26302 + *
26303 + * This software is distributed under GNU GPL v2, 1991
26304 + */
26305 +
26306 +#include <linux/module.h>
26307 +#include <linux/skbuff.h>
26308 +#include <linux/ipv6.h>
26309 +#include <linux/netfilter_ipv6/ip6_tables.h>
26310 +#include <linux/netfilter_ipv6/ip6t_ROUTE.h>
26311 +#include <linux/netdevice.h>
26312 +#include <net/ipv6.h>
26313 +#include <net/ndisc.h>
26314 +#include <net/ip6_route.h>
26315 +#include <linux/icmpv6.h>
26316 +
26317 +#if 1
26318 +#define DEBUGP printk
26319 +#else
26320 +#define DEBUGP(format, args...)
26321 +#endif
26322 +
26323 +#define NIP6(addr) \
26324 +       ntohs((addr).s6_addr16[0]), \
26325 +       ntohs((addr).s6_addr16[1]), \
26326 +       ntohs((addr).s6_addr16[2]), \
26327 +       ntohs((addr).s6_addr16[3]), \
26328 +       ntohs((addr).s6_addr16[4]), \
26329 +       ntohs((addr).s6_addr16[5]), \
26330 +       ntohs((addr).s6_addr16[6]), \
26331 +       ntohs((addr).s6_addr16[7])
26332 +
26333 +/* Route the packet according to the routing keys specified in
26334 + * route_info. Keys are :
26335 + *  - ifindex : 
26336 + *      0 if no oif preferred, 
26337 + *      otherwise set to the index of the desired oif
26338 + *  - route_info->gw :
26339 + *      0 if no gateway specified,
26340 + *      otherwise set to the next host to which the pkt must be routed
26341 + * If success, skb->dev is the output device to which the packet must 
26342 + * be sent and skb->dst is not NULL
26343 + *
26344 + * RETURN:  1 if the packet was succesfully routed to the 
26345 + *            destination desired
26346 + *          0 if the kernel routing table could not route the packet
26347 + *            according to the keys specified
26348 + */
26349 +static int 
26350 +route6(struct sk_buff *skb,
26351 +       unsigned int ifindex,
26352 +       const struct ip6t_route_target_info *route_info)
26353 +{
26354 +       struct rt6_info *rt = NULL;
26355 +       struct ipv6hdr *ipv6h = skb->nh.ipv6h;
26356 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
26357 +
26358 +       DEBUGP("ip6t_ROUTE: called with: ");
26359 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
26360 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(*gw));
26361 +       DEBUGP("OUT=%s\n", route_info->oif);
26362 +       
26363 +       if (ipv6_addr_any(gw))
26364 +               rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
26365 +       else
26366 +               rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
26367 +
26368 +       if (!rt)
26369 +               goto no_route;
26370 +
26371 +       DEBUGP("ip6t_ROUTE: routing gives: ");
26372 +       DEBUGP("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_dst.addr));
26373 +       DEBUGP("GATEWAY=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(rt->rt6i_gateway));
26374 +       DEBUGP("OUT=%s\n", rt->rt6i_dev->name);
26375 +
26376 +       if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
26377 +               goto wrong_route;
26378 +       
26379 +       if (!rt->rt6i_nexthop) {
26380 +               DEBUGP("ip6t_ROUTE: discovering neighbour\n");
26381 +               rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_dst.addr);
26382 +       }
26383 +
26384 +       /* Drop old route. */
26385 +       dst_release(skb->dst);
26386 +       skb->dst = &rt->u.dst;
26387 +       skb->dev = rt->rt6i_dev;
26388 +       return 1;
26389 +
26390 + wrong_route:
26391 +       dst_release(&rt->u.dst);
26392 + no_route:
26393 +       if (!net_ratelimit())
26394 +               return 0;
26395 +
26396 +       printk("ip6t_ROUTE: no explicit route found ");
26397 +       if (ifindex)
26398 +               printk("via interface %s ", route_info->oif);
26399 +       if (!ipv6_addr_any(gw))
26400 +               printk("via gateway %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", NIP6(*gw));
26401 +       printk("\n");
26402 +       return 0;
26403 +}
26404 +
26405 +
26406 +/* Stolen from ip6_output_finish
26407 + * PRE : skb->dev is set to the device we are leaving by
26408 + *       skb->dst is not NULL
26409 + * POST: the packet is sent with the link layer header pushed
26410 + *       the packet is destroyed
26411 + */
26412 +static void ip_direct_send(struct sk_buff *skb)
26413 +{
26414 +       struct dst_entry *dst = skb->dst;
26415 +       struct hh_cache *hh = dst->hh;
26416 +
26417 +       if (hh) {
26418 +               read_lock_bh(&hh->hh_lock);
26419 +               memcpy(skb->data - 16, hh->hh_data, 16);
26420 +               read_unlock_bh(&hh->hh_lock);
26421 +               skb_push(skb, hh->hh_len);
26422 +               hh->hh_output(skb);
26423 +       } else if (dst->neighbour)
26424 +               dst->neighbour->output(skb);
26425 +       else {
26426 +               if (net_ratelimit())
26427 +                       DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
26428 +               kfree_skb(skb);
26429 +       }
26430 +}
26431 +
26432 +
26433 +static unsigned int 
26434 +route6_oif(const struct ip6t_route_target_info *route_info,
26435 +          struct sk_buff *skb) 
26436 +{
26437 +       unsigned int ifindex = 0;
26438 +       struct net_device *dev_out = NULL;
26439 +
26440 +       /* The user set the interface name to use.
26441 +        * Getting the current interface index.
26442 +        */
26443 +       if ((dev_out = dev_get_by_name(route_info->oif))) {
26444 +               ifindex = dev_out->ifindex;
26445 +       } else {
26446 +               /* Unknown interface name : packet dropped */
26447 +               if (net_ratelimit()) 
26448 +                       DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
26449 +
26450 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
26451 +                       return IP6T_CONTINUE;
26452 +               else
26453 +                       return NF_DROP;
26454 +       }
26455 +
26456 +       /* Trying the standard way of routing packets */
26457 +       if (route6(skb, ifindex, route_info)) {
26458 +               dev_put(dev_out);
26459 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
26460 +                       return IP6T_CONTINUE;
26461 +               
26462 +               ip_direct_send(skb);
26463 +               return NF_STOLEN;
26464 +       } else 
26465 +               return NF_DROP;
26466 +}
26467 +
26468 +
26469 +static unsigned int 
26470 +route6_gw(const struct ip6t_route_target_info *route_info,
26471 +         struct sk_buff *skb) 
26472 +{
26473 +       if (route6(skb, 0, route_info)) {
26474 +               if (route_info->flags & IP6T_ROUTE_CONTINUE)
26475 +                       return IP6T_CONTINUE;
26476 +
26477 +               ip_direct_send(skb);
26478 +               return NF_STOLEN;
26479 +       } else
26480 +               return NF_DROP;
26481 +}
26482 +
26483 +
26484 +static unsigned int 
26485 +ip6t_route_target(struct sk_buff **pskb,
26486 +                 unsigned int hooknum,
26487 +                 const struct net_device *in,
26488 +                 const struct net_device *out,
26489 +                 const void *targinfo,
26490 +                 void *userinfo)
26491 +{
26492 +       const struct ip6t_route_target_info *route_info = targinfo;
26493 +       struct sk_buff *skb = *pskb;
26494 +       struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
26495 +
26496 +       if (route_info->flags & IP6T_ROUTE_CONTINUE)
26497 +               goto do_it;
26498 +
26499 +       /* If we are at PREROUTING or INPUT hook
26500 +        * the TTL isn't decreased by the IP stack
26501 +        */
26502 +       if (hooknum == NF_IP6_PRE_ROUTING ||
26503 +           hooknum == NF_IP6_LOCAL_IN) {
26504 +
26505 +               struct ipv6hdr *ipv6h = skb->nh.ipv6h;
26506 +
26507 +               if (ipv6h->hop_limit <= 1) {
26508 +                       /* Force OUTPUT device used as source address */
26509 +                       skb->dev = skb->dst->dev;
26510 +
26511 +                       icmpv6_send(skb, ICMPV6_TIME_EXCEED, 
26512 +                                   ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
26513 +
26514 +                       return NF_DROP;
26515 +               }
26516 +
26517 +               ipv6h->hop_limit--;
26518 +       }
26519 +
26520 +
26521 + do_it:
26522 +       if (route_info->oif[0]) 
26523 +               return route6_oif(route_info, *pskb);
26524 +       
26525 +       if (!ipv6_addr_any(gw))
26526 +               return route6_gw(route_info, *pskb);
26527 +
26528 +       if (net_ratelimit()) 
26529 +               DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
26530 +
26531 +       return IP6T_CONTINUE;
26532 +}
26533 +
26534 +
26535 +static int 
26536 +ip6t_route_checkentry(const char *tablename,
26537 +                     const struct ip6t_entry *e,
26538 +                     void *targinfo,
26539 +                     unsigned int targinfosize,
26540 +                     unsigned int hook_mask)
26541 +{
26542 +       if (strcmp(tablename, "mangle") != 0) {
26543 +               printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
26544 +               return 0;
26545 +       }
26546 +
26547 +       if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
26548 +               printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
26549 +                      targinfosize,
26550 +                      IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
26551 +               return 0;
26552 +       }
26553 +
26554 +       return 1;
26555 +}
26556 +
26557 +
26558 +static struct ip6t_target ip6t_route_reg = {
26559 +       .name       = "ROUTE",
26560 +       .target     = ip6t_route_target,
26561 +       .checkentry = ip6t_route_checkentry,
26562 +       .me         = THIS_MODULE
26563 +};
26564 +
26565 +
26566 +static int __init init(void)
26567 +{
26568 +       printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
26569 +       if (ip6t_register_target(&ip6t_route_reg))
26570 +               return -EINVAL;
26571 +
26572 +       return 0;
26573 +}
26574 +
26575 +
26576 +static void __exit fini(void)
26577 +{
26578 +       ip6t_unregister_target(&ip6t_route_reg);
26579 +}
26580 +
26581 +module_init(init);
26582 +module_exit(fini);
26583 +MODULE_LICENSE("GPL");
26584 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_TRACE.c linux-2.4.20/net/ipv6/netfilter/ip6t_TRACE.c
26585 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_TRACE.c    Thu Jan  1 00:00:00 1970
26586 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_TRACE.c        Wed Sep 24 09:18:14 2003
26587 @@ -0,0 +1,66 @@
26588 +/* This is a module which is used for setting
26589 + * the NFC_TRACE flag in the nfcache field of an skb. 
26590 + */
26591 +#include <linux/module.h>
26592 +#include <linux/skbuff.h>
26593 +
26594 +#include <linux/netfilter_ipv6/ip6_tables.h>
26595 +
26596 +MODULE_LICENSE("GPL");
26597 +
26598 +static unsigned int
26599 +target(struct sk_buff **pskb,
26600 +       unsigned int hooknum,
26601 +       const struct net_device *in,
26602 +       const struct net_device *out,
26603 +       const void *targinfo,
26604 +       void *userinfo)
26605 +{
26606 +       (*pskb)->nfcache |= NFC_TRACE;
26607 +       return IP6T_CONTINUE;
26608 +}
26609 +
26610 +static int 
26611 +checkentry(const char *tablename,
26612 +                  const struct ip6t_entry *e,
26613 +           void *targinfo,
26614 +           unsigned int targinfosize,
26615 +           unsigned int hook_mask)
26616 +{
26617 +       if (targinfosize != 0) {
26618 +               printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
26619 +                      targinfosize);
26620 +               return 0;
26621 +       }
26622 +
26623 +       if (strcmp(tablename, "raw") != 0) {
26624 +               printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
26625 +               return 0;
26626 +       }
26627 +
26628 +       return 1;
26629 +}
26630 +
26631 +static struct ip6t_target ip6t_trace_reg = { 
26632 +       .list = { NULL, NULL },
26633 +       .name = "TRACE",
26634 +       .target = target, 
26635 +       .checkentry = checkentry, 
26636 +       .destroy = NULL, 
26637 +       .me = THIS_MODULE };
26638 +
26639 +static int __init init(void)
26640 +{
26641 +       if (ip6t_register_target(&ip6t_trace_reg))
26642 +               return -EINVAL;
26643 +
26644 +       return 0;
26645 +}
26646 +
26647 +static void __exit fini(void)
26648 +{
26649 +       ip6t_unregister_target(&ip6t_trace_reg);
26650 +}
26651 +
26652 +module_init(init);
26653 +module_exit(fini);
26654 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_ah.c linux-2.4.20/net/ipv6/netfilter/ip6t_ah.c
26655 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_ah.c       Thu Jan  1 00:00:00 1970
26656 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_ah.c   Wed Sep 24 09:16:17 2003
26657 @@ -0,0 +1,207 @@
26658 +/* Kernel module to match AH parameters. */
26659 +#include <linux/module.h>
26660 +#include <linux/skbuff.h>
26661 +#include <linux/ipv6.h>
26662 +#include <linux/types.h>
26663 +#include <net/checksum.h>
26664 +#include <net/ipv6.h>
26665 +
26666 +#include <linux/netfilter_ipv6/ip6_tables.h>
26667 +#include <linux/netfilter_ipv6/ip6t_ah.h>
26668 +
26669 +EXPORT_NO_SYMBOLS;
26670 +MODULE_LICENSE("GPL");
26671 +MODULE_DESCRIPTION("IPv6 AH match");
26672 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
26673 +
26674 +#if 0
26675 +#define DEBUGP printk
26676 +#else
26677 +#define DEBUGP(format, args...)
26678 +#endif
26679 +
26680 +struct ahhdr {
26681 +       __u8    nexthdr;
26682 +       __u8    hdrlen;
26683 +       __u16   reserved;
26684 +       __u32   spi;
26685 +};
26686 +
26687 +/* Returns 1 if the spi is matched by the range, 0 otherwise */
26688 +static inline int
26689 +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
26690 +{
26691 +       int r=0;
26692 +       DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
26693 +              min,spi,max);
26694 +       r=(spi >= min && spi <= max) ^ invert;
26695 +       DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
26696 +       return r;
26697 +}
26698 +
26699 +static int
26700 +match(const struct sk_buff *skb,
26701 +      const struct net_device *in,
26702 +      const struct net_device *out,
26703 +      const void *matchinfo,
26704 +      int offset,
26705 +      const void *protohdr,
26706 +      u_int16_t datalen,
26707 +      int *hotdrop)
26708 +{
26709 +       struct ahhdr *ah = NULL;
26710 +       const struct ip6t_ah *ahinfo = matchinfo;
26711 +       unsigned int temp;
26712 +       int len;
26713 +       u8 nexthdr;
26714 +       unsigned int ptr;
26715 +       unsigned int hdrlen = 0;
26716 +
26717 +       /*DEBUGP("IPv6 AH entered\n");*/
26718 +       /* if (opt->auth == 0) return 0;
26719 +       * It does not filled on output */
26720 +
26721 +       /* type of the 1st exthdr */
26722 +       nexthdr = skb->nh.ipv6h->nexthdr;
26723 +       /* pointer to the 1st exthdr */
26724 +       ptr = sizeof(struct ipv6hdr);
26725 +       /* available length */
26726 +       len = skb->len - ptr;
26727 +       temp = 0;
26728 +
26729 +        while (ip6t_ext_hdr(nexthdr)) {
26730 +               struct ipv6_opt_hdr *hdr;
26731 +
26732 +              DEBUGP("ipv6_ah header iteration \n");
26733 +
26734 +              /* Is there enough space for the next ext header? */
26735 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
26736 +                        return 0;
26737 +              /* No more exthdr -> evaluate */
26738 +                if (nexthdr == NEXTHDR_NONE) {
26739 +                     break;
26740 +              }
26741 +              /* ESP -> evaluate */
26742 +                if (nexthdr == NEXTHDR_ESP) {
26743 +                     break;
26744 +              }
26745 +
26746 +              hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
26747 +
26748 +              /* Calculate the header length */
26749 +                if (nexthdr == NEXTHDR_FRAGMENT) {
26750 +                        hdrlen = 8;
26751 +                } else if (nexthdr == NEXTHDR_AUTH)
26752 +                        hdrlen = (hdr->hdrlen+2)<<2;
26753 +                else
26754 +                        hdrlen = ipv6_optlen(hdr);
26755 +
26756 +              /* AH -> evaluate */
26757 +                if (nexthdr == NEXTHDR_AUTH) {
26758 +                     temp |= MASK_AH;
26759 +                     break;
26760 +              }
26761 +
26762 +
26763 +              /* set the flag */
26764 +              switch (nexthdr){
26765 +                     case NEXTHDR_HOP:
26766 +                     case NEXTHDR_ROUTING:
26767 +                     case NEXTHDR_FRAGMENT:
26768 +                     case NEXTHDR_AUTH:
26769 +                     case NEXTHDR_DEST:
26770 +                            break;
26771 +                     default:
26772 +                            DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
26773 +                            return 0;
26774 +                            break;
26775 +              }
26776 +
26777 +                nexthdr = hdr->nexthdr;
26778 +                len -= hdrlen;
26779 +                ptr += hdrlen;
26780 +               if ( ptr > skb->len ) {
26781 +                       DEBUGP("ipv6_ah: new pointer too large! \n");
26782 +                       break;
26783 +               }
26784 +        }
26785 +
26786 +       /* AH header not found */
26787 +       if ( temp != MASK_AH ) return 0;
26788 +
26789 +       if (len < (int)sizeof(struct ahhdr)){
26790 +              *hotdrop = 1;
26791 +                       return 0;
26792 +       }
26793 +
26794 +       ah = (struct ahhdr *) (skb->data + ptr);
26795 +
26796 +       DEBUGP("IPv6 AH LEN %u %u ", hdrlen, ah->hdrlen);
26797 +       DEBUGP("RES %04X ", ah->reserved);
26798 +       DEBUGP("SPI %u %08X\n", ntohl(ah->spi), ntohl(ah->spi));
26799 +
26800 +       DEBUGP("IPv6 AH spi %02X ",
26801 +                       (spi_match(ahinfo->spis[0], ahinfo->spis[1],
26802 +                           ntohl(ah->spi),
26803 +                           !!(ahinfo->invflags & IP6T_AH_INV_SPI))));
26804 +       DEBUGP("len %02X %04X %02X ",
26805 +                       ahinfo->hdrlen, hdrlen,
26806 +                       (!ahinfo->hdrlen ||
26807 +                           (ahinfo->hdrlen == hdrlen) ^
26808 +                           !!(ahinfo->invflags & IP6T_AH_INV_LEN)));
26809 +       DEBUGP("res %02X %04X %02X\n", 
26810 +                       ahinfo->hdrres, ah->reserved,
26811 +                       !(ahinfo->hdrres && ah->reserved));
26812 +
26813 +       return (ah != NULL)
26814 +              &&
26815 +              (spi_match(ahinfo->spis[0], ahinfo->spis[1],
26816 +                           ntohl(ah->spi),
26817 +                           !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
26818 +              &&
26819 +              (!ahinfo->hdrlen ||
26820 +                           (ahinfo->hdrlen == hdrlen) ^
26821 +                           !!(ahinfo->invflags & IP6T_AH_INV_LEN))
26822 +              &&
26823 +              !(ahinfo->hdrres && ah->reserved);
26824 +}
26825 +
26826 +/* Called when user tries to insert an entry of this type. */
26827 +static int
26828 +checkentry(const char *tablename,
26829 +          const struct ip6t_ip6 *ip,
26830 +          void *matchinfo,
26831 +          unsigned int matchinfosize,
26832 +          unsigned int hook_mask)
26833 +{
26834 +       const struct ip6t_ah *ahinfo = matchinfo;
26835 +
26836 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_ah))) {
26837 +              DEBUGP("ip6t_ah: matchsize %u != %u\n",
26838 +                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_ah)));
26839 +              return 0;
26840 +       }
26841 +       if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
26842 +              DEBUGP("ip6t_ah: unknown flags %X\n",
26843 +                      ahinfo->invflags);
26844 +              return 0;
26845 +       }
26846 +
26847 +       return 1;
26848 +}
26849 +
26850 +static struct ip6t_match ah_match
26851 += { { NULL, NULL }, "ah", &match, &checkentry, NULL, THIS_MODULE };
26852 +
26853 +static int __init init(void)
26854 +{
26855 +       return ip6t_register_match(&ah_match);
26856 +}
26857 +
26858 +static void __exit cleanup(void)
26859 +{
26860 +       ip6t_unregister_match(&ah_match);
26861 +}
26862 +
26863 +module_init(init);
26864 +module_exit(cleanup);
26865 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_condition.c linux-2.4.20/net/ipv6/netfilter/ip6t_condition.c
26866 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_condition.c        Thu Jan  1 00:00:00 1970
26867 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_condition.c    Wed Sep 24 09:17:36 2003
26868 @@ -0,0 +1,254 @@
26869 +/*-------------------------------------------*\
26870 +|    Netfilter Condition Module for IPv6      |
26871 +|                                             |
26872 +|  Description: This module allows firewall   |
26873 +|    rules to match using condition variables |
26874 +|    stored in /proc files.                   |
26875 +|                                             |
26876 +|  Author: Stephane Ouellette     2003-02-10  |
26877 +|          <ouellettes@videotron.ca>          |
26878 +|                                             |
26879 +|  This software is distributed under the     |
26880 +|  terms of the GNU GPL.                      |
26881 +\*-------------------------------------------*/
26882 +
26883 +#include<linux/module.h>
26884 +#include<linux/proc_fs.h>
26885 +#include<linux/spinlock.h>
26886 +#include<linux/string.h>
26887 +#include<asm/atomic.h>
26888 +#include<linux/netfilter_ipv6/ip6_tables.h>
26889 +#include<linux/netfilter_ipv6/ip6t_condition.h>
26890 +
26891 +
26892 +#ifndef CONFIG_PROC_FS
26893 +#error  "Proc file system support is required for this module"
26894 +#endif
26895 +
26896 +
26897 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
26898 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
26899 +MODULE_LICENSE("GPL");
26900 +
26901 +
26902 +struct condition_variable {
26903 +       struct condition_variable *next;
26904 +       struct proc_dir_entry *status_proc;
26905 +       atomic_t refcount;
26906 +        int enabled; /* TRUE == 1, FALSE == 0 */
26907 +};
26908 +
26909 +
26910 +static rwlock_t list_lock;
26911 +static struct condition_variable *head = NULL;
26912 +static struct proc_dir_entry *proc_net_condition = NULL;
26913 +
26914 +
26915 +static int
26916 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
26917 +                       int length, int *eof, void *data)
26918 +{
26919 +       struct condition_variable *var =
26920 +           (struct condition_variable *) data;
26921 +
26922 +       if (offset == 0) {
26923 +               *start = buffer;
26924 +               buffer[0] = (var->enabled) ? '1' : '0';
26925 +               buffer[1] = '\n';
26926 +               return 2;
26927 +       }
26928 +
26929 +       *eof = 1;
26930 +       return 0;
26931 +}
26932 +
26933 +
26934 +static int
26935 +ipt_condition_write_info(struct file *file, const char *buffer,
26936 +                        unsigned long length, void *data)
26937 +{
26938 +       struct condition_variable *var =
26939 +           (struct condition_variable *) data;
26940 +
26941 +       if (length) {
26942 +               /* Match only on the first character */
26943 +               switch (buffer[0]) {
26944 +               case '0':
26945 +                       var->enabled = 0;
26946 +                       break;
26947 +               case '1':
26948 +                       var->enabled = 1;
26949 +               }
26950 +       }
26951 +
26952 +       return (int) length;
26953 +}
26954 +
26955 +
26956 +static int
26957 +match(const struct sk_buff *skb, const struct net_device *in,
26958 +      const struct net_device *out, const void *matchinfo, int offset,
26959 +      const void *hdr, u_int16_t datalen, int *hotdrop)
26960 +{
26961 +       const struct condition6_info *info =
26962 +           (const struct condition6_info *) matchinfo;
26963 +       struct condition_variable *var;
26964 +       int condition_status = 0;
26965 +
26966 +       read_lock(&list_lock);
26967 +
26968 +       for (var = head; var; var = var->next) {
26969 +               if (strcmp(info->name, var->status_proc->name) == 0) {
26970 +                       condition_status = var->enabled;
26971 +                       break;
26972 +               }
26973 +       }
26974 +
26975 +       read_unlock(&list_lock);
26976 +
26977 +       return condition_status ^ info->invert;
26978 +}
26979 +
26980 +
26981 +
26982 +static int
26983 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
26984 +          void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
26985 +{
26986 +       struct condition6_info *info =
26987 +           (struct condition6_info *) matchinfo;
26988 +       struct condition_variable *var, *newvar;
26989 +
26990 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
26991 +               return 0;
26992 +
26993 +       /* The first step is to check if the condition variable already exists. */
26994 +       /* Here, a read lock is sufficient because we won't change the list */
26995 +       read_lock(&list_lock);
26996 +
26997 +       for (var = head; var; var = var->next) {
26998 +               if (strcmp(info->name, var->status_proc->name) == 0) {
26999 +                       atomic_inc(&var->refcount);
27000 +                       read_unlock(&list_lock);
27001 +                       return 1;
27002 +               }
27003 +       }
27004 +
27005 +       read_unlock(&list_lock);
27006 +
27007 +       /* At this point, we need to allocate a new condition variable */
27008 +       newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
27009 +
27010 +       if (!newvar)
27011 +               return -ENOMEM;
27012 +
27013 +       /* Create the condition variable's proc file entry */
27014 +       newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
27015 +
27016 +       if (!newvar->status_proc) {
27017 +         /*
27018 +          * There are two possibilities:
27019 +          *  1- Another condition variable with the same name has been created, which is valid.
27020 +          *  2- There was a memory allocation error.
27021 +          */
27022 +               kfree(newvar);
27023 +               read_lock(&list_lock);
27024 +
27025 +               for (var = head; var; var = var->next) {
27026 +                       if (strcmp(info->name, var->status_proc->name) == 0) {
27027 +                               atomic_inc(&var->refcount);
27028 +                               read_unlock(&list_lock);
27029 +                               return 1;
27030 +                       }
27031 +               }
27032 +
27033 +               read_unlock(&list_lock);
27034 +               return -ENOMEM;
27035 +       }
27036 +
27037 +       atomic_set(&newvar->refcount, 1);
27038 +       newvar->enabled = 0;
27039 +       newvar->status_proc->owner = THIS_MODULE;
27040 +       newvar->status_proc->data = newvar;
27041 +       wmb();
27042 +       newvar->status_proc->read_proc = ipt_condition_read_info;
27043 +       newvar->status_proc->write_proc = ipt_condition_write_info;
27044 +
27045 +       write_lock(&list_lock);
27046 +
27047 +       newvar->next = head;
27048 +       head = newvar;
27049 +
27050 +       write_unlock(&list_lock);
27051 +
27052 +       return 1;
27053 +}
27054 +
27055 +
27056 +static void
27057 +destroy(void *matchinfo, unsigned int matchsize)
27058 +{
27059 +       struct condition6_info *info =
27060 +           (struct condition6_info *) matchinfo;
27061 +       struct condition_variable *var, *prev = NULL;
27062 +
27063 +       if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
27064 +               return;
27065 +
27066 +       write_lock(&list_lock);
27067 +
27068 +       for (var = head; var && strcmp(info->name, var->status_proc->name);
27069 +            prev = var, var = var->next);
27070 +
27071 +       if (var && atomic_dec_and_test(&var->refcount)) {
27072 +               if (prev)
27073 +                       prev->next = var->next;
27074 +               else
27075 +                       head = var->next;
27076 +
27077 +               write_unlock(&list_lock);
27078 +               remove_proc_entry(var->status_proc->name, proc_net_condition);
27079 +               kfree(var);
27080 +       } else
27081 +               write_unlock(&list_lock);
27082 +}
27083 +
27084 +
27085 +static struct ip6t_match condition_match = {
27086 +       .name = "condition",
27087 +       .match = &match,
27088 +       .checkentry = &checkentry,
27089 +       .destroy = &destroy,
27090 +       .me = THIS_MODULE
27091 +};
27092 +
27093 +
27094 +static int __init
27095 +init(void)
27096 +{
27097 +       int errorcode;
27098 +
27099 +       rwlock_init(&list_lock);
27100 +       proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
27101 +
27102 +       if (proc_net_condition) {
27103 +               errorcode = ipt_register_match(&condition_match);
27104 +
27105 +               if (errorcode)
27106 +                       remove_proc_entry("ip6t_condition", proc_net);
27107 +       } else
27108 +               errorcode = -EACCES;
27109 +
27110 +       return errorcode;
27111 +}
27112 +
27113 +
27114 +static void __exit
27115 +fini(void)
27116 +{
27117 +       ipt_unregister_match(&condition_match);
27118 +       remove_proc_entry("ip6t_condition", proc_net);
27119 +}
27120 +
27121 +module_init(init);
27122 +module_exit(fini);
27123 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_dst.c linux-2.4.20/net/ipv6/netfilter/ip6t_dst.c
27124 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_dst.c      Thu Jan  1 00:00:00 1970
27125 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_dst.c  Wed Sep 24 09:16:14 2003
27126 @@ -0,0 +1,276 @@
27127 +/* Kernel module to match Hop-by-Hop and Destination parameters. */
27128 +#include <linux/module.h>
27129 +#include <linux/skbuff.h>
27130 +#include <linux/ipv6.h>
27131 +#include <linux/types.h>
27132 +#include <net/checksum.h>
27133 +#include <net/ipv6.h>
27134 +
27135 +#include <asm/byteorder.h>
27136 +
27137 +#include <linux/netfilter_ipv6/ip6_tables.h>
27138 +#include <linux/netfilter_ipv6/ip6t_opts.h>
27139 +
27140 +#define LOW(n)         (n & 0x00FF)
27141 +
27142 +#define HOPBYHOP       0
27143 +
27144 +EXPORT_NO_SYMBOLS;
27145 +MODULE_LICENSE("GPL");
27146 +#if HOPBYHOP
27147 +MODULE_DESCRIPTION("IPv6 HbH match");
27148 +#else
27149 +MODULE_DESCRIPTION("IPv6 DST match");
27150 +#endif
27151 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27152 +
27153 +#if 0
27154 +#define DEBUGP printk
27155 +#else
27156 +#define DEBUGP(format, args...)
27157 +#endif
27158 +
27159 +/*
27160 + * (Type & 0xC0) >> 6
27161 + *     0       -> ignorable
27162 + *     1       -> must drop the packet
27163 + *     2       -> send ICMP PARM PROB regardless and drop packet
27164 + *     3       -> Send ICMP if not a multicast address and drop packet
27165 + *  (Type & 0x20) >> 5
27166 + *     0       -> invariant
27167 + *     1       -> can change the routing
27168 + *  (Type & 0x1F) Type
27169 + *      0      -> PAD0 (only 1 byte!)
27170 + *      1      -> PAD1 LENGTH info (total length = length + 2)
27171 + *      C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
27172 + *      5      -> RTALERT 2 x x
27173 + */
27174 +
27175 +static int
27176 +match(const struct sk_buff *skb,
27177 +      const struct net_device *in,
27178 +      const struct net_device *out,
27179 +      const void *matchinfo,
27180 +      int offset,
27181 +      const void *protohdr,
27182 +      u_int16_t datalen,
27183 +      int *hotdrop)
27184 +{
27185 +       struct ipv6_opt_hdr *optsh = NULL;
27186 +       const struct ip6t_opts *optinfo = matchinfo;
27187 +       unsigned int temp;
27188 +       unsigned int len;
27189 +       u8 nexthdr;
27190 +       unsigned int ptr;
27191 +       unsigned int hdrlen = 0;
27192 +       unsigned int ret = 0;
27193 +       u_int16_t *optdesc = NULL;
27194 +       
27195 +       /* type of the 1st exthdr */
27196 +       nexthdr = skb->nh.ipv6h->nexthdr;
27197 +       /* pointer to the 1st exthdr */
27198 +       ptr = sizeof(struct ipv6hdr);
27199 +       /* available length */
27200 +       len = skb->len - ptr;
27201 +       temp = 0;
27202 +
27203 +        while (ip6t_ext_hdr(nexthdr)) {
27204 +               struct ipv6_opt_hdr *hdr;
27205 +
27206 +              DEBUGP("ipv6_opts header iteration \n");
27207 +
27208 +              /* Is there enough space for the next ext header? */
27209 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
27210 +                        return 0;
27211 +              /* No more exthdr -> evaluate */
27212 +                if (nexthdr == NEXTHDR_NONE) {
27213 +                     break;
27214 +              }
27215 +              /* ESP -> evaluate */
27216 +                if (nexthdr == NEXTHDR_ESP) {
27217 +                     break;
27218 +              }
27219 +
27220 +              hdr=(void *)(skb->data)+ptr;
27221 +
27222 +              /* Calculate the header length */
27223 +                if (nexthdr == NEXTHDR_FRAGMENT) {
27224 +                        hdrlen = 8;
27225 +                } else if (nexthdr == NEXTHDR_AUTH)
27226 +                        hdrlen = (hdr->hdrlen+2)<<2;
27227 +                else
27228 +                        hdrlen = ipv6_optlen(hdr);
27229 +
27230 +              /* OPTS -> evaluate */
27231 +#if HOPBYHOP
27232 +                if (nexthdr == NEXTHDR_HOP) {
27233 +                     temp |= MASK_HOPOPTS;
27234 +#else
27235 +                if (nexthdr == NEXTHDR_DEST) {
27236 +                     temp |= MASK_DSTOPTS;
27237 +#endif
27238 +                     break;
27239 +              }
27240 +
27241 +
27242 +              /* set the flag */
27243 +              switch (nexthdr){
27244 +                     case NEXTHDR_HOP:
27245 +                     case NEXTHDR_ROUTING:
27246 +                     case NEXTHDR_FRAGMENT:
27247 +                     case NEXTHDR_AUTH:
27248 +                     case NEXTHDR_DEST:
27249 +                            break;
27250 +                     default:
27251 +                            DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
27252 +                            return 0;
27253 +                            break;
27254 +              }
27255 +
27256 +                nexthdr = hdr->nexthdr;
27257 +                len -= hdrlen;
27258 +                ptr += hdrlen;
27259 +               if ( ptr > skb->len ) {
27260 +                       DEBUGP("ipv6_opts: new pointer is too large! \n");
27261 +                       break;
27262 +               }
27263 +        }
27264 +
27265 +       /* OPTIONS header not found */
27266 +#if HOPBYHOP
27267 +       if ( temp != MASK_HOPOPTS ) return 0;
27268 +#else
27269 +       if ( temp != MASK_DSTOPTS ) return 0;
27270 +#endif
27271 +
27272 +       if (len < (int)sizeof(struct ipv6_opt_hdr)){
27273 +              *hotdrop = 1;
27274 +                       return 0;
27275 +       }
27276 +
27277 +       if (len < hdrlen){
27278 +              /* Packet smaller than it's length field */
27279 +                       return 0;
27280 +       }
27281 +
27282 +       optsh=(void *)(skb->data)+ptr;
27283 +
27284 +       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
27285 +
27286 +       DEBUGP("len %02X %04X %02X ",
27287 +                       optinfo->hdrlen, hdrlen,
27288 +                       (!(optinfo->flags & IP6T_OPTS_LEN) ||
27289 +                           ((optinfo->hdrlen == hdrlen) ^
27290 +                           !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
27291 +
27292 +       ret = (optsh != NULL)
27293 +                       &&
27294 +               (!(optinfo->flags & IP6T_OPTS_LEN) ||
27295 +                           ((optinfo->hdrlen == hdrlen) ^
27296 +                           !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
27297 +
27298 +       temp = len = 0;
27299 +       ptr += 2;
27300 +       hdrlen -= 2;
27301 +       if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
27302 +              return ret;
27303 +       } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
27304 +               DEBUGP("Not strict - not implemented");
27305 +       } else {
27306 +               DEBUGP("Strict ");
27307 +               DEBUGP("#%d ",optinfo->optsnr);
27308 +               for(temp=0; temp<optinfo->optsnr; temp++){
27309 +                       optdesc = (void *)(skb->data)+ptr;
27310 +                       /* Type check */
27311 +                       if ( (unsigned char)*optdesc != 
27312 +                               (optinfo->opts[temp] & 0xFF00)>>8 ){
27313 +                               DEBUGP("Tbad %02X %02X\n",
27314 +                                               (unsigned char)*optdesc,
27315 +                                               (optinfo->opts[temp] &
27316 +                                                0xFF00)>>8);
27317 +                               return 0;
27318 +                       } else {
27319 +                               DEBUGP("Tok ");
27320 +                       }
27321 +                       /* Length check */
27322 +                       if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
27323 +                               (unsigned char)*optdesc != 0){
27324 +                               if ( ntohs((u16)*optdesc) != 
27325 +                                               optinfo->opts[temp] ){
27326 +                                       DEBUGP("Lbad %02X %04X %04X\n",
27327 +                                                       (unsigned char)*optdesc,
27328 +                                                       ntohs((u16)*optdesc),
27329 +                                                       optinfo->opts[temp]);
27330 +                                       return 0;
27331 +                               } else {
27332 +                                       DEBUGP("Lok ");
27333 +                               }
27334 +                       }
27335 +                       /* Step to the next */
27336 +                       if ((unsigned char)*optdesc == 0){
27337 +                               DEBUGP("PAD0 \n");
27338 +                               ptr++;
27339 +                               hdrlen--;
27340 +                       } else {
27341 +                               ptr += LOW(ntohs(*optdesc));
27342 +                               hdrlen -= LOW(ntohs(*optdesc));
27343 +                               DEBUGP("len%04X \n", 
27344 +                                       LOW(ntohs(*optdesc)));
27345 +                       }
27346 +                       if (ptr > skb->len || ( !hdrlen && 
27347 +                               (temp != optinfo->optsnr - 1))) {
27348 +                               DEBUGP("new pointer is too large! \n");
27349 +                               break;
27350 +                       }
27351 +               }
27352 +               if (temp == optinfo->optsnr)
27353 +                       return ret;
27354 +               else return 0;
27355 +       }
27356 +
27357 +       return 0;
27358 +}
27359 +
27360 +/* Called when user tries to insert an entry of this type. */
27361 +static int
27362 +checkentry(const char *tablename,
27363 +          const struct ip6t_ip6 *ip,
27364 +          void *matchinfo,
27365 +          unsigned int matchinfosize,
27366 +          unsigned int hook_mask)
27367 +{
27368 +       const struct ip6t_opts *optsinfo = matchinfo;
27369 +
27370 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
27371 +              DEBUGP("ip6t_opts: matchsize %u != %u\n",
27372 +                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
27373 +              return 0;
27374 +       }
27375 +       if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
27376 +              DEBUGP("ip6t_opts: unknown flags %X\n",
27377 +                      optsinfo->invflags);
27378 +              return 0;
27379 +       }
27380 +
27381 +       return 1;
27382 +}
27383 +
27384 +static struct ip6t_match opts_match
27385 +#if HOPBYHOP
27386 += { { NULL, NULL }, "hbh", &match, &checkentry, NULL, THIS_MODULE };
27387 +#else
27388 += { { NULL, NULL }, "dst", &match, &checkentry, NULL, THIS_MODULE };
27389 +#endif
27390 +
27391 +static int __init init(void)
27392 +{
27393 +       return ip6t_register_match(&opts_match);
27394 +}
27395 +
27396 +static void __exit cleanup(void)
27397 +{
27398 +       ip6t_unregister_match(&opts_match);
27399 +}
27400 +
27401 +module_init(init);
27402 +module_exit(cleanup);
27403 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_esp.c linux-2.4.20/net/ipv6/netfilter/ip6t_esp.c
27404 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_esp.c      Thu Jan  1 00:00:00 1970
27405 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_esp.c  Wed Sep 24 09:16:17 2003
27406 @@ -0,0 +1,175 @@
27407 +/* Kernel module to match ESP parameters. */
27408 +#include <linux/module.h>
27409 +#include <linux/skbuff.h>
27410 +#include <linux/ipv6.h>
27411 +#include <linux/types.h>
27412 +#include <net/checksum.h>
27413 +#include <net/ipv6.h>
27414 +
27415 +#include <linux/netfilter_ipv6/ip6_tables.h>
27416 +#include <linux/netfilter_ipv6/ip6t_esp.h>
27417 +
27418 +EXPORT_NO_SYMBOLS;
27419 +MODULE_LICENSE("GPL");
27420 +MODULE_DESCRIPTION("IPv6 ESP match");
27421 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27422 +
27423 +#if 0
27424 +#define DEBUGP printk
27425 +#else
27426 +#define DEBUGP(format, args...)
27427 +#endif
27428 +
27429 +struct esphdr {
27430 +       __u32   spi;
27431 +};
27432 +
27433 +/* Returns 1 if the spi is matched by the range, 0 otherwise */
27434 +static inline int
27435 +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
27436 +{
27437 +       int r=0;
27438 +        DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
27439 +               min,spi,max);
27440 +       r=(spi >= min && spi <= max) ^ invert;
27441 +       DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
27442 +       return r;
27443 +}
27444 +
27445 +static int
27446 +match(const struct sk_buff *skb,
27447 +      const struct net_device *in,
27448 +      const struct net_device *out,
27449 +      const void *matchinfo,
27450 +      int offset,
27451 +      const void *protohdr,
27452 +      u_int16_t datalen,
27453 +      int *hotdrop)
27454 +{
27455 +       struct esphdr *esp = NULL;
27456 +       const struct ip6t_esp *espinfo = matchinfo;
27457 +       unsigned int temp;
27458 +       int len;
27459 +       u8 nexthdr;
27460 +       unsigned int ptr;
27461 +
27462 +       /* Make sure this isn't an evil packet */
27463 +       /*DEBUGP("ipv6_esp entered \n");*/
27464 +
27465 +       /* type of the 1st exthdr */
27466 +       nexthdr = skb->nh.ipv6h->nexthdr;
27467 +       /* pointer to the 1st exthdr */
27468 +       ptr = sizeof(struct ipv6hdr);
27469 +       /* available length */
27470 +       len = skb->len - ptr;
27471 +       temp = 0;
27472 +
27473 +        while (ip6t_ext_hdr(nexthdr)) {
27474 +               struct ipv6_opt_hdr *hdr;
27475 +               int hdrlen;
27476 +
27477 +               DEBUGP("ipv6_esp header iteration \n");
27478 +
27479 +               /* Is there enough space for the next ext header? */
27480 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
27481 +                        return 0;
27482 +               /* No more exthdr -> evaluate */
27483 +                if (nexthdr == NEXTHDR_NONE) {
27484 +                       break;
27485 +               }
27486 +               /* ESP -> evaluate */
27487 +                if (nexthdr == NEXTHDR_ESP) {
27488 +                       temp |= MASK_ESP;
27489 +                       break;
27490 +               }
27491 +
27492 +               hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
27493 +
27494 +               /* Calculate the header length */
27495 +                if (nexthdr == NEXTHDR_FRAGMENT) {
27496 +                        hdrlen = 8;
27497 +                } else if (nexthdr == NEXTHDR_AUTH)
27498 +                        hdrlen = (hdr->hdrlen+2)<<2;
27499 +                else
27500 +                        hdrlen = ipv6_optlen(hdr);
27501 +
27502 +               /* set the flag */
27503 +               switch (nexthdr){
27504 +                       case NEXTHDR_HOP:
27505 +                       case NEXTHDR_ROUTING:
27506 +                       case NEXTHDR_FRAGMENT:
27507 +                       case NEXTHDR_AUTH:
27508 +                       case NEXTHDR_DEST:
27509 +                               break;
27510 +                       default:
27511 +                               DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
27512 +                               return 0;
27513 +                               break;
27514 +               }
27515 +
27516 +                nexthdr = hdr->nexthdr;
27517 +                len -= hdrlen;
27518 +                ptr += hdrlen;
27519 +               if ( ptr > skb->len ) {
27520 +                       DEBUGP("ipv6_esp: new pointer too large! \n");
27521 +                       break;
27522 +               }
27523 +        }
27524 +
27525 +       /* ESP header not found */
27526 +       if ( temp != MASK_ESP ) return 0;
27527 +
27528 +       if (len < (int)sizeof(struct esphdr)){
27529 +              *hotdrop = 1;
27530 +                       return 0;
27531 +       }
27532 +
27533 +       esp = (struct esphdr *) (skb->data + ptr);
27534 +
27535 +       DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
27536 +
27537 +       return (esp != NULL)
27538 +               && spi_match(espinfo->spis[0], espinfo->spis[1],
27539 +                             ntohl(esp->spi),
27540 +                             !!(espinfo->invflags & IP6T_ESP_INV_SPI));
27541 +}
27542 +
27543 +/* Called when user tries to insert an entry of this type. */
27544 +static int
27545 +checkentry(const char *tablename,
27546 +          const struct ip6t_ip6 *ip,
27547 +          void *matchinfo,
27548 +          unsigned int matchinfosize,
27549 +          unsigned int hook_mask)
27550 +{
27551 +       const struct ip6t_esp *espinfo = matchinfo;
27552 +
27553 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_esp))) {
27554 +               DEBUGP("ip6t_esp: matchsize %u != %u\n",
27555 +                        matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_esp)));
27556 +               return 0;
27557 +       }
27558 +       if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
27559 +               DEBUGP("ip6t_esp: unknown flags %X\n",
27560 +                        espinfo->invflags);
27561 +               return 0;
27562 +       }
27563 +
27564 +       return 1;
27565 +}
27566 +
27567 +static struct ip6t_match esp_match
27568 += { { NULL, NULL }, "esp", &match, &checkentry, NULL, THIS_MODULE };
27569 +
27570 +static int __init init(void)
27571 +{
27572 +       return ip6t_register_match(&esp_match);
27573 +}
27574 +
27575 +static void __exit cleanup(void)
27576 +{
27577 +       ip6t_unregister_match(&esp_match);
27578 +}
27579 +
27580 +module_init(init);
27581 +module_exit(cleanup);
27582 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_frag.c linux-2.4.20/net/ipv6/netfilter/ip6t_frag.c
27583 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_frag.c     Thu Jan  1 00:00:00 1970
27584 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_frag.c Wed Sep 24 09:16:17 2003
27585 @@ -0,0 +1,239 @@
27586 +/* Kernel module to match FRAG parameters. */
27587 +#include <linux/module.h>
27588 +#include <linux/skbuff.h>
27589 +#include <linux/ipv6.h>
27590 +#include <linux/types.h>
27591 +#include <net/checksum.h>
27592 +#include <net/ipv6.h>
27593 +
27594 +#include <asm/byteorder.h>
27595 +
27596 +#include <linux/netfilter_ipv6/ip6_tables.h>
27597 +#include <linux/netfilter_ipv6/ip6t_frag.h>
27598 +
27599 +EXPORT_NO_SYMBOLS;
27600 +MODULE_LICENSE("GPL");
27601 +MODULE_DESCRIPTION("IPv6 FRAG match");
27602 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27603 +
27604 +#if 0
27605 +#define DEBUGP printk
27606 +#else
27607 +#define DEBUGP(format, args...)
27608 +#endif
27609 +
27610 +#if 0
27611 +#if     BYTE_ORDER == BIG_ENDIAN
27612 +#define IP6F_OFF_MASK       0xfff8  /* mask out offset from _offlg */
27613 +#define IP6F_RESERVED_MASK  0x0006  /* reserved bits in ip6f_offlg */
27614 +#define IP6F_MORE_FRAG      0x0001  /* more-fragments flag */
27615 +#else   /* BYTE_ORDER == LITTLE_ENDIAN */
27616 +#define IP6F_OFF_MASK       0xf8ff  /* mask out offset from _offlg */
27617 +#define IP6F_RESERVED_MASK  0x0600  /* reserved bits in ip6f_offlg */
27618 +#define IP6F_MORE_FRAG      0x0100  /* more-fragments flag */
27619 +#endif
27620 +#endif
27621 +
27622 +#define IP6F_OFF_MASK       0xf8ff  /* mask out offset from _offlg */
27623 +#define IP6F_RESERVED_MASK  0x0600  /* reserved bits in ip6f_offlg */
27624 +#define IP6F_MORE_FRAG      0x0100  /* more-fragments flag */
27625 +
27626 +struct fraghdr {
27627 +       __u8    nexthdr;
27628 +       __u8    hdrlen;
27629 +       __u16   info;
27630 +       __u32   id;
27631 +};
27632 +
27633 +/* Returns 1 if the id is matched by the range, 0 otherwise */
27634 +static inline int
27635 +id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
27636 +{
27637 +       int r=0;
27638 +       DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
27639 +              min,id,max);
27640 +       r=(id >= min && id <= max) ^ invert;
27641 +       DEBUGP(" result %s\n",r? "PASS" : "FAILED");
27642 +       return r;
27643 +}
27644 +
27645 +static int
27646 +match(const struct sk_buff *skb,
27647 +      const struct net_device *in,
27648 +      const struct net_device *out,
27649 +      const void *matchinfo,
27650 +      int offset,
27651 +      const void *protohdr,
27652 +      u_int16_t datalen,
27653 +      int *hotdrop)
27654 +{
27655 +       struct fraghdr *frag = NULL;
27656 +       const struct ip6t_frag *fraginfo = matchinfo;
27657 +       unsigned int temp;
27658 +       int len;
27659 +       u8 nexthdr;
27660 +       unsigned int ptr;
27661 +       unsigned int hdrlen = 0;
27662 +
27663 +       /* type of the 1st exthdr */
27664 +       nexthdr = skb->nh.ipv6h->nexthdr;
27665 +       /* pointer to the 1st exthdr */
27666 +       ptr = sizeof(struct ipv6hdr);
27667 +       /* available length */
27668 +       len = skb->len - ptr;
27669 +       temp = 0;
27670 +
27671 +        while (ip6t_ext_hdr(nexthdr)) {
27672 +               struct ipv6_opt_hdr *hdr;
27673 +
27674 +              DEBUGP("ipv6_frag header iteration \n");
27675 +
27676 +              /* Is there enough space for the next ext header? */
27677 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
27678 +                        return 0;
27679 +              /* No more exthdr -> evaluate */
27680 +                if (nexthdr == NEXTHDR_NONE) {
27681 +                     break;
27682 +              }
27683 +              /* ESP -> evaluate */
27684 +                if (nexthdr == NEXTHDR_ESP) {
27685 +                     break;
27686 +              }
27687 +
27688 +              hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
27689 +
27690 +              /* Calculate the header length */
27691 +                if (nexthdr == NEXTHDR_FRAGMENT) {
27692 +                        hdrlen = 8;
27693 +                } else if (nexthdr == NEXTHDR_AUTH)
27694 +                        hdrlen = (hdr->hdrlen+2)<<2;
27695 +                else
27696 +                        hdrlen = ipv6_optlen(hdr);
27697 +
27698 +              /* FRAG -> evaluate */
27699 +                if (nexthdr == NEXTHDR_FRAGMENT) {
27700 +                     temp |= MASK_FRAGMENT;
27701 +                     break;
27702 +              }
27703 +
27704 +
27705 +              /* set the flag */
27706 +              switch (nexthdr){
27707 +                     case NEXTHDR_HOP:
27708 +                     case NEXTHDR_ROUTING:
27709 +                     case NEXTHDR_FRAGMENT:
27710 +                     case NEXTHDR_AUTH:
27711 +                     case NEXTHDR_DEST:
27712 +                            break;
27713 +                     default:
27714 +                            DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr);
27715 +                            return 0;
27716 +                            break;
27717 +              }
27718 +
27719 +                nexthdr = hdr->nexthdr;
27720 +                len -= hdrlen;
27721 +                ptr += hdrlen;
27722 +               if ( ptr > skb->len ) {
27723 +                       DEBUGP("ipv6_frag: new pointer too large! \n");
27724 +                       break;
27725 +               }
27726 +        }
27727 +
27728 +       /* FRAG header not found */
27729 +       if ( temp != MASK_FRAGMENT ) return 0;
27730 +
27731 +       if (len < (int)sizeof(struct fraghdr)){
27732 +              *hotdrop = 1;
27733 +                       return 0;
27734 +       }
27735 +
27736 +       frag = (struct fraghdr *) (skb->data + ptr);
27737 +
27738 +       DEBUGP("IPv6 FRAG LEN %u %u ", hdrlen, frag->hdrlen);
27739 +       DEBUGP("INFO %04X ", frag->info);
27740 +       DEBUGP("OFFSET %04X ", frag->info & IP6F_OFF_MASK);
27741 +       DEBUGP("RES %04X ", frag->info & IP6F_RESERVED_MASK);
27742 +       DEBUGP("MF %04X ", frag->info & IP6F_MORE_FRAG);
27743 +       DEBUGP("ID %u %08X\n", ntohl(frag->id), ntohl(frag->id));
27744 +
27745 +       DEBUGP("IPv6 FRAG id %02X ",
27746 +                       (id_match(fraginfo->ids[0], fraginfo->ids[1],
27747 +                           ntohl(frag->id),
27748 +                           !!(fraginfo->invflags & IP6T_FRAG_INV_IDS))));
27749 +       DEBUGP("len %02X %04X %02X ",
27750 +                       fraginfo->hdrlen, hdrlen,
27751 +                       (!fraginfo->hdrlen ||
27752 +                           (fraginfo->hdrlen == hdrlen) ^
27753 +                           !!(fraginfo->invflags & IP6T_FRAG_INV_LEN)));
27754 +       DEBUGP("res %02X %02X %02X ", 
27755 +                       (fraginfo->flags & IP6T_FRAG_RES), frag->info & IP6F_RESERVED_MASK,
27756 +                       !((fraginfo->flags & IP6T_FRAG_RES) && (frag->info & IP6F_RESERVED_MASK)));
27757 +       DEBUGP("first %02X %02X %02X ", 
27758 +                       (fraginfo->flags & IP6T_FRAG_FST), frag->info & IP6F_OFF_MASK,
27759 +                       !((fraginfo->flags & IP6T_FRAG_FST) && (frag->info & IP6F_OFF_MASK)));
27760 +       DEBUGP("mf %02X %02X %02X ", 
27761 +                       (fraginfo->flags & IP6T_FRAG_MF), frag->info & IP6F_MORE_FRAG,
27762 +                       !((fraginfo->flags & IP6T_FRAG_MF) && !((frag->info & IP6F_MORE_FRAG))));
27763 +       DEBUGP("last %02X %02X %02X\n", 
27764 +                       (fraginfo->flags & IP6T_FRAG_NMF), frag->info & IP6F_MORE_FRAG,
27765 +                       !((fraginfo->flags & IP6T_FRAG_NMF) && (frag->info & IP6F_MORE_FRAG)));
27766 +
27767 +       return (frag != NULL)
27768 +                       &&
27769 +                       (id_match(fraginfo->ids[0], fraginfo->ids[1],
27770 +                           ntohl(frag->id),
27771 +                           !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
27772 +               &&
27773 +               (!fraginfo->hdrlen ||
27774 +                           (fraginfo->hdrlen == hdrlen) ^
27775 +                           !!(fraginfo->invflags & IP6T_FRAG_INV_LEN))
27776 +               &&
27777 +               !((fraginfo->flags & IP6T_FRAG_RES) && (frag->info & IP6F_RESERVED_MASK))
27778 +               &&
27779 +               !((fraginfo->flags & IP6T_FRAG_FST) && (frag->info & IP6F_OFF_MASK))
27780 +               &&
27781 +               !((fraginfo->flags & IP6T_FRAG_MF) && !((frag->info & IP6F_MORE_FRAG)))
27782 +               &&
27783 +               !((fraginfo->flags & IP6T_FRAG_NMF) && (frag->info & IP6F_MORE_FRAG));
27784 +}
27785 +
27786 +/* Called when user tries to insert an entry of this type. */
27787 +static int
27788 +checkentry(const char *tablename,
27789 +          const struct ip6t_ip6 *ip,
27790 +          void *matchinfo,
27791 +          unsigned int matchinfosize,
27792 +          unsigned int hook_mask)
27793 +{
27794 +       const struct ip6t_frag *fraginfo = matchinfo;
27795 +
27796 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_frag))) {
27797 +              DEBUGP("ip6t_frag: matchsize %u != %u\n",
27798 +                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_frag)));
27799 +              return 0;
27800 +       }
27801 +       if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
27802 +              DEBUGP("ip6t_frag: unknown flags %X\n",
27803 +                      fraginfo->invflags);
27804 +              return 0;
27805 +       }
27806 +
27807 +       return 1;
27808 +}
27809 +
27810 +static struct ip6t_match frag_match
27811 += { { NULL, NULL }, "frag", &match, &checkentry, NULL, THIS_MODULE };
27812 +
27813 +static int __init init(void)
27814 +{
27815 +       return ip6t_register_match(&frag_match);
27816 +}
27817 +
27818 +static void __exit cleanup(void)
27819 +{
27820 +       ip6t_unregister_match(&frag_match);
27821 +}
27822 +
27823 +module_init(init);
27824 +module_exit(cleanup);
27825 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_fuzzy.c linux-2.4.20/net/ipv6/netfilter/ip6t_fuzzy.c
27826 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_fuzzy.c    Thu Jan  1 00:00:00 1970
27827 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_fuzzy.c        Wed Sep 24 09:16:45 2003
27828 @@ -0,0 +1,189 @@
27829 +/*
27830 + * This module implements a simple TSK FLC
27831 + * (Takagi-Sugeno-Kang Fuzzy Logic Controller) that aims
27832 + * to limit , in an adaptive and flexible way , the packet rate crossing
27833 + * a given stream . It serves as an initial and very simple (but effective)
27834 + * example of how Fuzzy Logic techniques can be applied to defeat DoS attacks.
27835 + *  As a matter of fact , Fuzzy Logic can help us to insert any "behavior"
27836 + * into our code in a precise , adaptive and efficient manner.
27837 + *  The goal is very similar to that of "limit" match , but using techniques of
27838 + * Fuzzy Control , that allow us to shape the transfer functions precisely ,
27839 + * avoiding over and undershoots - and stuff like that .
27840 + *
27841 + *
27842 + * 2002-08-10  Hime Aguiar e Oliveira Jr. <hime@engineer.com> : Initial version.
27843 + * 2002-08-17  : Changed to eliminate floating point operations .
27844 + * 2002-08-23  : Coding style changes .
27845 + * 2003-04-08  Maciej Soltysiak <solt@dns.toxicilms.tv> : IPv6 Port
27846 + */
27847 +
27848 +#include <linux/module.h>
27849 +#include <linux/skbuff.h>
27850 +#include <linux/ipv6.h>
27851 +#include <linux/random.h>
27852 +#include <net/tcp.h>
27853 +#include <linux/spinlock.h>
27854 +#include <linux/netfilter_ipv6/ip6_tables.h>
27855 +#include <linux/netfilter_ipv6/ip6t_fuzzy.h>
27856 +
27857 +/*
27858 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
27859 + Expressed in percentage
27860 +*/
27861 +
27862 +#define PAR_LOW                1/100
27863 +#define PAR_HIGH       1
27864 +
27865 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
27866 +
27867 +MODULE_AUTHOR("Hime Aguiar e Oliveira Junior <hime@engineer.com>");
27868 +MODULE_DESCRIPTION("IP tables Fuzzy Logic Controller match module");
27869 +MODULE_LICENSE("GPL");
27870 +
27871 +static  u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
27872 +{
27873 +       if (tx >= maxi) return 100;
27874 +
27875 +       if (tx <= mini) return 0;
27876 +
27877 +       return ((100 * (tx-mini)) / (maxi-mini));
27878 +}
27879 +
27880 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
27881 +{
27882 +       if (tx <= mini) return 100;
27883 +
27884 +       if (tx >= maxi) return 0;
27885 +
27886 +       return ((100 * (maxi - tx)) / (maxi - mini));
27887 +
27888 +}
27889 +
27890 +static int
27891 +ip6t_fuzzy_match(const struct sk_buff *pskb,
27892 +              const struct net_device *in,
27893 +              const struct net_device *out,
27894 +              const void *matchinfo,
27895 +              int offset,
27896 +              const void *hdr,
27897 +              u_int16_t datalen,
27898 +              int *hotdrop)
27899 +{
27900 +       /* From userspace */
27901 +
27902 +       struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
27903 +
27904 +       u_int8_t random_number;
27905 +       unsigned long amount;
27906 +       u_int8_t howhigh, howlow;
27907 +
27908 +
27909 +       spin_lock_bh(&fuzzy_lock); /* Rise the lock */
27910 +
27911 +       info->bytes_total += pskb->len;
27912 +       info->packets_total++;
27913 +
27914 +       info->present_time = jiffies;
27915 +
27916 +       if (info->present_time >= info->previous_time)
27917 +               amount = info->present_time - info->previous_time;
27918 +       else {
27919 +               /* There was a transition : I choose to re-sample
27920 +                  and keep the old acceptance rate...
27921 +               */
27922 +
27923 +               amount = 0;
27924 +               info->previous_time = info->present_time;
27925 +               info->bytes_total = info->packets_total = 0;
27926 +            };
27927 +
27928 +       if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
27929 +
27930 +               info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
27931 +                                       / amount);
27932 +
27933 +               info->previous_time = info->present_time;
27934 +               info->bytes_total = info->packets_total = 0;
27935 +
27936 +               howhigh = mf_high(info->mean_rate,info->minimum_rate,info->maximum_rate);
27937 +               howlow  = mf_low(info->mean_rate,info->minimum_rate,info->maximum_rate);
27938 +
27939 +               info->acceptance_rate = (u_int8_t) \
27940 +                               (howhigh * PAR_LOW + PAR_HIGH * howlow);
27941 +
27942 +       /* In fact, the above defuzzification would require a denominator
27943 +        * proportional to (howhigh+howlow) but, in this particular case,
27944 +        * that expression is constant.
27945 +        * An imediate consequence is that it is not necessary to call
27946 +        * both mf_high and mf_low - but to keep things understandable,
27947 +        * I did so.
27948 +        */
27949 +
27950 +       }
27951 +
27952 +       spin_unlock_bh(&fuzzy_lock); /* Release the lock */
27953 +
27954 +
27955 +       if (info->acceptance_rate < 100)
27956 +       {
27957 +               get_random_bytes((void *)(&random_number), 1);
27958 +
27959 +               /*  If within the acceptance , it can pass => don't match */
27960 +               if (random_number <= (255 * info->acceptance_rate) / 100)
27961 +                       return 0;
27962 +               else
27963 +                       return 1; /* It can't pass (It matches) */
27964 +       };
27965 +
27966 +       return 0; /* acceptance_rate == 100 % => Everything passes ... */
27967 +
27968 +}
27969 +
27970 +static int
27971 +ip6t_fuzzy_checkentry(const char *tablename,
27972 +                  const struct ip6t_ip6 *ip,
27973 +                  void *matchinfo,
27974 +                  unsigned int matchsize,
27975 +                  unsigned int hook_mask)
27976 +{
27977 +
27978 +       const struct ip6t_fuzzy_info *info = matchinfo;
27979 +
27980 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info))) {
27981 +               printk("ip6t_fuzzy: matchsize %u != %u\n", matchsize,
27982 +                      IP6T_ALIGN(sizeof(struct ip6t_fuzzy_info)));
27983 +               return 0;
27984 +       }
27985 +
27986 +       if ((info->minimum_rate < MINFUZZYRATE) || (info->maximum_rate > MAXFUZZYRATE)
27987 +        || (info->minimum_rate >= info->maximum_rate)) {
27988 +               printk("ip6t_fuzzy: BAD limits , please verify !!!\n");
27989 +               return 0;
27990 +       }
27991 +
27992 +       return 1;
27993 +}
27994 +
27995 +static struct ip6t_match ip6t_fuzzy_reg = {
27996 +       {NULL, NULL},
27997 +       "fuzzy",
27998 +       ip6t_fuzzy_match,
27999 +       ip6t_fuzzy_checkentry,
28000 +       NULL,
28001 +       THIS_MODULE };
28002 +
28003 +static int __init init(void)
28004 +{
28005 +       if (ip6t_register_match(&ip6t_fuzzy_reg))
28006 +               return -EINVAL;
28007 +
28008 +       return 0;
28009 +}
28010 +
28011 +static void __exit fini(void)
28012 +{
28013 +       ip6t_unregister_match(&ip6t_fuzzy_reg);
28014 +}
28015 +
28016 +module_init(init);
28017 +module_exit(fini);
28018 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_hbh.c linux-2.4.20/net/ipv6/netfilter/ip6t_hbh.c
28019 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_hbh.c      Thu Jan  1 00:00:00 1970
28020 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_hbh.c  Wed Sep 24 09:16:14 2003
28021 @@ -0,0 +1,276 @@
28022 +/* Kernel module to match Hop-by-Hop and Destination parameters. */
28023 +#include <linux/module.h>
28024 +#include <linux/skbuff.h>
28025 +#include <linux/ipv6.h>
28026 +#include <linux/types.h>
28027 +#include <net/checksum.h>
28028 +#include <net/ipv6.h>
28029 +
28030 +#include <asm/byteorder.h>
28031 +
28032 +#include <linux/netfilter_ipv6/ip6_tables.h>
28033 +#include <linux/netfilter_ipv6/ip6t_opts.h>
28034 +
28035 +#define LOW(n)         (n & 0x00FF)
28036 +
28037 +#define HOPBYHOP       1
28038 +
28039 +EXPORT_NO_SYMBOLS;
28040 +MODULE_LICENSE("GPL");
28041 +#if HOPBYHOP
28042 +MODULE_DESCRIPTION("IPv6 HbH match");
28043 +#else
28044 +MODULE_DESCRIPTION("IPv6 DST match");
28045 +#endif
28046 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28047 +
28048 +#if 0
28049 +#define DEBUGP printk
28050 +#else
28051 +#define DEBUGP(format, args...)
28052 +#endif
28053 +
28054 +/*
28055 + * (Type & 0xC0) >> 6
28056 + *     0       -> ignorable
28057 + *     1       -> must drop the packet
28058 + *     2       -> send ICMP PARM PROB regardless and drop packet
28059 + *     3       -> Send ICMP if not a multicast address and drop packet
28060 + *  (Type & 0x20) >> 5
28061 + *     0       -> invariant
28062 + *     1       -> can change the routing
28063 + *  (Type & 0x1F) Type
28064 + *      0      -> PAD0 (only 1 byte!)
28065 + *      1      -> PAD1 LENGTH info (total length = length + 2)
28066 + *      C0 | 2 -> JUMBO 4 x x x x ( xxxx > 64k )
28067 + *      5      -> RTALERT 2 x x
28068 + */
28069 +
28070 +static int
28071 +match(const struct sk_buff *skb,
28072 +      const struct net_device *in,
28073 +      const struct net_device *out,
28074 +      const void *matchinfo,
28075 +      int offset,
28076 +      const void *protohdr,
28077 +      u_int16_t datalen,
28078 +      int *hotdrop)
28079 +{
28080 +       struct ipv6_opt_hdr *optsh = NULL;
28081 +       const struct ip6t_opts *optinfo = matchinfo;
28082 +       unsigned int temp;
28083 +       unsigned int len;
28084 +       u8 nexthdr;
28085 +       unsigned int ptr;
28086 +       unsigned int hdrlen = 0;
28087 +       unsigned int ret = 0;
28088 +       u_int16_t *optdesc = NULL;
28089 +       
28090 +       /* type of the 1st exthdr */
28091 +       nexthdr = skb->nh.ipv6h->nexthdr;
28092 +       /* pointer to the 1st exthdr */
28093 +       ptr = sizeof(struct ipv6hdr);
28094 +       /* available length */
28095 +       len = skb->len - ptr;
28096 +       temp = 0;
28097 +
28098 +        while (ip6t_ext_hdr(nexthdr)) {
28099 +               struct ipv6_opt_hdr *hdr;
28100 +
28101 +              DEBUGP("ipv6_opts header iteration \n");
28102 +
28103 +              /* Is there enough space for the next ext header? */
28104 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
28105 +                        return 0;
28106 +              /* No more exthdr -> evaluate */
28107 +                if (nexthdr == NEXTHDR_NONE) {
28108 +                     break;
28109 +              }
28110 +              /* ESP -> evaluate */
28111 +                if (nexthdr == NEXTHDR_ESP) {
28112 +                     break;
28113 +              }
28114 +
28115 +              hdr=(void *)(skb->data)+ptr;
28116 +
28117 +              /* Calculate the header length */
28118 +                if (nexthdr == NEXTHDR_FRAGMENT) {
28119 +                        hdrlen = 8;
28120 +                } else if (nexthdr == NEXTHDR_AUTH)
28121 +                        hdrlen = (hdr->hdrlen+2)<<2;
28122 +                else
28123 +                        hdrlen = ipv6_optlen(hdr);
28124 +
28125 +              /* OPTS -> evaluate */
28126 +#if HOPBYHOP
28127 +                if (nexthdr == NEXTHDR_HOP) {
28128 +                     temp |= MASK_HOPOPTS;
28129 +#else
28130 +                if (nexthdr == NEXTHDR_DEST) {
28131 +                     temp |= MASK_DSTOPTS;
28132 +#endif
28133 +                     break;
28134 +              }
28135 +
28136 +
28137 +              /* set the flag */
28138 +              switch (nexthdr){
28139 +                     case NEXTHDR_HOP:
28140 +                     case NEXTHDR_ROUTING:
28141 +                     case NEXTHDR_FRAGMENT:
28142 +                     case NEXTHDR_AUTH:
28143 +                     case NEXTHDR_DEST:
28144 +                            break;
28145 +                     default:
28146 +                            DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
28147 +                            return 0;
28148 +                            break;
28149 +              }
28150 +
28151 +                nexthdr = hdr->nexthdr;
28152 +                len -= hdrlen;
28153 +                ptr += hdrlen;
28154 +               if ( ptr > skb->len ) {
28155 +                       DEBUGP("ipv6_opts: new pointer is too large! \n");
28156 +                       break;
28157 +               }
28158 +        }
28159 +
28160 +       /* OPTIONS header not found */
28161 +#if HOPBYHOP
28162 +       if ( temp != MASK_HOPOPTS ) return 0;
28163 +#else
28164 +       if ( temp != MASK_DSTOPTS ) return 0;
28165 +#endif
28166 +
28167 +       if (len < (int)sizeof(struct ipv6_opt_hdr)){
28168 +              *hotdrop = 1;
28169 +                       return 0;
28170 +       }
28171 +
28172 +       if (len < hdrlen){
28173 +              /* Packet smaller than it's length field */
28174 +                       return 0;
28175 +       }
28176 +
28177 +       optsh=(void *)(skb->data)+ptr;
28178 +
28179 +       DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
28180 +
28181 +       DEBUGP("len %02X %04X %02X ",
28182 +                       optinfo->hdrlen, hdrlen,
28183 +                       (!(optinfo->flags & IP6T_OPTS_LEN) ||
28184 +                           ((optinfo->hdrlen == hdrlen) ^
28185 +                           !!(optinfo->invflags & IP6T_OPTS_INV_LEN))));
28186 +
28187 +       ret = (optsh != NULL)
28188 +                       &&
28189 +               (!(optinfo->flags & IP6T_OPTS_LEN) ||
28190 +                           ((optinfo->hdrlen == hdrlen) ^
28191 +                           !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
28192 +
28193 +       temp = len = 0;
28194 +       ptr += 2;
28195 +       hdrlen -= 2;
28196 +       if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
28197 +              return ret;
28198 +       } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
28199 +               DEBUGP("Not strict - not implemented");
28200 +       } else {
28201 +               DEBUGP("Strict ");
28202 +               DEBUGP("#%d ",optinfo->optsnr);
28203 +               for(temp=0; temp<optinfo->optsnr; temp++){
28204 +                       optdesc = (void *)(skb->data)+ptr;
28205 +                       /* Type check */
28206 +                       if ( (unsigned char)*optdesc != 
28207 +                               (optinfo->opts[temp] & 0xFF00)>>8 ){
28208 +                               DEBUGP("Tbad %02X %02X\n",
28209 +                                               (unsigned char)*optdesc,
28210 +                                               (optinfo->opts[temp] &
28211 +                                                0xFF00)>>8);
28212 +                               return 0;
28213 +                       } else {
28214 +                               DEBUGP("Tok ");
28215 +                       }
28216 +                       /* Length check */
28217 +                       if (((optinfo->opts[temp] & 0x00FF) != 0xFF) &&
28218 +                               (unsigned char)*optdesc != 0){
28219 +                               if ( ntohs((u16)*optdesc) != 
28220 +                                               optinfo->opts[temp] ){
28221 +                                       DEBUGP("Lbad %02X %04X %04X\n",
28222 +                                                       (unsigned char)*optdesc,
28223 +                                                       ntohs((u16)*optdesc),
28224 +                                                       optinfo->opts[temp]);
28225 +                                       return 0;
28226 +                               } else {
28227 +                                       DEBUGP("Lok ");
28228 +                               }
28229 +                       }
28230 +                       /* Step to the next */
28231 +                       if ((unsigned char)*optdesc == 0){
28232 +                               DEBUGP("PAD0 \n");
28233 +                               ptr++;
28234 +                               hdrlen--;
28235 +                       } else {
28236 +                               ptr += LOW(ntohs(*optdesc));
28237 +                               hdrlen -= LOW(ntohs(*optdesc));
28238 +                               DEBUGP("len%04X \n", 
28239 +                                       LOW(ntohs(*optdesc)));
28240 +                       }
28241 +                       if (ptr > skb->len || ( !hdrlen && 
28242 +                               (temp != optinfo->optsnr - 1))) {
28243 +                               DEBUGP("new pointer is too large! \n");
28244 +                               break;
28245 +                       }
28246 +               }
28247 +               if (temp == optinfo->optsnr)
28248 +                       return ret;
28249 +               else return 0;
28250 +       }
28251 +
28252 +       return 0;
28253 +}
28254 +
28255 +/* Called when user tries to insert an entry of this type. */
28256 +static int
28257 +checkentry(const char *tablename,
28258 +          const struct ip6t_ip6 *ip,
28259 +          void *matchinfo,
28260 +          unsigned int matchinfosize,
28261 +          unsigned int hook_mask)
28262 +{
28263 +       const struct ip6t_opts *optsinfo = matchinfo;
28264 +
28265 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_opts))) {
28266 +              DEBUGP("ip6t_opts: matchsize %u != %u\n",
28267 +                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_opts)));
28268 +              return 0;
28269 +       }
28270 +       if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
28271 +              DEBUGP("ip6t_opts: unknown flags %X\n",
28272 +                      optsinfo->invflags);
28273 +              return 0;
28274 +       }
28275 +
28276 +       return 1;
28277 +}
28278 +
28279 +static struct ip6t_match opts_match
28280 +#if HOPBYHOP
28281 += { { NULL, NULL }, "hbh", &match, &checkentry, NULL, THIS_MODULE };
28282 +#else
28283 += { { NULL, NULL }, "dst", &match, &checkentry, NULL, THIS_MODULE };
28284 +#endif
28285 +
28286 +static int __init init(void)
28287 +{
28288 +       return ip6t_register_match(&opts_match);
28289 +}
28290 +
28291 +static void __exit cleanup(void)
28292 +{
28293 +       ip6t_unregister_match(&opts_match);
28294 +}
28295 +
28296 +module_init(init);
28297 +module_exit(cleanup);
28298 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_hl.c linux-2.4.20/net/ipv6/netfilter/ip6t_hl.c
28299 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_hl.c       Thu Jan  1 00:00:00 1970
28300 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_hl.c   Wed Sep 24 09:16:14 2003
28301 @@ -0,0 +1,74 @@
28302 +/*
28303 + * Hop Limit matching module
28304 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
28305 + * Based on HW's ttl module
28306 + *
28307 + * This software is distributed under the terms  GNU GPL
28308 + */
28309 +
28310 +#include <linux/module.h>
28311 +#include <linux/skbuff.h>
28312 +
28313 +#include <linux/netfilter_ipv6/ip6t_hl.h>
28314 +#include <linux/netfilter_ipv6/ip6_tables.h>
28315 +
28316 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
28317 +MODULE_DESCRIPTION("IP tables Hop Limit matching module");
28318 +MODULE_LICENSE("GPL");
28319 +
28320 +static int match(const struct sk_buff *skb, const struct net_device *in,
28321 +                const struct net_device *out, const void *matchinfo,
28322 +                int offset, const void *hdr, u_int16_t datalen,
28323 +                int *hotdrop)
28324 +{
28325 +       const struct ip6t_hl_info *info = matchinfo;
28326 +       const struct ipv6hdr *ip6h = skb->nh.ipv6h;
28327 +
28328 +       switch (info->mode) {
28329 +               case IP6T_HL_EQ:
28330 +                       return (ip6h->hop_limit == info->hop_limit);
28331 +                       break;
28332 +               case IP6T_HL_NE:
28333 +                       return (!(ip6h->hop_limit == info->hop_limit));
28334 +                       break;
28335 +               case IP6T_HL_LT:
28336 +                       return (ip6h->hop_limit < info->hop_limit);
28337 +                       break;
28338 +               case IP6T_HL_GT:
28339 +                       return (ip6h->hop_limit > info->hop_limit);
28340 +                       break;
28341 +               default:
28342 +                       printk(KERN_WARNING "ip6t_hl: unknown mode %d\n", 
28343 +                               info->mode);
28344 +                       return 0;
28345 +       }
28346 +
28347 +       return 0;
28348 +}
28349 +
28350 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
28351 +                     void *matchinfo, unsigned int matchsize,
28352 +                     unsigned int hook_mask)
28353 +{
28354 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_hl_info)))
28355 +               return 0;
28356 +
28357 +       return 1;
28358 +}
28359 +
28360 +static struct ip6t_match hl_match = { { NULL, NULL }, "hl", &match,
28361 +               &checkentry, NULL, THIS_MODULE };
28362 +
28363 +static int __init init(void)
28364 +{
28365 +       return ip6t_register_match(&hl_match);
28366 +}
28367 +
28368 +static void __exit fini(void)
28369 +{
28370 +       ip6t_unregister_match(&hl_match);
28371 +
28372 +}
28373 +
28374 +module_init(init);
28375 +module_exit(fini);
28376 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_ipv6header.c linux-2.4.20/net/ipv6/netfilter/ip6t_ipv6header.c
28377 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_ipv6header.c       Thu Jan  1 00:00:00 1970
28378 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_ipv6header.c   Wed Sep 24 09:16:26 2003
28379 @@ -0,0 +1,153 @@
28380 +/* ipv6header match - matches IPv6 packets based
28381 +on whether they contain certain headers */
28382 +
28383 +/* Original idea: Brad Chapman 
28384 + * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
28385 +
28386 +#include <linux/module.h>
28387 +#include <linux/skbuff.h>
28388 +#include <linux/ipv6.h>
28389 +#include <linux/types.h>
28390 +#include <net/checksum.h>
28391 +#include <net/ipv6.h>
28392 +
28393 +#include <linux/netfilter_ipv6/ip6_tables.h>
28394 +#include <linux/netfilter_ipv6/ip6t_ipv6header.h>
28395 +
28396 +EXPORT_NO_SYMBOLS;
28397 +MODULE_LICENSE("GPL");
28398 +MODULE_DESCRIPTION("IPv6 headers match");
28399 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28400 +
28401 +static int
28402 +ipv6header_match(const struct sk_buff *skb,
28403 +                const struct net_device *in,
28404 +                const struct net_device *out,
28405 +                const void *matchinfo,
28406 +                int offset,
28407 +                const void *protohdr,
28408 +                u_int16_t datalen,
28409 +                int *hotdrop)
28410 +{
28411 +       const struct ip6t_ipv6header_info *info = matchinfo;
28412 +       unsigned int temp;
28413 +       int len;
28414 +       u8 nexthdr;
28415 +       unsigned int ptr;
28416 +
28417 +       /* Make sure this isn't an evil packet */
28418 +
28419 +       /* type of the 1st exthdr */
28420 +       nexthdr = skb->nh.ipv6h->nexthdr;
28421 +       /* pointer to the 1st exthdr */
28422 +       ptr = sizeof(struct ipv6hdr);
28423 +       /* available length */
28424 +       len = skb->len - ptr;
28425 +       temp = 0;
28426 +
28427 +        while (ip6t_ext_hdr(nexthdr)) {
28428 +               struct ipv6_opt_hdr *hdr;
28429 +               int hdrlen;
28430 +
28431 +               /* Is there enough space for the next ext header? */
28432 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
28433 +                        return 0;
28434 +               /* No more exthdr -> evaluate */
28435 +                if (nexthdr == NEXTHDR_NONE) {
28436 +                       temp |= MASK_NONE;
28437 +                       break;
28438 +               }
28439 +               /* ESP -> evaluate */
28440 +                if (nexthdr == NEXTHDR_ESP) {
28441 +                       temp |= MASK_ESP;
28442 +                       break;
28443 +               }
28444 +
28445 +               hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
28446 +
28447 +               /* Calculate the header length */
28448 +                if (nexthdr == NEXTHDR_FRAGMENT) {
28449 +                        hdrlen = 8;
28450 +                } else if (nexthdr == NEXTHDR_AUTH)
28451 +                        hdrlen = (hdr->hdrlen+2)<<2;
28452 +                else
28453 +                        hdrlen = ipv6_optlen(hdr);
28454 +
28455 +               /* set the flag */
28456 +               switch (nexthdr){
28457 +                       case NEXTHDR_HOP:
28458 +                               temp |= MASK_HOPOPTS;
28459 +                               break;
28460 +                       case NEXTHDR_ROUTING:
28461 +                               temp |= MASK_ROUTING;
28462 +                               break;
28463 +                       case NEXTHDR_FRAGMENT:
28464 +                               temp |= MASK_FRAGMENT;
28465 +                               break;
28466 +                       case NEXTHDR_AUTH:
28467 +                               temp |= MASK_AH;
28468 +                               break;
28469 +                       case NEXTHDR_DEST:
28470 +                               temp |= MASK_DSTOPTS;
28471 +                               break;
28472 +                       default:
28473 +                               return 0;
28474 +                               break;
28475 +               }
28476 +
28477 +                nexthdr = hdr->nexthdr;
28478 +                len -= hdrlen;
28479 +                ptr += hdrlen;
28480 +               if ( ptr > skb->len ) {
28481 +                       break;
28482 +               }
28483 +        }
28484 +
28485 +       if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) )
28486 +               temp |= MASK_PROTO;
28487 +
28488 +       if (info->modeflag)
28489 +               return (!( (temp & info->matchflags)
28490 +                       ^ info->matchflags) ^ info->invflags);
28491 +       else
28492 +               return (!( temp ^ info->matchflags) ^ info->invflags);
28493 +}
28494 +
28495 +static int
28496 +ipv6header_checkentry(const char *tablename,
28497 +                     const struct ip6t_ip6 *ip,
28498 +                     void *matchinfo,
28499 +                     unsigned int matchsize,
28500 +                     unsigned int hook_mask)
28501 +{
28502 +       /* Check for obvious errors */
28503 +       /* This match is valid in all hooks! */
28504 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) {
28505 +               return 0;
28506 +       }
28507 +
28508 +       return 1;
28509 +}
28510 +
28511 +static struct ip6t_match
28512 +ip6t_ipv6header_match = {
28513 +       { NULL, NULL },
28514 +       "ipv6header",
28515 +       &ipv6header_match,
28516 +       &ipv6header_checkentry,
28517 +       THIS_MODULE
28518 +};
28519 +
28520 +static int  __init ipv6header_init(void)
28521 +{
28522 +       return ip6t_register_match(&ip6t_ipv6header_match);
28523 +}
28524 +
28525 +static void __exit ipv6header_exit(void)
28526 +{
28527 +       ip6t_unregister_match(&ip6t_ipv6header_match);
28528 +}
28529 +
28530 +module_init(ipv6header_init);
28531 +module_exit(ipv6header_exit);
28532 +
28533 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_nth.c linux-2.4.20/net/ipv6/netfilter/ip6t_nth.c
28534 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_nth.c      Thu Jan  1 00:00:00 1970
28535 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_nth.c  Wed Sep 24 09:16:55 2003
28536 @@ -0,0 +1,173 @@
28537 +/*
28538 +  This is a module which is used for match support for every Nth packet
28539 +  This file is distributed under the terms of the GNU General Public
28540 +  License (GPL). Copies of the GPL can be obtained from:
28541 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
28542 +
28543 +  2001-07-18 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
28544 +  2001-09-20 Richard Wagner (rwagner@cloudnet.com)
28545 +        * added support for multiple counters
28546 +        * added support for matching on individual packets
28547 +          in the counter cycle
28548 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
28549 +
28550 +*/
28551 +
28552 +#include <linux/module.h>
28553 +#include <linux/skbuff.h>
28554 +#include <linux/ip.h>
28555 +#include <net/tcp.h>
28556 +#include <linux/spinlock.h>
28557 +#include <linux/netfilter_ipv6/ip6_tables.h>
28558 +#include <linux/netfilter_ipv6/ip6t_nth.h>
28559 +
28560 +MODULE_LICENSE("GPL");
28561 +
28562 +/*
28563 + * State information.
28564 + */
28565 +struct state {
28566 +       spinlock_t lock;
28567 +       u_int16_t number;
28568 +};
28569 +
28570 +static struct state states[IP6T_NTH_NUM_COUNTERS];
28571 +
28572 +static int
28573 +ip6t_nth_match(const struct sk_buff *pskb,
28574 +             const struct net_device *in,
28575 +             const struct net_device *out,
28576 +             const void *matchinfo,
28577 +             int offset,
28578 +             const void *hdr,
28579 +             u_int16_t datalen,
28580 +             int *hotdrop)
28581 +{
28582 +       /* Parameters from userspace */
28583 +       const struct ip6t_nth_info *info = matchinfo;
28584 +        unsigned counter = info->counter;
28585 +               if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
28586 +       {
28587 +                       printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
28588 +               return 0;
28589 +        };
28590 +
28591 +        spin_lock(&states[counter].lock);
28592 +
28593 +        /* Are we matching every nth packet?*/
28594 +        if (info->packet == 0xFF)
28595 +        {
28596 +               /* We're matching every nth packet and only every nth packet*/
28597 +               /* Do we match or invert match? */
28598 +               if (info->not == 0)
28599 +               {
28600 +                       if (states[counter].number == 0)
28601 +                       {
28602 +                               ++states[counter].number;
28603 +                               goto match;
28604 +                       }
28605 +                       if (states[counter].number >= info->every)
28606 +                               states[counter].number = 0; /* reset the counter */
28607 +                       else
28608 +                               ++states[counter].number;
28609 +                       goto dontmatch;
28610 +               }
28611 +               else
28612 +               {
28613 +                       if (states[counter].number == 0)
28614 +                       {
28615 +                               ++states[counter].number;
28616 +                               goto dontmatch;
28617 +                       }
28618 +                       if (states[counter].number >= info->every)
28619 +                               states[counter].number = 0;
28620 +                       else
28621 +                               ++states[counter].number;
28622 +                       goto match;
28623 +               }
28624 +        }
28625 +        else
28626 +        {
28627 +               /* We're using the --packet, so there must be a rule for every value */
28628 +               if (states[counter].number == info->packet)
28629 +               {
28630 +                       /* only increment the counter when a match happens */
28631 +                       if (states[counter].number >= info->every)
28632 +                               states[counter].number = 0; /* reset the counter */
28633 +                       else
28634 +                               ++states[counter].number;
28635 +                       goto match;
28636 +               }
28637 +               else
28638 +                       goto dontmatch;
28639 +       }
28640 +
28641 + dontmatch:
28642 +       /* don't match */
28643 +       spin_unlock(&states[counter].lock);
28644 +       return 0;
28645 +
28646 + match:
28647 +       spin_unlock(&states[counter].lock);
28648 +       return 1;
28649 +}
28650 +
28651 +static int
28652 +ip6t_nth_checkentry(const char *tablename,
28653 +                  const struct ip6t_ip6 *e,
28654 +                  void *matchinfo,
28655 +                  unsigned int matchsize,
28656 +                  unsigned int hook_mask)
28657 +{
28658 +       /* Parameters from userspace */
28659 +       const struct ip6t_nth_info *info = matchinfo;
28660 +        unsigned counter = info->counter;
28661 +        if((counter < 0) || (counter >= IP6T_NTH_NUM_COUNTERS)) 
28662 +       {
28663 +               printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
28664 +                       return 0;
28665 +               };
28666 +
28667 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_nth_info))) {
28668 +               printk("nth: matchsize %u != %u\n", matchsize,
28669 +                      IP6T_ALIGN(sizeof(struct ip6t_nth_info)));
28670 +               return 0;
28671 +       }
28672 +
28673 +       states[counter].number = info->startat;
28674 +
28675 +       return 1;
28676 +}
28677 +
28678 +static struct ip6t_match ip6t_nth_reg = { 
28679 +       {NULL, NULL},
28680 +       "nth",
28681 +       ip6t_nth_match,
28682 +       ip6t_nth_checkentry,
28683 +       NULL,
28684 +       THIS_MODULE };
28685 +
28686 +static int __init init(void)
28687 +{
28688 +       unsigned counter;
28689 +        memset(&states, 0, sizeof(states));
28690 +       if (ip6t_register_match(&ip6t_nth_reg))
28691 +               return -EINVAL;
28692 +
28693 +        for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++) 
28694 +       {
28695 +               spin_lock_init(&(states[counter].lock));
28696 +        };
28697 +
28698 +       printk("ip6t_nth match loaded\n");
28699 +       return 0;
28700 +}
28701 +
28702 +static void __exit fini(void)
28703 +{
28704 +       ip6t_unregister_match(&ip6t_nth_reg);
28705 +       printk("ip6t_nth match unloaded\n");
28706 +}
28707 +
28708 +module_init(init);
28709 +module_exit(fini);
28710 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_owner.c linux-2.4.20/net/ipv6/netfilter/ip6t_owner.c
28711 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_owner.c    Tue Oct 30 23:08:12 2001
28712 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_owner.c        Wed Sep 24 09:17:52 2003
28713 @@ -16,6 +16,38 @@
28714  MODULE_LICENSE("GPL");
28715  
28716  static int
28717 +match_comm(const struct sk_buff *skb, const char *comm)
28718 +{
28719 +       struct task_struct *p;
28720 +       struct files_struct *files;
28721 +       int i;
28722 +
28723 +       read_lock(&tasklist_lock);
28724 +       for_each_task(p) {
28725 +               if(strncmp(p->comm, comm, sizeof(p->comm)))
28726 +                       continue;
28727 +
28728 +               task_lock(p);
28729 +               files = p->files;
28730 +               if(files) {
28731 +                       read_lock(&files->file_lock);
28732 +                       for (i=0; i < files->max_fds; i++) {
28733 +                               if (fcheck_files(files, i) == skb->sk->socket->file) {
28734 +                                       read_unlock(&files->file_lock);
28735 +                                       task_unlock(p);
28736 +                                       read_unlock(&tasklist_lock);
28737 +                                       return 1;
28738 +                               }
28739 +                       }
28740 +                       read_unlock(&files->file_lock);
28741 +               }
28742 +               task_unlock(p);
28743 +       }
28744 +       read_unlock(&tasklist_lock);
28745 +       return 0;
28746 +}
28747 +
28748 +static int
28749  match_pid(const struct sk_buff *skb, pid_t pid)
28750  {
28751         struct task_struct *p;
28752 @@ -119,6 +151,12 @@
28753                         return 0;
28754         }
28755  
28756 +       if(info->match & IP6T_OWNER_COMM) {
28757 +               if (!match_comm(skb, info->comm) ^
28758 +                   !!(info->invert & IP6T_OWNER_COMM))
28759 +                       return 0;
28760 +       }
28761 +
28762         return 1;
28763  }
28764  
28765 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_random.c linux-2.4.20/net/ipv6/netfilter/ip6t_random.c
28766 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_random.c   Thu Jan  1 00:00:00 1970
28767 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_random.c       Wed Sep 24 09:17:07 2003
28768 @@ -0,0 +1,97 @@
28769 +/*
28770 +  This is a module which is used for a "random" match support.
28771 +  This file is distributed under the terms of the GNU General Public
28772 +  License (GPL). Copies of the GPL can be obtained from:
28773 +     ftp://prep.ai.mit.edu/pub/gnu/GPL
28774 +
28775 +  2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
28776 +  2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
28777 +*/
28778 +
28779 +#include <linux/module.h>
28780 +#include <linux/skbuff.h>
28781 +#include <linux/ip.h>
28782 +#include <linux/random.h>
28783 +#include <net/tcp.h>
28784 +#include <linux/spinlock.h>
28785 +#include <linux/netfilter_ipv6/ip6_tables.h>
28786 +#include <linux/netfilter_ipv6/ip6t_random.h>
28787 +
28788 +MODULE_LICENSE("GPL");
28789 +
28790 +static int
28791 +ip6t_rand_match(const struct sk_buff *pskb,
28792 +              const struct net_device *in,
28793 +              const struct net_device *out,
28794 +              const void *matchinfo,
28795 +              int offset,
28796 +              const void *hdr,
28797 +              u_int16_t datalen,
28798 +              int *hotdrop)
28799 +{
28800 +       /* Parameters from userspace */
28801 +       const struct ip6t_rand_info *info = matchinfo;
28802 +       u_int8_t random_number;
28803 +
28804 +       /* get 1 random number from the kernel random number generation routine */
28805 +       get_random_bytes((void *)(&random_number), 1);
28806 +
28807 +       /* Do we match ? */
28808 +       if (random_number <= info->average)
28809 +               return 1;
28810 +       else
28811 +               return 0;
28812 +}
28813 +
28814 +static int
28815 +ip6t_rand_checkentry(const char *tablename,
28816 +                  const struct ip6t_ip6 *e,
28817 +                  void *matchinfo,
28818 +                  unsigned int matchsize,
28819 +                  unsigned int hook_mask)
28820 +{
28821 +       /* Parameters from userspace */
28822 +       const struct ip6t_rand_info *info = matchinfo;
28823 +
28824 +       if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_rand_info))) {
28825 +               printk("ip6t_random: matchsize %u != %u\n", matchsize,
28826 +                      IP6T_ALIGN(sizeof(struct ip6t_rand_info)));
28827 +               return 0;
28828 +       }
28829 +
28830 +       /* must be  1 <= average % <= 99 */
28831 +       /* 1  x 2.55 = 2   */
28832 +       /* 99 x 2.55 = 252 */
28833 +       if ((info->average < 2) || (info->average > 252)) {
28834 +               printk("ip6t_random:  invalid average %u\n", info->average);
28835 +               return 0;
28836 +       }
28837 +
28838 +       return 1;
28839 +}
28840 +
28841 +static struct ip6t_match ip6t_rand_reg = { 
28842 +       {NULL, NULL},
28843 +       "random",
28844 +       ip6t_rand_match,
28845 +       ip6t_rand_checkentry,
28846 +       NULL,
28847 +       THIS_MODULE };
28848 +
28849 +static int __init init(void)
28850 +{
28851 +       if (ip6t_register_match(&ip6t_rand_reg))
28852 +               return -EINVAL;
28853 +
28854 +       printk("ip6t_random match loaded\n");
28855 +       return 0;
28856 +}
28857 +
28858 +static void __exit fini(void)
28859 +{
28860 +       ip6t_unregister_match(&ip6t_rand_reg);
28861 +       printk("ip6t_random match unloaded\n");
28862 +}
28863 +
28864 +module_init(init);
28865 +module_exit(fini);
28866 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6t_rt.c linux-2.4.20/net/ipv6/netfilter/ip6t_rt.c
28867 --- linux-2.4.20.org/net/ipv6/netfilter/ip6t_rt.c       Thu Jan  1 00:00:00 1970
28868 +++ linux-2.4.20/net/ipv6/netfilter/ip6t_rt.c   Wed Sep 24 09:16:17 2003
28869 @@ -0,0 +1,294 @@
28870 +/* Kernel module to match ROUTING parameters. */
28871 +#include <linux/module.h>
28872 +#include <linux/skbuff.h>
28873 +#include <linux/ipv6.h>
28874 +#include <linux/types.h>
28875 +#include <net/checksum.h>
28876 +#include <net/ipv6.h>
28877 +
28878 +#include <asm/byteorder.h>
28879 +
28880 +#include <linux/netfilter_ipv6/ip6_tables.h>
28881 +#include <linux/netfilter_ipv6/ip6t_rt.h>
28882 +
28883 +EXPORT_NO_SYMBOLS;
28884 +MODULE_LICENSE("GPL");
28885 +MODULE_DESCRIPTION("IPv6 RT match");
28886 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28887 +
28888 +#if 0
28889 +#define DEBUGP printk
28890 +#else
28891 +#define DEBUGP(format, args...)
28892 +#endif
28893 +
28894 +/* Returns 1 if the id is matched by the range, 0 otherwise */
28895 +static inline int
28896 +segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
28897 +{
28898 +       int r=0;
28899 +       DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
28900 +              min,id,max);
28901 +       r=(id >= min && id <= max) ^ invert;
28902 +       DEBUGP(" result %s\n",r? "PASS" : "FAILED");
28903 +       return r;
28904 +}
28905 +
28906 +static int
28907 +match(const struct sk_buff *skb,
28908 +      const struct net_device *in,
28909 +      const struct net_device *out,
28910 +      const void *matchinfo,
28911 +      int offset,
28912 +      const void *protohdr,
28913 +      u_int16_t datalen,
28914 +      int *hotdrop)
28915 +{
28916 +       struct ipv6_rt_hdr *route = NULL;
28917 +       const struct ip6t_rt *rtinfo = matchinfo;
28918 +       unsigned int temp;
28919 +       unsigned int len;
28920 +       u8 nexthdr;
28921 +       unsigned int ptr;
28922 +       unsigned int hdrlen = 0;
28923 +       unsigned int ret = 0;
28924 +
28925 +       /* type of the 1st exthdr */
28926 +       nexthdr = skb->nh.ipv6h->nexthdr;
28927 +       /* pointer to the 1st exthdr */
28928 +       ptr = sizeof(struct ipv6hdr);
28929 +       /* available length */
28930 +       len = skb->len - ptr;
28931 +       temp = 0;
28932 +
28933 +        while (ip6t_ext_hdr(nexthdr)) {
28934 +               struct ipv6_opt_hdr *hdr;
28935 +
28936 +              DEBUGP("ipv6_rt header iteration \n");
28937 +
28938 +              /* Is there enough space for the next ext header? */
28939 +                if (len < (int)sizeof(struct ipv6_opt_hdr))
28940 +                        return 0;
28941 +              /* No more exthdr -> evaluate */
28942 +                if (nexthdr == NEXTHDR_NONE) {
28943 +                     break;
28944 +              }
28945 +              /* ESP -> evaluate */
28946 +                if (nexthdr == NEXTHDR_ESP) {
28947 +                     break;
28948 +              }
28949 +
28950 +              hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
28951 +
28952 +              /* Calculate the header length */
28953 +                if (nexthdr == NEXTHDR_FRAGMENT) {
28954 +                        hdrlen = 8;
28955 +                } else if (nexthdr == NEXTHDR_AUTH)
28956 +                        hdrlen = (hdr->hdrlen+2)<<2;
28957 +                else
28958 +                        hdrlen = ipv6_optlen(hdr);
28959 +
28960 +              /* ROUTING -> evaluate */
28961 +                if (nexthdr == NEXTHDR_ROUTING) {
28962 +                     temp |= MASK_ROUTING;
28963 +                     break;
28964 +              }
28965 +
28966 +
28967 +              /* set the flag */
28968 +              switch (nexthdr){
28969 +                     case NEXTHDR_HOP:
28970 +                     case NEXTHDR_ROUTING:
28971 +                     case NEXTHDR_FRAGMENT:
28972 +                     case NEXTHDR_AUTH:
28973 +                     case NEXTHDR_DEST:
28974 +                            break;
28975 +                     default:
28976 +                            DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr);
28977 +                            return 0;
28978 +                            break;
28979 +              }
28980 +
28981 +                nexthdr = hdr->nexthdr;
28982 +                len -= hdrlen;
28983 +                ptr += hdrlen;
28984 +               if ( ptr > skb->len ) {
28985 +                       DEBUGP("ipv6_rt: new pointer is too large! \n");
28986 +                       break;
28987 +               }
28988 +        }
28989 +
28990 +       /* ROUTING header not found */
28991 +       if ( temp != MASK_ROUTING ) return 0;
28992 +
28993 +       if (len < (int)sizeof(struct ipv6_rt_hdr)){
28994 +              *hotdrop = 1;
28995 +                       return 0;
28996 +       }
28997 +
28998 +       if (len < hdrlen){
28999 +              /* Pcket smaller than its length field */
29000 +                       return 0;
29001 +       }
29002 +
29003 +       route = (struct ipv6_rt_hdr *) (skb->data + ptr);
29004 +
29005 +       DEBUGP("IPv6 RT LEN %u %u ", hdrlen, route->hdrlen);
29006 +       DEBUGP("TYPE %04X ", route->type);
29007 +       DEBUGP("SGS_LEFT %u %08X\n", ntohl(route->segments_left), ntohl(route->segments_left));
29008 +
29009 +       DEBUGP("IPv6 RT segsleft %02X ",
29010 +                       (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
29011 +                           ntohl(route->segments_left),
29012 +                           !!(rtinfo->invflags & IP6T_RT_INV_SGS))));
29013 +       DEBUGP("type %02X %02X %02X ",
29014 +                       rtinfo->rt_type, route->type, 
29015 +                       (!(rtinfo->flags & IP6T_RT_TYP) ||
29016 +                           ((rtinfo->rt_type == route->type) ^
29017 +                           !!(rtinfo->invflags & IP6T_RT_INV_TYP))));
29018 +       DEBUGP("len %02X %04X %02X ",
29019 +                       rtinfo->hdrlen, hdrlen,
29020 +                       (!(rtinfo->flags & IP6T_RT_LEN) ||
29021 +                           ((rtinfo->hdrlen == hdrlen) ^
29022 +                           !!(rtinfo->invflags & IP6T_RT_INV_LEN))));
29023 +       DEBUGP("res %02X %02X %02X ", 
29024 +                       (rtinfo->flags & IP6T_RT_RES), ((struct rt0_hdr *)route)->bitmap,
29025 +                       !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap)));
29026 +
29027 +       ret = (route != NULL)
29028 +                       &&
29029 +                       (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
29030 +                           ntohl(route->segments_left),
29031 +                           !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
29032 +               &&
29033 +               (!(rtinfo->flags & IP6T_RT_LEN) ||
29034 +                           ((rtinfo->hdrlen == hdrlen) ^
29035 +                           !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
29036 +               &&
29037 +                       (!(rtinfo->flags & IP6T_RT_TYP) ||
29038 +                           ((rtinfo->rt_type == route->type) ^
29039 +                           !!(rtinfo->invflags & IP6T_RT_INV_TYP)))
29040 +               &&
29041 +                       !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap));
29042 +
29043 +       DEBUGP("#%d ",rtinfo->addrnr);
29044 +       temp = len = ptr = 0;
29045 +       if ( !(rtinfo->flags & IP6T_RT_FST) ){
29046 +              return ret;
29047 +       } else if (rtinfo->flags & IP6T_RT_FST_NSTRICT) {
29048 +               DEBUGP("Not strict ");
29049 +               if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){
29050 +                       DEBUGP("There isn't enough space\n");
29051 +                       return 0;
29052 +               } else {
29053 +                       DEBUGP("#%d ",rtinfo->addrnr);
29054 +                       ptr = 0;
29055 +                       for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
29056 +                               len = 0;
29057 +                               while ((u8)(((struct rt0_hdr *)route)->
29058 +                                               addr[temp].s6_addr[len]) ==
29059 +                                       (u8)(rtinfo->addrs[ptr].s6_addr[len])){
29060 +                                       DEBUGP("%02X?%02X ",
29061 +               (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
29062 +                                       (u8)(rtinfo->addrs[ptr].s6_addr[len]));
29063 +                                       len++;
29064 +                                       if ( len == 16 ) break;
29065 +                               }
29066 +                               if (len==16) {
29067 +                                       DEBUGP("ptr=%d temp=%d;\n",ptr,temp);
29068 +                                       ptr++;
29069 +                               } else {
29070 +                                       DEBUGP("%02X?%02X ",
29071 +               (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
29072 +                                       (u8)(rtinfo->addrs[ptr].s6_addr[len]));
29073 +                                       DEBUGP("!ptr=%d temp=%d;\n",ptr,temp);
29074 +                               }
29075 +                               if (ptr==rtinfo->addrnr) break;
29076 +                       }
29077 +                       DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr);
29078 +                       if ( (len == 16) && (ptr == rtinfo->addrnr))
29079 +                               return ret;
29080 +                       else return 0;
29081 +               }
29082 +       } else {
29083 +               DEBUGP("Strict ");
29084 +               if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){
29085 +                       DEBUGP("There isn't enough space\n");
29086 +                       return 0;
29087 +               } else {
29088 +                       DEBUGP("#%d ",rtinfo->addrnr);
29089 +                       for(temp=0; temp<rtinfo->addrnr; temp++){
29090 +                               len = 0;
29091 +                               while ((u8)(((struct rt0_hdr *)route)->
29092 +                                               addr[temp].s6_addr[len]) ==
29093 +                                       (u8)(rtinfo->addrs[temp].s6_addr[len])){
29094 +                                       DEBUGP("%02X?%02X ",
29095 +               (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
29096 +                                       (u8)(rtinfo->addrs[temp].s6_addr[len]));
29097 +                                       len++;
29098 +                                       if ( len == 16 ) break;
29099 +                               }
29100 +                               if (len!=16) {
29101 +                                       DEBUGP("%02X?%02X ",
29102 +               (u8)(((struct rt0_hdr *)route)->addr[temp].s6_addr[len]),
29103 +                                       (u8)(rtinfo->addrs[temp].s6_addr[len]));
29104 +                                       DEBUGP("!len=%d temp=%d;\n",len,temp);
29105 +                                       break;
29106 +                               }
29107 +                       }
29108 +                       DEBUGP("temp=%d len=%d #%d\n",temp,len,rtinfo->addrnr);
29109 +                       if ( (len == 16) && (temp == rtinfo->addrnr) && (temp == (unsigned int)((hdrlen-8)/16)))
29110 +                               return ret;
29111 +                       else return 0;
29112 +               }
29113 +       }
29114 +
29115 +       return 0;
29116 +}
29117 +
29118 +/* Called when user tries to insert an entry of this type. */
29119 +static int
29120 +checkentry(const char *tablename,
29121 +          const struct ip6t_ip6 *ip,
29122 +          void *matchinfo,
29123 +          unsigned int matchinfosize,
29124 +          unsigned int hook_mask)
29125 +{
29126 +       const struct ip6t_rt *rtinfo = matchinfo;
29127 +
29128 +       if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_rt))) {
29129 +              DEBUGP("ip6t_rt: matchsize %u != %u\n",
29130 +                      matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_rt)));
29131 +              return 0;
29132 +       }
29133 +       if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
29134 +              DEBUGP("ip6t_rt: unknown flags %X\n",
29135 +                      rtinfo->invflags);
29136 +              return 0;
29137 +       }
29138 +       if ( (rtinfo->flags & (IP6T_RT_RES|IP6T_RT_FST_MASK)) && 
29139 +                      (!(rtinfo->flags & IP6T_RT_TYP) || 
29140 +                      (rtinfo->rt_type != 0) || 
29141 +                      (rtinfo->invflags & IP6T_RT_INV_TYP)) ) {
29142 +             DEBUGP("`--rt-type 0' required before `--rt-0-*'");
29143 +              return 0;
29144 +       }
29145 +
29146 +       return 1;
29147 +}
29148 +
29149 +static struct ip6t_match rt_match
29150 += { { NULL, NULL }, "rt", &match, &checkentry, NULL, THIS_MODULE };
29151 +
29152 +static int __init init(void)
29153 +{
29154 +       return ip6t_register_match(&rt_match);
29155 +}
29156 +
29157 +static void __exit cleanup(void)
29158 +{
29159 +       ip6t_unregister_match(&rt_match);
29160 +}
29161 +
29162 +module_init(init);
29163 +module_exit(cleanup);
29164 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6table_mangle.c linux-2.4.20/net/ipv6/netfilter/ip6table_mangle.c
29165 --- linux-2.4.20.org/net/ipv6/netfilter/ip6table_mangle.c       Mon Feb 25 19:38:14 2002
29166 +++ linux-2.4.20/net/ipv6/netfilter/ip6table_mangle.c   Wed Sep 24 09:16:14 2003
29167 @@ -157,7 +157,7 @@
29168         hop_limit = (*pskb)->nh.ipv6h->hop_limit;
29169  
29170         /* flowlabel and prio (includes version, which shouldn't change either */
29171 -       flowlabel = (u_int32_t) (*pskb)->nh.ipv6h;
29172 +       flowlabel = *((u_int32_t *) (*pskb)->nh.ipv6h);
29173  
29174         ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
29175  
29176 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/ipv6/netfilter/ip6table_raw.c linux-2.4.20/net/ipv6/netfilter/ip6table_raw.c
29177 --- linux-2.4.20.org/net/ipv6/netfilter/ip6table_raw.c  Thu Jan  1 00:00:00 1970
29178 +++ linux-2.4.20/net/ipv6/netfilter/ip6table_raw.c      Wed Sep 24 09:18:14 2003
29179 @@ -0,0 +1,156 @@
29180 +/*
29181 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
29182 + *
29183 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
29184 + */
29185 +#include <linux/module.h>
29186 +#include <linux/netfilter_ipv6/ip6_tables.h>
29187 +
29188 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
29189 +
29190 +#if 0
29191 +#define DEBUGP(x, args...)     printk(KERN_DEBUG x, ## args)
29192 +#else
29193 +#define DEBUGP(x, args...)
29194 +#endif
29195 +
29196 +/* Standard entry. */
29197 +struct ip6t_standard
29198 +{
29199 +       struct ip6t_entry entry;
29200 +       struct ip6t_standard_target target;
29201 +};
29202 +
29203 +struct ip6t_error_target
29204 +{
29205 +       struct ip6t_entry_target target;
29206 +       char errorname[IP6T_FUNCTION_MAXNAMELEN];
29207 +};
29208 +
29209 +struct ip6t_error
29210 +{
29211 +       struct ip6t_entry entry;
29212 +       struct ip6t_error_target target;
29213 +};
29214 +
29215 +static struct
29216 +{
29217 +       struct ip6t_replace repl;
29218 +       struct ip6t_standard entries[2];
29219 +       struct ip6t_error term;
29220 +} initial_table __initdata 
29221 += { { "raw", RAW_VALID_HOOKS, 3,
29222 +      sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
29223 +      { [NF_IP6_PRE_ROUTING]   0,
29224 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
29225 +      { [NF_IP6_PRE_ROUTING]   0,
29226 +       [NF_IP6_LOCAL_OUT]      sizeof(struct ip6t_standard) },
29227 +      0, NULL, { } },
29228 +    {
29229 +           /* PRE_ROUTING */
29230 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
29231 +               0,
29232 +               sizeof(struct ip6t_entry),
29233 +               sizeof(struct ip6t_standard),
29234 +               0, { 0, 0 }, { } },
29235 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
29236 +               -NF_ACCEPT - 1 } },
29237 +           /* LOCAL_OUT */
29238 +            { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
29239 +               0,
29240 +               sizeof(struct ip6t_entry),
29241 +               sizeof(struct ip6t_standard),
29242 +               0, { 0, 0 }, { } },
29243 +             { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
29244 +               -NF_ACCEPT - 1 } },
29245 +    },
29246 +    /* ERROR */
29247 +    { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 0 },
29248 +       0,
29249 +       sizeof(struct ip6t_entry),
29250 +       sizeof(struct ip6t_error),
29251 +       0, { 0, 0 }, { } },
29252 +      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
29253 +         { } },
29254 +       "ERROR"
29255 +      }
29256 +    }
29257 +};
29258 +
29259 +static struct ip6t_table packet_raw = { 
29260 +       .list = { NULL, NULL }, 
29261 +       .name = "raw", 
29262 +       .table = &initial_table.repl,
29263 +       .valid_hooks = RAW_VALID_HOOKS, 
29264 +       .lock = RW_LOCK_UNLOCKED, 
29265 +       .private = NULL, 
29266 +       .me = THIS_MODULE
29267 +};
29268 +
29269 +/* The work comes in here from netfilter.c. */
29270 +static unsigned int
29271 +ip6t_hook(unsigned int hook,
29272 +        struct sk_buff **pskb,
29273 +        const struct net_device *in,
29274 +        const struct net_device *out,
29275 +        int (*okfn)(struct sk_buff *))
29276 +{
29277 +       return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
29278 +}
29279 +
29280 +static struct nf_hook_ops ip6t_ops[] = { 
29281 +       /* PRE_ROUTING */
29282 +       { .list = { NULL, NULL }, 
29283 +         .hook = ip6t_hook, 
29284 +         .pf = PF_INET6,
29285 +         .hooknum = NF_IP6_PRE_ROUTING,
29286 +         .priority = NF_IP6_PRI_FIRST },
29287 +       /* LOCAL_OUT */
29288 +       { .list = { NULL, NULL },
29289 +         .hook = ip6t_hook, 
29290 +         .pf = PF_INET6, 
29291 +         .hooknum = NF_IP6_LOCAL_OUT,
29292 +         .priority = NF_IP6_PRI_FIRST }
29293 +};
29294 +
29295 +static int __init init(void)
29296 +{
29297 +       int ret;
29298 +
29299 +       /* Register table */
29300 +       ret = ip6t_register_table(&packet_raw);
29301 +       if (ret < 0)
29302 +               return ret;
29303 +
29304 +       /* Register hooks */
29305 +       ret = nf_register_hook(&ip6t_ops[0]);
29306 +       if (ret < 0)
29307 +               goto cleanup_table;
29308 +
29309 +       ret = nf_register_hook(&ip6t_ops[1]);
29310 +       if (ret < 0)
29311 +               goto cleanup_hook0;
29312 +
29313 +       return ret;
29314 +
29315 + cleanup_hook0:
29316 +       nf_unregister_hook(&ip6t_ops[0]);
29317 + cleanup_table:
29318 +       ip6t_unregister_table(&packet_raw);
29319 +
29320 +       return ret;
29321 +}
29322 +
29323 +static void __exit fini(void)
29324 +{
29325 +       unsigned int i;
29326 +
29327 +       for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
29328 +               nf_unregister_hook(&ip6t_ops[i]);
29329 +
29330 +       ip6t_unregister_table(&packet_raw);
29331 +}
29332 +
29333 +module_init(init);
29334 +module_exit(fini);
29335 +MODULE_LICENSE("GPL");
29336 diff -Nur --exclude '*.orig' linux-2.4.20.org/net/netsyms.c linux-2.4.20/net/netsyms.c
29337 --- linux-2.4.20.org/net/netsyms.c      Wed Sep 24 08:52:55 2003
29338 +++ linux-2.4.20/net/netsyms.c  Wed Sep 24 09:26:45 2003
29339 @@ -296,6 +296,9 @@
29340  EXPORT_SYMBOL(unregister_inet6addr_notifier);
29341  #include <net/ip6_route.h>
29342  EXPORT_SYMBOL(ip6_route_output);
29343 +#ifdef CONFIG_NETFILTER
29344 +EXPORT_SYMBOL(ip6_route_me_harder);
29345 +#endif
29346  #endif
29347  #if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE)
29348  /* inet functions common to v4 and v6 */
29349 @@ -571,6 +574,7 @@
29350  #endif
29351  #ifdef CONFIG_NETFILTER
29352  #include <linux/netfilter.h>
29353 +#include <linux/netfilter_logging.h>
29354  EXPORT_SYMBOL(nf_register_hook);
29355  EXPORT_SYMBOL(nf_unregister_hook);
29356  EXPORT_SYMBOL(nf_register_sockopt);
29357 @@ -583,6 +587,10 @@
29358  EXPORT_SYMBOL(nf_setsockopt);
29359  EXPORT_SYMBOL(nf_getsockopt);
29360  EXPORT_SYMBOL(ip_ct_attach);
29361 +EXPORT_SYMBOL(nf_log_register);
29362 +EXPORT_SYMBOL(nf_log_unregister);
29363 +EXPORT_SYMBOL(nf_log_packet);
29364 +EXPORT_SYMBOL(nf_log);
29365  #ifdef CONFIG_INET
29366  #include <linux/netfilter_ipv4.h>
29367  EXPORT_SYMBOL(ip_route_me_harder);
29368 @@ -593,13 +601,6 @@
29369  
29370  EXPORT_SYMBOL(softnet_data);
29371  
29372 -#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
29373 -#if !defined (CONFIG_IPV6_MODULE) && !defined (CONFIG_KHTTPD) && !defined (CONFIG_KHTTPD_MODULE)
29374 -EXPORT_SYMBOL(tcp_v4_lookup_listener);
29375 -#endif
29376 -extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
29377 -EXPORT_SYMBOL(udp_v4_lookup);
29378 -#endif
29379  
29380  #if defined(CONFIG_GRKERNSEC_RANDID)
29381  EXPORT_SYMBOL(ip_randomid);
29382 @@ -641,4 +642,28 @@
29383  EXPORT_SYMBOL(wireless_send_event);
29384  #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
29385  
29386 +#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
29387 +#if !defined (CONFIG_IPV6_MODULE) && !defined (CONFIG_KHTTPD) && !defined (CONFIG_KHTTPD_MODULE)
29388 +EXPORT_SYMBOL(tcp_v4_lookup_listener);
29389 +#endif
29390 +#endif
29391 +
29392 +#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
29393 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
29394 +#endif
29395 +
29396 +#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)||defined(CONFIG_IP_NF_MATCH_OWNER)||defined(CONFIG_IP_NF_MATCH_OWNER_MODULE)
29397 +EXPORT_SYMBOL(udp_v4_lookup);
29398 +#endif
29399 +
29400 +#if defined(CONFIG_IP_NF_MATCH_OWNER)||defined(CONFIG_IP_NF_MATCH_OWNER_MODULE)
29401 +EXPORT_SYMBOL(tcp_v4_lookup);
29402 +#endif /* CONFIG_IP_NF_MATCH_OWNER */
29403 +
29404 +#if defined(CONFIG_IP_NF_MATCH_OWNER)||defined(CONFIG_IP_NF_MATCH_OWNER_MODULE)
29405 +#if !(defined (CONFIG_IPV6_MODULE) || defined (CONFIG_KHTTPD) || defined (CONFIG_KHTTPD_MODULE))
29406 +EXPORT_SYMBOL(tcp_timewait_cachep);
29407 +#endif
29408 +#endif /* CONFIG_IP_NF_MATCH_OWNER */
29409 +
29410  #endif  /* CONFIG_NET */
29411 diff -Nur --exclude '*.orig' linux-2.4.20.org/netfilter-patch-o-matic/patches linux-2.4.20/netfilter-patch-o-matic/patches
29412 --- linux-2.4.20.org/netfilter-patch-o-matic/patches    Thu Jan  1 00:00:00 1970
29413 +++ linux-2.4.20/netfilter-patch-o-matic/patches        Wed Sep 24 09:20:32 2003
29414 @@ -0,0 +1,84 @@
29415 +./submitted/01_2.4.19.patch
29416 +./submitted/02_2.4.20.patch
29417 +./submitted/03_2.4.21.patch
29418 +./submitted/04_2.4.22.patch
29419 +./submitted/44_backport_ah_esp_fixes.patch
29420 +./submitted/45_masq_routing_check.patch
29421 +./submitted/54_ip_nat-macro-args.patch
29422 +./submitted/58-ip_conntrack-macro-args.patch
29423 +./submitted/60_nat_tftp-remove-warning.patch
29424 +./submitted/72_recent_procfs_fix.patch
29425 +./submitted/73_ipt_MASQUERADE-oif.patch
29426 +./submitted/74_nat-range-fix.patch
29427 +./submitted/75_REJECT_localpmtu-fix.patch
29428 +./submitted/76_snmp-checksum_h-fix.patch
29429 +./pending/39_ip_conntrack-proc.patch
29430 +./pending/40_nf-log.patch
29431 +./pending/40_nf-log.patch.ipv6
29432 +./pending/55_ipt_unclean-tcp-flag-table.patch
29433 +./pending/59_ip_nat_h-unused-var.patch
29434 +./pending/61-remove-memsets.patch
29435 +./pending/63_getorigdst-tuple-zero.patch
29436 +./pending/64_masquerade-sameip-noflush.patch
29437 +./pending/65_irc-conntrack-mirc-serverlookup.patch
29438 +./pending/66_ipv6header.patch
29439 +./pending/67_nolocalout.patch
29440 +./pending/68_local-nullbinding.patch
29441 +./base/HL.patch.ipv6
29442 +./base/IPV4OPTSSTRIP.patch
29443 +./base/NETLINK.patch
29444 +./base/NETMAP.patch
29445 +./base/REJECT.patch.ipv6
29446 +./base/SAME.patch
29447 +./base/TTL.patch
29448 +./base/connlimit.patch
29449 +./base/fuzzy.patch
29450 +./base/fuzzy6.patch.ipv6
29451 +./base/iprange.patch
29452 +./base/ipv4options.patch
29453 +./base/mport.patch
29454 +./base/nth.patch
29455 +./base/nth6.patch.ipv6
29456 +./base/osf.patch
29457 +./base/pool.patch
29458 +./base/psd.patch
29459 +./base/quota.patch
29460 +./base/random.patch
29461 +./base/random6.patch.ipv6
29462 +./base/realm.patch
29463 +./base/time.patch
29464 +./base/u32.patch
29465 +./extra/CLASSIFY.patch
29466 +./extra/CONNMARK.patch
29467 +./extra/IMQ.patch
29468 +./extra/IMQ.patch.ipv6
29469 +./extra/IPMARK.patch
29470 +./extra/ROUTE.patch
29471 +./extra/ROUTE.patch.ipv6
29472 +./extra/TCPLAG.patch
29473 +./extra/XOR.patch
29474 +./extra/addrtype.patch
29475 +./extra/condition.patch
29476 +./extra/condition6.patch.ipv6
29477 +./extra/cuseeme-nat.patch
29478 +./extra/eggdrop-conntrack.patch
29479 +./extra/h323-conntrack-nat.patch
29480 +./extra/ipt_TARPIT.patch
29481 +./extra/iptables-loopcheck-speedup.patch
29482 +./extra/mms-conntrack-nat.patch
29483 +./extra/netfilter-docbook.patch
29484 +./extra/nfnetlink-ctnetlink-0.11.patch
29485 +./extra/owner-socketlookup.patch
29486 +./extra/ownercmd.patch.ipv6
29487 +./extra/pptp-conntrack-nat.patch
29488 +./extra/quake3-conntrack.patch
29489 +./extra/rpc.patch
29490 +./extra/rsh.patch
29491 +./extra/string.patch
29492 +./extra/talk-conntrack-nat.patch
29493 +./userspace/ipt_REJECT-fake-source.patch
29494 +./userspace/mark-bitwise-ops.patch
29495 +./userspace/raw.patch
29496 +./userspace/raw.patch.ipv6
29497 +./optimizations/ip_ct_refresh_optimization.patch
29498 +./optimizations/ip_ct_refresh_optimization_pptp.patch
This page took 5.090276 seconds and 3 git commands to generate.