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
5 If you want to compile it as a module, say M here and read
6 <file:Documentation/modules.txt>. If unsure, say `N'.
8 +Amanda protocol support
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
17 + If you want to compile it as a module, say M here and read
18 + Documentation/modules.txt. If unsure, say `N'.
21 +CuSeeMe protocol support
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.
29 + If you want to compile it as a module, say M here and read
30 + <file:Documentation/modules.txt>. If unsure, say `Y'.
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.
39 + If you want to compile it as a module, say M here and read
40 + <file:Documentation/modules.txt>. If unsure, say `Y'.
42 +Quake III Arena protocol support
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.
49 + If you want to compile it as a module, say M here and read
50 + <file:Documentation/modules.txt>. If unsure, say `Y'.
52 IRC Send/Chat protocol support
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'.
59 +TFTP protocol support
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
66 + If you want to compile it as a module, say M here and read
67 + Documentation/modules.txt. If unsure, say `Y'.
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.
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.
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'.
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'.
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.
97 + If you want to compile it as a module, say M here and read
98 + Documentation/modules.txt. If unsure, say `N'.
100 +H.323 (netmeeting) support
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.
107 + If you want to compile it as a module, say 'M' here and read
108 + Documentation/modules.txt. If unsure, say 'N'.
110 +PPTP conntrack and NAT support
112 + This module adds support for PPTP (Point to Point Tunnelling Protocol,
113 + RFC2637) conncection tracking and NAT.
115 + If you are running PPTP sessions over a stateful firewall or NAT box,
116 + you may want to enable this feature.
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
121 + If you want to compile it as a module, say M here and read
122 + Documentation/modules.txt. If unsure, say `N'.
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.
130 + You will need GRE support to enable PPTP support.
132 + If you want to compile it as a module, say `M' here and read
133 + Documentation/modules.txt. If unsire, say `N'.
135 +RSH protocol support
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;
141 + Client 0:1023 --> Server 514 (stream 1 - stdin/stdout)
142 + Client 0:1023 <-- Server 0:1023 (stream 2 - stderr)
144 + This connection tracker will identify new RSH sessions,
145 + extract the outbound session details, and notify netfilter
146 + of pending "related" sessions.
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)
153 + If you want to compile it as a module, say M here and read
154 + <file:Documentation/modules.txt>. If unsure, say `N'.
156 +Talk protocol support
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.
168 + If you want to compile it as a module, say 'M' here and read
169 + Documentation/modules.txt. If unsure, say 'N'.
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'.
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).
183 + Short options are available by using 'iptables -m recent -h'
184 + Official Website: <http://snowman.net/projects/ipt_recent/>
186 + If you want to compile it as a module, say M here and read
187 + Documentation/modules.txt. If unsure, say `N'.
190 +CONFIG_IP_NF_MATCH_QUOTA
191 + This match implements network quotas.
193 + If you want to compile it as a module, say M here and read
194 + Documentation/modules.txt. If unsure, say `N'.
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, ...
202 + If you want to compile it as a module, say M here and read
203 + Documentation/modules.txt. If unsure, say `N'.
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'.
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.
217 + If you want to compile it as a module, say M here and read
218 + Documentation/modules.txt. If unsure, say `N'.
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'.
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
236 + Details and examples are in the kernel module source.
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 @@
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
252 + If you want to compile it as a module, say M here and read
253 + Documentation/modules.txt. If unsure, say `N'.
256 +iprange match support
257 +CONFIG_IP_NF_MATCH_IPRANGE
258 + This option makes possible to match IP addresses against
261 + If you want to compile it as a module, say M here and read
262 + <file:Documentation/modules.txt>. If unsure, say `N'.
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.
271 + If you say Y here, try iptables -m ipv4options --help for more information.
273 + If you want to compile it as a module, say M here and read
274 + Documentation/modules.txt. If unsure, say `N'.
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.
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
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
296 + If you want to compile it as a module, say M here and read
297 + Documentation/modules.txt. If unsure, say `N'.
301 +CONFIG_IP_NF_MATCH_OSF
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.
308 + Original table was created by Michal Zalewski <lcamtuf@coredump.cx> for
309 + his excellent p0f and than changed a bit for more convenience.
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.
315 + If you say Y here, try iptables -m osf --help for more information.
317 + If you want to compile it as a module, say M here and read
318 + Documentation/modules.txt. If unsure, say `N'.
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.
325 + If you want to compile it as a module, say M here and read
326 + Documentation/modules.txt. If unsure, say `N'.
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.
335 + If you want to compile it as a module, say M here and read
336 + Documentation/modules.txt. If unsure, say `N'.
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.
344 + This match pretty much resembles the CONFIG_NET_CLS_ROUTE4 option
347 + If you want to compile it as a module, say M here and read
348 + Documentation/modules.txt. If unsure, say `N'.
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).
358 + If you say Y here, try iptables -m time --help for more information.
360 + If you want to compile it as a module, say M here and read
361 + Documentation/modules.txt. If unsure, say `N'.
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.
369 + If you want to compile it as a module, say M here and read
370 + Documentation/modules.txt. If unsure, say `N'.
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'.
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).
384 + If you want to compile it as a module, say M here and read
385 + Documentation/modules.txt. If unsure, say `N'.
388 +CONFIG_IP_NF_MATCH_RPC
389 + This adds CONFIG_IP_NF_MATCH_RPC, which is the RPC connection
390 + matcher and tracker.
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.
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.
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.
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.
414 + If you want to compile it as a module, say M here and read
415 + <file:Documentation/modules.txt>. If unsure, say `N'.
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'.
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.
429 + If you want to compile it as a module, say M here and read
430 + Documentation/modules.txt. If unsure, say `N'.
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'.
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.
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.
454 +raw table support (required for NOTRACK/TRACE)
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
460 + If you want to compile it as a module, say M here and read
461 + <file:Documentation/modules.txt>. If unsure, say `N'.
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
469 + TRACE: tablename/chainname/rulenum
471 + If you want to compile it as a module, say M here and read
472 + <file:Documentation/modules.txt>. If unsure, say `N'.
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).
481 + If you want to compile it as a module, say M here and read
482 + <file:Documentation/modules.txt>. If unsure, say `N'.
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'.
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.
497 + If you want to compile it as a module, say M here and read
498 + Documentation/modules.txt. If unsure, say `N'.
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.
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'.
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.
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'.
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
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'.
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'.
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.
550 + If you want to compile it as a module, say M here and read
551 + <file:Documentation/modules.txt>. If unsure, say `N'.
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.
560 + If you want to compile it as a module, say M here and read
561 + <file:Documentation/modules.txt>. If unsure, say `N'.
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.
573 + The target can be or not a final target. It has to be used inside the
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'.
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'.
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
594 + If you want to compile it as a module, say M here and read
595 + Documentation/modules.txt. If unsure, say `N'.
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.
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.
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/.
612 + If you want to compile it as a module, say M here and read
613 + Documentation/modules.txt. If unsure, say `N'.
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.
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,
626 + atm, cbq, dsmark, pfifo_fast, htb, prio
628 + If you want to compile it as a module, say M here and read
629 + Documentation/modules.txt. If unsure, say `N'.
631 +TCPLAG target support
632 +CONFIG_IP_NF_TARGET_TCPLAG
633 + This option adds a `TCPLAG' target, intended for INPUT, OUTPUT and
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.
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.
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.
652 + If you want to compile it as a module, say M here and read
653 + Documentation/modules.txt. If unsure, say `N'.
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'.
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.
667 + If you want to compile it as a module, say M here and read
668 + Documentation/modules.txt. If unsure, say `N'.
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.
676 + If you want to compile it as a module, say M here and read
677 + Documentation/modules.txt. If unsure, say `N'.
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.
685 + If you want to compile it as a module, say M here and read
686 + Documentation/modules.txt. If unsure, say `N'.
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.
694 + If you want to compile it as a module, say M here and read
695 + Documentation/modules.txt. If unsure, say `N'.
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.
703 + If you want to compile it as a module, say M here and read
704 + Documentation/modules.txt. If unsure, say `N'.
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.
712 + If you want to compile it as a module, say M here and read
713 + Documentation/modules.txt. If unsure, say `N'.
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.
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
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
735 + If you want to compile it as a module, say M here and read
736 + Documentation/modules.txt. If unsure, say `N'.
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.
745 + If you want to compile it as a module, say M here and read
746 + Documentation/modules.txt. If unsure, say `N'.
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'.
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.
761 + If you want to compile it as a module, say M here and read
762 + Documentation/modules.txt. If unsure, say `N'.
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'.
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.
777 + If you want to compile it as a module, say M here and read
778 + Documentation/modules.txt. If unsure, say `N'.
780 +raw table support (required for TRACE)
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
786 + If you want to compile it as a module, say M here and read
787 + <file:Documentation/modules.txt>. If unsure, say `N'.
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
795 + TRACE: tablename/chainname/rulenum
797 + If you want to compile it as a module, say M here and read
798 + <file:Documentation/modules.txt>. If unsure, say `N'.
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'.
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.
812 + If you want to compile it as a module, say M here and read
813 + <file:Documentation/modules.txt>. If unsure, say `N'.
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
821 + The target can be or not a final target. It has to be used inside the
824 + Not working as a module.
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'.
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.
839 TCP Explicit Congestion Notification support
841 Explicit Congestion Notification (ECN) allows routers to notify
842 @@ -3096,6 +3808,22 @@
844 If you want to compile it as a module, say M here and read
845 <file:Documentation/modules.txt>. If unsure, say `N'.
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.
852 + If you want to compile it as a module, say M here and read
853 + <file:Documentation/modules.txt>. If unsure, say `N'.
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.
860 + If you want to compile it as a module, say M here and read
861 + <file:Documentation/modules.txt>. If unsure, say `N'.
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
869 +#ifndef _LINUX_JHASH_H
870 +#define _LINUX_JHASH_H
872 +/* jhash.h: Jenkins hash support.
874 + * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
876 + * http://burtleburtle.net/bob/hash/
878 + * These are the credits from Bob's sources:
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.
885 + * Copyright (C) 2003 David S. Miller (davem@redhat.com)
887 + * I've modified Bob's hash to be useful in the Linux kernel, and
888 + * any bugs present are surely my fault. -DaveM
891 +/* NOTE: Arguments are modified. */
892 +#define __jhash_mix(a, b, c) \
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); \
905 +/* The golden ration: an arbitrary value */
906 +#define JHASH_GOLDEN_RATIO 0x9e3779b9
908 +/* The most generic version, hashes an arbitrary sequence
909 + * of bytes. No alignment or length assumptions are made about
912 +static inline u32 jhash(void *key, u32 length, u32 initval)
918 + a = b = JHASH_GOLDEN_RATIO;
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));
926 + __jhash_mix(a,b,c);
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];
947 + __jhash_mix(a,b,c);
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.
955 +static inline u32 jhash2(u32 *k, u32 length, u32 initval)
959 + a = b = JHASH_GOLDEN_RATIO;
967 + __jhash_mix(a, b, c);
974 + case 2 : b += k[1];
975 + case 1 : a += k[0];
978 + __jhash_mix(a,b,c);
984 +/* A special ultra-optimized versions that knows they are hashing exactly
985 + * 3, 2 or 1 word(s).
987 + * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
988 + * done at the end is not done here.
990 +static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
992 + a += JHASH_GOLDEN_RATIO;
993 + b += JHASH_GOLDEN_RATIO;
996 + __jhash_mix(a, b, c);
1001 +static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
1003 + return jhash_3words(a, b, 0, initval);
1006 +static inline u32 jhash_1word(u32 a, u32 initval)
1008 + return jhash_3words(a, 0, 0, initval);
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
1017 #define NF_MAX_VERDICT NF_REPEAT
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
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
1033 +#ifndef _ARPT_MANGLE_H
1034 +#define _ARPT_MANGLE_H
1035 +#include <linux/netfilter_arp/arp_tables.h>
1037 +#define ARPT_MANGLE_ADDR_LEN_MAX sizeof(struct in_addr)
1040 + char src_devaddr[ARPT_DEV_ADDR_LEN_MAX];
1041 + char tgt_devaddr[ARPT_DEV_ADDR_LEN_MAX];
1043 + struct in_addr src_ip;
1046 + struct in_addr tgt_ip;
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
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
1064 #include <linux/config.h>
1065 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
1066 +#include <linux/bitops.h>
1067 #include <asm/atomic.h>
1069 enum ip_conntrack_info
1071 /* Conntrack should never be early-expired. */
1072 IPS_ASSURED_BIT = 2,
1073 IPS_ASSURED = (1 << IPS_ASSURED_BIT),
1075 + /* Connection is confirmed: originating packet has left box */
1076 + IPS_CONFIRMED_BIT = 3,
1077 + IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
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>
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;
1092 union ip_conntrack_expect_proto {
1093 /* insert expect proto private data here */
1094 + struct ip_ct_gre_expect gre;
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>
1104 +#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
1106 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
1107 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
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;
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;
1134 #ifdef CONFIG_IP_NF_NAT_NEEDED
1135 #include <linux/netfilter_ipv4/ip_nat.h>
1136 +#include <linux/netfilter_ipv4/ip_nat_pptp.h>
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;
1146 struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
1148 /* Have we seen traffic both ways yet? (bitset) */
1149 - volatile unsigned long status;
1150 + unsigned long status;
1152 /* Timer function; drops refcnt when it goes off. */
1153 struct timer_list timeout;
1156 #endif /* CONFIG_IP_NF_NAT_NEEDED */
1158 +#if defined(CONFIG_IP_NF_CONNTRACK_MARK)
1159 + unsigned long mark;
1163 /* get master conntrack via master expectation */
1165 extern void ip_ct_refresh(struct ip_conntrack *ct,
1166 unsigned long extra_jiffies);
1168 +/* Kill conntrack */
1169 +extern void ip_ct_death_by_timeout(unsigned long ul_conntrack);
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)
1178 - return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL;
1179 + return test_bit(IPS_CONFIRMED_BIT, &ct->status);
1182 extern unsigned int ip_conntrack_htable_size;
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
1192 +#ifndef _IP_CONNTRACK_AMANDA_H
1193 +#define _IP_CONNTRACK_AMANDA_H
1194 +/* AMANDA tracking. */
1198 +#include <linux/netfilter_ipv4/lockhelp.h>
1200 +/* Protects amanda part of conntracks */
1201 +DECLARE_LOCK_EXTERN(ip_amanda_lock);
1213 +struct ip_ct_amanda_expect
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 */
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
1225 #ifndef _IP_CONNTRACK_CORE_H
1226 #define _IP_CONNTRACK_CORE_H
1227 +#include <linux/netfilter.h>
1228 #include <linux/netfilter_ipv4/lockhelp.h>
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
1235 +#ifndef _IP_CT_CUSEEME
1236 +#define _IP_CT_CUSEEME
1238 +#define CUSEEME_PORT 7648
1240 +/* These structs come from the 2.2 ip_masq_cuseeme code... */
1243 +/* CuSeeMe data header */
1245 + u_int16_t dest_family;
1246 + u_int16_t dest_port;
1247 + u_int32_t dest_addr;
1253 + u_int16_t data_type;
1254 + /* possible values:
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
1277 + u_int16_t packet_len;
1280 +/* Open Continue Header */
1282 + struct cu_header cu_head;
1283 + u_int16_t client_count; /* Number of client info structs */
1285 + char user_name[20];
1286 + char stuff[4]; /* Flags, version stuff, etc */
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 */
1296 +/* This structure is per expected connection */
1297 +struct ip_ct_cuseeme_expect {
1300 +/* This structure exists only once per master */
1301 +struct ip_ct_cuseeme_master {
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
1309 +#ifndef _IP_CONNTRACK_H323_H
1310 +#define _IP_CONNTRACK_H323_H
1311 +/* H.323 connection tracking. */
1314 +/* Protects H.323 related data */
1315 +DECLARE_LOCK_EXTERN(ip_h323_lock);
1318 +/* Default H.225 port */
1319 +#define H225_PORT 1720
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 */
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 */
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
1343 +#ifndef _IP_CONNTRACK_MMS_H
1344 +#define _IP_CONNTRACK_MMS_H
1345 +/* MMS tracking. */
1348 +#include <linux/netfilter_ipv4/lockhelp.h>
1350 +DECLARE_LOCK_EXTERN(ip_mms_lock);
1352 +#define MMS_PORT 1755
1353 +#define MMS_SRV_MSG_ID 196610
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
1362 +/* This structure is per expected connection */
1363 +struct ip_ct_mms_expect {
1365 + u_int32_t padding;
1369 +/* This structure exists only once per master */
1370 +struct ip_ct_mms_master {
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
1378 +/* PPTP constants and structs */
1379 +#ifndef _CONNTRACK_PPTP_H
1380 +#define _CONNTRACK_PPTP_H
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 */
1391 +/* state of the call inside the control session */
1392 +enum pptp_ctrlcall_state {
1395 + PPTP_CALL_OUT_REQ,
1396 + PPTP_CALL_OUT_CONF,
1399 + PPTP_CALL_IN_CONF,
1400 + PPTP_CALL_CLEAR_REQ,
1404 +/* conntrack private data */
1405 +struct ip_ct_pptp_master {
1406 + enum pptp_ctrlsess_state sstate; /* session state */
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 */
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 */
1425 +#include <linux/netfilter_ipv4/lockhelp.h>
1426 +DECLARE_LOCK_EXTERN(ip_pptp_lock);
1428 +#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
1430 +union pptp_ctrl_union {
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;
1449 +#define PPTP_CONTROL_PORT 1723
1451 +#define PPTP_PACKET_CONTROL 1
1452 +#define PPTP_PACKET_MGMT 2
1454 +#define PPTP_MAGIC_COOKIE 0x1a2b3c4d
1456 +struct pptp_pkt_hdr {
1457 + __u16 packetLength;
1459 + __u32 magicCookie;
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
1479 +#define PPTP_MSG_MAX 15
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
1490 +struct PptpControlHeader {
1491 + __u16 messageType;
1495 +/* FramingCapability Bitmap Values */
1496 +#define PPTP_FRAME_CAP_ASYNC 0x1
1497 +#define PPTP_FRAME_CAP_SYNC 0x2
1499 +/* BearerCapability Bitmap Values */
1500 +#define PPTP_BEARER_CAP_ANALOG 0x1
1501 +#define PPTP_BEARER_CAP_DIGITAL 0x2
1503 +struct PptpStartSessionRequest {
1504 + __u16 protocolVersion;
1507 + __u32 framingCapability;
1508 + __u32 bearerCapability;
1509 + __u16 maxChannels;
1510 + __u16 firmwareRevision;
1511 + __u8 hostName[64];
1512 + __u8 vendorString[64];
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
1522 +struct PptpStartSessionReply {
1523 + __u16 protocolVersion;
1525 + __u8 generalErrorCode;
1526 + __u32 framingCapability;
1527 + __u32 bearerCapability;
1528 + __u16 maxChannels;
1529 + __u16 firmwareRevision;
1530 + __u8 hostName[64];
1531 + __u8 vendorString[64];
1534 +/* PptpStopReasons */
1535 +#define PPTP_STOP_NONE 1
1536 +#define PPTP_STOP_PROTOCOL 2
1537 +#define PPTP_STOP_LOCAL_SHUTDOWN 3
1539 +struct PptpStopSessionRequest {
1543 +/* PptpStopSessionResultCode */
1544 +#define PPTP_STOP_OK 1
1545 +#define PPTP_STOP_GENERAL_ERROR 2
1547 +struct PptpStopSessionReply {
1549 + __u8 generalErrorCode;
1552 +struct PptpEchoRequest {
1553 + __u32 identNumber;
1556 +/* PptpEchoReplyResultCode */
1557 +#define PPTP_ECHO_OK 1
1558 +#define PPTP_ECHO_GENERAL_ERROR 2
1560 +struct PptpEchoReply {
1561 + __u32 identNumber;
1563 + __u8 generalErrorCode;
1567 +/* PptpFramingType */
1568 +#define PPTP_ASYNC_FRAMING 1
1569 +#define PPTP_SYNC_FRAMING 2
1570 +#define PPTP_DONT_CARE_FRAMING 3
1572 +/* PptpCallBearerType */
1573 +#define PPTP_ANALOG_TYPE 1
1574 +#define PPTP_DIGITAL_TYPE 2
1575 +#define PPTP_DONT_CARE_BEARER_TYPE 3
1577 +struct PptpOutCallRequest {
1579 + __u16 callSerialNumber;
1583 + __u32 framingType;
1584 + __u16 packetWindow;
1585 + __u16 packetProcDelay;
1587 + __u16 phoneNumberLength;
1589 + __u8 phoneNumber[64];
1590 + __u8 subAddress[64];
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
1602 +struct PptpOutCallReply {
1604 + __u16 peersCallID;
1606 + __u8 generalErrorCode;
1608 + __u32 connectSpeed;
1609 + __u16 packetWindow;
1610 + __u16 packetProcDelay;
1611 + __u32 physChannelID;
1614 +struct PptpInCallRequest {
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];
1626 +/* PptpInCallResultCode */
1627 +#define PPTP_INCALL_ACCEPT 1
1628 +#define PPTP_INCALL_GENERAL_ERROR 2
1629 +#define PPTP_INCALL_DONT_ACCEPT 3
1631 +struct PptpInCallReply {
1633 + __u16 peersCallID;
1635 + __u8 generalErrorCode;
1636 + __u16 packetWindow;
1637 + __u16 packetProcDelay;
1641 +struct PptpInCallConnected {
1642 + __u16 peersCallID;
1644 + __u32 connectSpeed;
1645 + __u16 packetWindow;
1646 + __u16 packetProcDelay;
1647 + __u32 callFramingType;
1650 +struct PptpClearCallRequest {
1655 +struct PptpCallDisconnectNotify {
1658 + __u8 generalErrorCode;
1661 + __u8 callStatistics[128];
1664 +struct PptpWanErrorNotify {
1665 + __u16 peersCallID;
1668 + __u32 framingErrors;
1669 + __u32 hardwareOverRuns;
1670 + __u32 bufferOverRuns;
1671 + __u32 timeoutErrors;
1672 + __u32 alignmentErrors;
1675 +struct PptpSetLinkInfo {
1676 + __u16 peersCallID;
1683 +struct pptp_priv_data {
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
1695 +#ifndef _CONNTRACK_PROTO_GRE_H
1696 +#define _CONNTRACK_PROTO_GRE_H
1697 +#include <asm/byteorder.h>
1699 +/* GRE PROTOCOL HEADER */
1701 +/* GRE Version field */
1702 +#define GRE_VERSION_1701 0x0
1703 +#define GRE_VERSION_PPTP 0x1
1705 +/* GRE Protocol field */
1706 +#define GRE_PROTOCOL_PPTP 0x880B
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
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)
1721 +/* GRE is a mess: Four different standards */
1723 +#if defined(__LITTLE_ENDIAN_BITFIELD)
1733 +#elif defined(__BIG_ENDIAN_BITFIELD)
1744 +#error "Adjust your <asm/byteorder.h> defines"
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 */
1762 +/* this is part of ip_conntrack */
1764 + unsigned int stream_timeout;
1765 + unsigned int timeout;
1768 +/* this is part of ip_conntrack_expect */
1769 +struct ip_ct_gre_expect {
1770 + struct ip_ct_gre_keymap *keymap_orig, *keymap_reply;
1774 +struct ip_conntrack_expect;
1776 +/* structure for original <-> reply keymap */
1777 +struct ip_ct_gre_keymap {
1778 + struct list_head list;
1780 + struct ip_conntrack_tuple tuple;
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,
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);
1793 +/* delete keymap entries */
1794 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp);
1797 +/* get pointer to gre key, if present */
1798 +static inline u_int32_t *gre_key(struct gre_hdr *greh)
1802 + if (greh->csum || greh->routing)
1803 + return (u_int32_t *) (greh+sizeof(*greh)+4);
1804 + return (u_int32_t *) (greh+sizeof(*greh));
1807 +/* get pointer ot gre csum, if present */
1808 +static inline u_int16_t *gre_csum(struct gre_hdr *greh)
1812 + return (u_int16_t *) (greh+sizeof(*greh));
1815 +#endif /* __KERNEL__ */
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
1822 extern int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto);
1823 extern void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto);
1825 +/* Get the tuple from the packet and return 1 if it's succeeded. */
1827 +ip_conntrack_get_tuple(const struct iphdr *iph, size_t len,
1828 + struct ip_conntrack_tuple *tuple,
1829 + struct ip_conntrack_protocol *protocol);
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
1838 +#ifndef _IP_CT_QUAKE3
1839 +#define _IP_CT_QUAKE3
1841 +/* Don't confuse with 27960, often used as the Server Port */
1842 +#define QUAKE3_MASTER_PORT 27950
1844 +struct quake3_search {
1845 + const char marker[4]; /* always 0xff 0xff 0xff 0xff ? */
1846 + const char *pattern;
1850 +/* This structure is per expected connection */
1851 +struct ip_ct_quake3_expect {
1854 +/* This structure exists only once per master */
1855 +struct ip_ct_quake3_master {
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
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
1868 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
1869 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
1875 + * ip_conntrack_rpc.h,v 2.2 2003/01/12 18:30:00
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.
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>
1890 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
1892 +#ifndef _IP_CONNTRACK_RPC_H
1893 +#define _IP_CONNTRACK_RPC_H
1895 +#define RPC_PORT 111
1898 +/* Datum in RPC packets are encoded in XDR */
1899 +#define IXDR_GET_INT32(buf) ((u_int32_t) ntohl((uint32_t)*buf))
1901 +/* Fast timeout, to deny DoS atacks */
1902 +#define EXP (60 * HZ)
1904 +/* Normal timeouts */
1905 +#define EXPIRES (180 * HZ)
1907 +/* For future conections RPC, using client's cache bindings
1908 + * I'll use ip_conntrack_lock to lock these lists */
1910 +/* This identifies each request and stores protocol */
1912 + struct list_head list;
1921 + struct timer_list timeout;
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);
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
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
1939 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
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.
1946 +#ifndef _IP_CONNTRACK_RSH_H
1947 +#define _IP_CONNTRACK_RSH_H
1950 +#include <linux/netfilter_ipv4/lockhelp.h>
1952 +DECLARE_LOCK_EXTERN(ip_rsh_lock);
1956 +#define RSH_PORT 514
1958 +/* This structure is per expected connection */
1959 +struct ip_ct_rsh_expect
1964 +/* This structure exists only once per master */
1965 +struct ip_ct_rsh_master {
1968 +#endif /* _IP_CONNTRACK_RSH_H */
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
1974 +#ifndef _IP_CONNTRACK_TALK_H
1975 +#define _IP_CONNTRACK_TALK_H
1976 +/* TALK tracking. */
1979 +#include <linux/in.h>
1980 +#include <linux/netfilter_ipv4/lockhelp.h>
1982 +/* Protects talk part of conntracks */
1983 +DECLARE_LOCK_EXTERN(ip_talk_lock);
1987 +#define TALK_PORT 517
1988 +#define NTALK_PORT 518
1990 +/* talk structures and constants from <protocols/talkd.h> */
1993 + * 4.3BSD struct sockaddr
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;
2003 +#define TALK_OLD_NSIZE 9
2004 +#define TALK_NSIZE 12
2005 +#define TALK_TTY_NSIZE 16
2008 + * Client->server request message formats.
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 */
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 */
2023 + u_char vers; /* protocol version */
2024 + u_char type; /* request type, see below */
2025 + u_char answer; /* not used */
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 */
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 */
2051 + * Server->client response message formats.
2053 +struct talk_response {
2054 + u_char type; /* type of request message, see below */
2055 + u_char answer; /* response to request message, see below */
2057 + u_int32_t id_num; /* message id */
2058 + struct talk_addr addr; /* address for establishing conversation */
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 */
2066 + u_int32_t id_num; /* message id */
2067 + struct talk_addr addr; /* address for establishing conversation */
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 */
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)
2085 +#define TALK_VERSION 0 /* protocol versions */
2086 +#define NTALK_VERSION 1
2087 +#define NTALK2_VERSION 2
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 */
2095 +#define REPLY_QUERY 4 /* request reply data from local daemon */
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 */
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 */
2113 +/* We don't really need much for talk */
2114 +struct ip_ct_talk_expect
2116 + /* Port that was to be used */
2120 +/* This structure exists only once per master */
2121 +struct ip_ct_talk_master
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
2130 +#ifndef _IP_CT_TFTP
2131 +#define _IP_CT_TFTP
2133 +#define TFTP_PORT 69
2139 +#define TFTP_OPCODE_READ 1
2140 +#define TFTP_OPCODE_WRITE 2
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
2147 union ip_conntrack_manip_proto
2149 /* Add other protocols here. */
2164 /* The manipulable part of the tuple. */
2168 /* Add other protocols here. */
2176 u_int8_t type, code;
2179 + u_int16_t protocol;
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) \
2194 + (tuple)->src.u.all = 0; \
2195 + (tuple)->dst.u.all = 0; \
2198 enum ip_conntrack_dir
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))
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))
2219 #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
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
2225 +/* IPv4 macros for the internal logging interface. */
2226 +#ifndef __IP_LOGGING_H
2227 +#define __IP_LOGGING_H
2230 +#include <linux/socket.h>
2231 +#include <linux/netfilter_logging.h>
2233 +#define nf_log_ip_packet(pskb,hooknum,in,out,fmt,args...) \
2234 + nf_log_packet(AF_INET,pskb,hooknum,in,out,fmt,##args)
2236 +#define nf_log_ip(pfh,len,fmt,args...) \
2237 + nf_log(AF_INET,pfh,len,fmt,##args)
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)
2242 +#endif /*__KERNEL__*/
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
2249 unsigned int match_len,
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,
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
2266 +/* PPTP constants and structs */
2267 +#ifndef _NAT_PPTP_H
2268 +#define _NAT_PPTP_H
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 */
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
2281 const struct net_device *out,
2282 struct ip_conntrack *ct,
2283 struct ip_nat_info *info);
2285 +extern unsigned int
2286 +alloc_null_binding(struct ip_conntrack *conntrack,
2287 + struct ip_nat_info *info,
2288 + unsigned int hooknum);
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
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. */
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. */
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 +/***************************************************************************/
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!
2319 + * Comes with its own certificate of authenticity, valid anywhere in the
2322 + * Rusty, 19.4.2000
2324 +#define SO_IP_POOL 81
2326 +typedef int ip_pool_t; /* pool index */
2327 +#define IP_POOL_NONE ((ip_pool_t)-1)
2329 +struct ip_pool_request {
2336 +/* NOTE: I deliberately break the first cut ippool utility. Nobody uses it. */
2338 +#define IP_POOL_BAD001 0x00000010
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 */
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);
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
2363 +#ifndef _IPT_CLASSIFY_H
2364 +#define _IPT_CLASSIFY_H
2366 +struct ipt_classify_target_info {
2367 + u_int32_t priority;
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
2375 +#ifndef _IPT_CONNMARK_H_target
2376 +#define _IPT_CONNMARK_H_target
2379 + IPT_CONNMARK_SET = 0,
2380 + IPT_CONNMARK_SAVE,
2381 + IPT_CONNMARK_RESTORE
2384 +struct ipt_connmark_target_info {
2385 + unsigned long mark;
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
2397 +struct ipt_imq_info {
2398 + unsigned int todev; /* target imq device */
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
2406 +#ifndef _IPT_IPMARK_H_target
2407 +#define _IPT_IPMARK_H_target
2409 +struct ipt_ipmark_target_info {
2410 + unsigned long andmask;
2411 + unsigned long ormask;
2412 + unsigned int addr;
2415 +#define IPT_IPMARK_SRC 0
2416 +#define IPT_IPMARK_DST 1
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
2423 +#ifndef _IPT_FWMON_H
2424 +#define _IPT_FWMON_H
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
2431 +#define USE_MARK 0x00000001
2432 +#define USE_DROP 0x00000002
2433 +#define USE_SIZE 0x00000004
2437 + unsigned int flags;
2438 + unsigned int mark;
2439 + unsigned int size;
2445 + unsigned int mark;
2446 + char iface[IFNAMSIZ];
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
2455 IPT_ICMP_NET_PROHIBITED,
2456 IPT_ICMP_HOST_PROHIBITED,
2459 + IPT_ICMP_ADMIN_PROHIBITED
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 */
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
2473 +/* Header file for iptables ipt_ROUTE target
2475 + * (C) 2002 by Cédric de Launois <delaunois@info.ucl.ac.be>
2477 + * This software is distributed under GNU GPL v2, 1991
2479 +#ifndef _IPT_ROUTE_H_target
2480 +#define _IPT_ROUTE_H_target
2482 +#define IPT_ROUTE_IFNAMSIZ 16
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 */
2491 +/* Values for "flags" field */
2492 +#define IPT_ROUTE_CONTINUE 0x01
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
2499 +#ifndef _IPT_SAME_H
2500 +#define _IPT_SAME_H
2502 +#define IPT_SAME_MAX_RANGE 10
2504 +#define IPT_SAME_NODST 0x01
2506 +struct ipt_same_info
2508 + unsigned char info;
2509 + u_int32_t rangesize;
2511 + u_int32_t *iparray;
2513 + /* hangs off end. */
2514 + struct ip_nat_range range[IPT_SAME_MAX_RANGE];
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
2522 +#ifndef _IPT_TCPLAG_H
2523 +#define _IPT_TCPLAG_H
2527 + unsigned char level;
2528 + unsigned char prefix[ 15 ];
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
2536 +/* TTL modification module for IP tables
2537 + * (C) 2000 by Harald Welte <laforge@gnumonks.org> */
2548 +#define IPT_TTL_MAXMODE IPT_TTL_DEC
2550 +struct ipt_TTL_info {
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
2561 #define NETLINK_NFLOG 5
2564 +#define ULOG_DEFAULT_NLGROUP 1
2565 +#define ULOG_DEFAULT_QTHRESHOLD 1
2567 #define ULOG_MAC_LEN 80
2568 #define ULOG_PREFIX_LEN 32
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
2577 +struct ipt_XOR_info {
2579 + u_int8_t block_size;
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
2587 +#ifndef _IPT_ADDRTYPE_H
2588 +#define _IPT_ADDRTYPE_H
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;
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
2602 +#ifndef __IPT_CONDITION_MATCH__
2603 +#define __IPT_CONDITION_MATCH__
2605 +#define CONDITION_NAME_LEN 32
2607 +struct condition_info {
2608 + char name[CONDITION_NAME_LEN];
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
2617 +#ifndef _IPT_CONNLIMIT_H
2618 +#define _IPT_CONNLIMIT_H
2620 +struct ipt_connlimit_data;
2622 +struct ipt_connlimit_info {
2626 + struct ipt_connlimit_data *data;
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
2633 +#ifndef _IPT_CONNMARK_H
2634 +#define _IPT_CONNMARK_H
2636 +struct ipt_connmark_info {
2637 + unsigned long mark, mask;
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
2646 #define IPT_CONNTRACK_STATE_SNAT (1 << (IP_CT_NUMBER + 1))
2647 #define IPT_CONNTRACK_STATE_DNAT (1 << (IP_CT_NUMBER + 2))
2649 +#define IPT_CONNTRACK_STATE_UNTRACKED (1 << (IP_CT_IS_REPLY+3))
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
2658 +#ifndef _IPT_FUZZY_H
2659 +#define _IPT_FUZZY_H
2661 +#include <linux/param.h>
2662 +#include <linux/types.h>
2664 +#define MAXFUZZYRATE 10000000
2665 +#define MINFUZZYRATE 3
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;
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
2683 +#ifndef _IPT_IPRANGE_H
2684 +#define _IPT_IPRANGE_H
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 */
2691 +struct ipt_iprange {
2692 + /* Inclusive: network order. */
2693 + u_int32_t min_ip, max_ip;
2696 +struct ipt_iprange_info
2698 + struct ipt_iprange src;
2699 + struct ipt_iprange dst;
2701 + /* Flags from above */
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
2710 +#ifndef __ipt_ipv4options_h_included__
2711 +#define __ipt_ipv4options_h_included__
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 */
2725 +struct ipt_ipv4options_info {
2726 + u_int16_t options;
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
2739 + IPT_MARK_BIT_OP_NONE,
2740 + IPT_MARK_BIT_OP_AND,
2741 + IPT_MARK_BIT_OP_OR
2744 struct ipt_mark_info {
2745 unsigned long mark, mask;
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
2755 +#ifndef _IPT_MPORT_H
2756 +#define _IPT_MPORT_H
2757 +#include <linux/netfilter_ipv4/ip_tables.h>
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)
2763 +#define IPT_MULTI_PORTS 15
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[] */
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 */
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
2786 +#include <linux/param.h>
2787 +#include <linux/types.h>
2789 +#ifndef IPT_NTH_NUM_COUNTERS
2790 +#define IPT_NTH_NUM_COUNTERS 16
2793 +struct ipt_nth_info {
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
2809 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
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.
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.
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
2830 +#define MAXGENRELEN 32
2831 +#define MAXDETLEN 64
2833 +#include <linux/list.h>
2835 +struct ipt_osf_info
2837 + char genre[MAXGENRELEN];
2839 + int invert; /* UNSUPPORTED */
2845 + unsigned long val;
2848 +/* This struct represents IANA options
2849 + * http://www.iana.org/assignments/tcp-parameters
2853 + unsigned char kind;
2854 + unsigned char length;
2862 + struct list_head flist;
2863 + struct osf_wc wss;
2864 + unsigned char ttl;
2867 + char genre[MAXGENRELEN];
2869 + /* Not needed, but for consistency with original table from Michal Zalewski */
2870 + char details[MAXDETLEN];
2873 + struct osf_opt opt[MAX_IPOPTLEN]; /* In case it is all NOP or EOL */
2877 +/* Defines for IANA option kinds */
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 */
2892 +static struct osf_opt IANA_opts[] =
2899 + {5, 1 ,}, /* SACK length is not defined */
2905 + {11, 1,}, /* CC: Suppose 1 */
2906 + {12, 1,}, /* the same */
2907 + {13, 1,}, /* and here too */
2909 + {15, 1,}, /* TCP Alternate Checksum Data. Length is not defined */
2923 +#endif /* __KERNEL__ */
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
2930 +#ifndef _IPT_POOL_H
2931 +#define _IPT_POOL_H
2933 +#include <linux/netfilter_ipv4/ip_pool.h>
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
2947 +struct ipt_pool_info
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
2962 +#include <linux/param.h>
2963 +#include <linux/types.h>
2966 + * High port numbers have a lower weight to reduce the frequency of false
2967 + * positives, such as from passive mode FTP transfers.
2969 +#define PORT_WEIGHT_PRIV 3
2970 +#define PORT_WEIGHT_HIGH 1
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.
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)
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.
2986 +#define LIST_SIZE 0x100
2988 +#define HASH_SIZE (1 << HASH_LOG)
2989 +#define HASH_MAX 0x10
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;
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
3003 +#ifndef _IPT_QUOTA_H
3004 +#define _IPT_QUOTA_H
3006 +/* print debug info in both kernel/netfilter module & iptable library */
3007 +//#define DEBUG_IPT_QUOTA
3009 +struct ipt_quota_info {
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
3018 +#ifndef _IPT_RAND_H
3019 +#define _IPT_RAND_H
3021 +#include <linux/param.h>
3022 +#include <linux/types.h>
3024 +struct ipt_rand_info {
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
3033 +#ifndef _IPT_REALM_H
3034 +#define _IPT_REALM_H
3036 +struct ipt_realm_info {
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
3046 +#ifndef _IPT_RECENT_H
3047 +#define _IPT_RECENT_H
3049 +#define RECENT_NAME "ipt_recent"
3050 +#define RECENT_VER "v0.3.1"
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
3058 +#define IPT_RECENT_SOURCE 0
3059 +#define IPT_RECENT_DEST 1
3061 +#define IPT_RECENT_NAME_LEN 200
3063 +struct ipt_recent_info {
3064 + u_int32_t seconds;
3065 + u_int32_t hit_count;
3066 + u_int8_t check_set;
3068 + char name[IPT_RECENT_NAME_LEN];
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
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
3082 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
3083 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
3089 + * ipt_rpc.h.c,v 2.2 2003/01/12 18:30:00
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.
3101 +struct ipt_rpc_data;
3103 +struct ipt_rpc_info {
3106 + const char c_procs[1408];
3108 + struct ipt_rpc_data *data;
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
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))
3121 struct ipt_state_info
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
3127 +#ifndef _IPT_STRING_H
3128 +#define _IPT_STRING_H
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
3136 +#define BM_MAX_NLEN 256
3137 +#define BM_MAX_HLEN 1024
3139 +typedef char *(*proc_ipt_search) (char *, char *, int, int);
3141 +struct ipt_string_info {
3142 + char string[BM_MAX_NLEN];
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
3152 +#ifndef __ipt_time_h_included__
3153 +#define __ipt_time_h_included__
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. */
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
3171 +#include <linux/netfilter_ipv4/ip_tables.h>
3181 +struct ipt_u32_location_element
3186 +struct ipt_u32_value_element
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
3197 + struct ipt_u32_location_element location[U32MAXSIZE+1];
3199 + struct ipt_u32_value_element value[U32MAXSIZE+1];
3205 + struct ipt_u32_test tests[U32MAXSIZE+1];
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
3216 +/* Just like LIST_FIND but we search backwards */
3217 +#define LIST_FIND_B(head, cmpfn, type, args...) \
3219 + const struct list_head *__i = (head); \
3221 + ASSERT_READ_LOCK(head); \
3223 + __i = __i->prev; \
3224 + if (__i == (head)) { \
3228 + } while (!cmpfn((const type)__i , ## args)); \
3233 __list_cmp_same(const void *p1, const void *p2) { return p1 == p2; }
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
3239 printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l); \
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); \
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); \
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); \
3269 #define READ_UNLOCK(lk) \
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
3280 +/* IPv6 macros for the nternal logging interface. */
3281 +#ifndef __IP6_LOGGING_H
3282 +#define __IP6_LOGGING_H
3285 +#include <linux/socket.h>
3286 +#include <linux/netfilter_logging.h>
3288 +#define nf_log_ip6_packet(pskb,hooknum,in,out,fmt,args...) \
3289 + nf_log_packet(AF_INET6,pskb,hooknum,in,out,fmt,##args)
3291 +#define nf_log_ip6(pfh,len,fmt,args...) \
3292 + nf_log(AF_INET6,pfh,len,fmt,##args)
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)
3297 +#endif /*__KERNEL__*/
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
3304 struct ip6t_table *table,
3307 +/* Check for an extension */
3308 +extern int ip6t_ext_hdr(u8 nexthdr);
3310 #define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
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
3317 +/* Hop Limit modification module for ip6tables
3318 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3319 + * Based on HW's TTL module */
3330 +#define IP6T_HL_MAXMODE IP6T_HL_DEC
3332 +struct ip6t_HL_info {
3334 + u_int8_t hop_limit;
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
3343 +#ifndef _IP6T_IMQ_H
3344 +#define _IP6T_IMQ_H
3346 +struct ip6t_imq_info {
3347 + unsigned int todev; /* target imq device */
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
3355 #define _IP6T_REJECT_H
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,
3372 struct ip6t_reject_info {
3373 enum ip6t_reject_with with; /* reject type */
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
3382 +/* Header file for iptables ip6t_ROUTE target
3384 + * (C) 2003 by Cédric de Launois <delaunois@info.ucl.ac.be>
3386 + * This software is distributed under GNU GPL v2, 1991
3388 +#ifndef _IPT_ROUTE_H_target
3389 +#define _IPT_ROUTE_H_target
3391 +#define IP6T_ROUTE_IFNAMSIZ 16
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 */
3400 +/* Values for "flags" field */
3401 +#define IP6T_ROUTE_CONTINUE 0x01
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
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 */
3419 +#define IP6T_AH_SPI 0x01
3420 +#define IP6T_AH_LEN 0x02
3421 +#define IP6T_AH_RES 0x04
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. */
3428 +#define MASK_HOPOPTS 128
3429 +#define MASK_DSTOPTS 64
3430 +#define MASK_ROUTING 32
3431 +#define MASK_FRAGMENT 16
3434 +#define MASK_NONE 2
3435 +#define MASK_PROTO 1
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
3442 +#ifndef __IP6T_CONDITION_MATCH__
3443 +#define __IP6T_CONDITION_MATCH__
3445 +#define CONDITION6_NAME_LEN 32
3447 +struct condition6_info {
3448 + char name[CONDITION6_NAME_LEN];
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
3457 +#ifndef _IP6T_ESP_H
3458 +#define _IP6T_ESP_H
3462 + u_int32_t spis[2]; /* Security Parameter Index */
3463 + u_int8_t invflags; /* Inverse flags */
3466 +#define MASK_HOPOPTS 128
3467 +#define MASK_DSTOPTS 64
3468 +#define MASK_ROUTING 32
3469 +#define MASK_FRAGMENT 16
3472 +#define MASK_NONE 2
3473 +#define MASK_PROTO 1
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. */
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
3484 +#ifndef _IP6T_FRAG_H
3485 +#define _IP6T_FRAG_H
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 */
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
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. */
3507 +#define MASK_HOPOPTS 128
3508 +#define MASK_DSTOPTS 64
3509 +#define MASK_ROUTING 32
3510 +#define MASK_FRAGMENT 16
3513 +#define MASK_NONE 2
3514 +#define MASK_PROTO 1
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
3521 +#ifndef _IP6T_FUZZY_H
3522 +#define _IP6T_FUZZY_H
3524 +#include <linux/param.h>
3525 +#include <linux/types.h>
3527 +#define MAXFUZZYRATE 10000000
3528 +#define MINFUZZYRATE 3
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;
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
3546 +/* ip6tables module for matching the Hop Limit value
3547 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
3548 + * Based on HW's ttl module */
3554 + IP6T_HL_EQ = 0, /* equals */
3555 + IP6T_HL_NE, /* not equals */
3556 + IP6T_HL_LT, /* less than */
3557 + IP6T_HL_GT, /* greater than */
3561 +struct ip6t_hl_info {
3563 + u_int8_t hop_limit;
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
3572 +/* ipv6header match - matches IPv6 packets based
3573 +on whether they contain certain headers */
3575 +/* Original idea: Brad Chapman
3576 + * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
3579 +#ifndef __IPV6HEADER_H
3580 +#define __IPV6HEADER_H
3582 +struct ip6t_ipv6header_info
3584 + u_int8_t matchflags;
3585 + u_int8_t invflags;
3586 + u_int8_t modeflag;
3589 +#define MASK_HOPOPTS 128
3590 +#define MASK_DSTOPTS 64
3591 +#define MASK_ROUTING 32
3592 +#define MASK_FRAGMENT 16
3595 +#define MASK_NONE 2
3596 +#define MASK_PROTO 1
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
3603 +#ifndef _IP6T_NTH_H
3604 +#define _IP6T_NTH_H
3606 +#include <linux/param.h>
3607 +#include <linux/types.h>
3609 +#ifndef IP6T_NTH_NUM_COUNTERS
3610 +#define IP6T_NTH_NUM_COUNTERS 16
3613 +struct ip6t_nth_info {
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
3626 +#ifndef _IP6T_OPTS_H
3627 +#define _IP6T_OPTS_H
3629 +#define IP6T_OPTS_OPTSNR 16
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 */
3640 +#define IP6T_OPTS_LEN 0x01
3641 +#define IP6T_OPTS_OPTS 0x02
3642 +#define IP6T_OPTS_NSTRICT 0x04
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. */
3648 +#define MASK_HOPOPTS 128
3649 +#define MASK_DSTOPTS 64
3650 +#define MASK_ROUTING 32
3651 +#define MASK_FRAGMENT 16
3654 +#define MASK_NONE 2
3655 +#define MASK_PROTO 1
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
3662 #define IP6T_OWNER_GID 0x02
3663 #define IP6T_OWNER_PID 0x04
3664 #define IP6T_OWNER_SID 0x08
3665 +#define IP6T_OWNER_COMM 0x10
3667 struct ip6t_owner_info {
3673 u_int8_t match, invert; /* flags */
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
3680 +#ifndef _IP6T_RAND_H
3681 +#define _IP6T_RAND_H
3683 +#include <linux/param.h>
3684 +#include <linux/types.h>
3686 +struct ip6t_rand_info {
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
3698 +/*#include <linux/in6.h>*/
3700 +#define IP6T_RT_HOPS 16
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 */
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
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. */
3727 +#define MASK_HOPOPTS 128
3728 +#define MASK_DSTOPTS 64
3729 +#define MASK_ROUTING 32
3730 +#define MASK_FRAGMENT 16
3733 +#define MASK_NONE 2
3734 +#define MASK_PROTO 1
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
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
3747 +#include <asm/atomic.h>
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);
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);
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__*/
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
3778 +#ifndef _NFNETLINK_H
3779 +#define _NFNETLINK_H
3780 +#include <linux/types.h>
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.
3791 + unsigned short nfa_len;
3792 + unsigned short nfa_type;
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))
3806 +/* General form of address family dependent message.
3809 + unsigned char nfgen_family;
3814 + unsigned char iptgen_family;
3815 + char iptgen_table[IPT_TABLE_MAXNAMELEN];
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;
3825 +enum iptattr_type_t
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
3838 + char name[IPT_FUNCTION_MAXNAMELEN];
3839 + unsigned char data[0];
3842 +#define NFM_IPTA(n) ((struct nfattr *)(((char *)(n)) \
3843 + + NLMSG_ALIGN(sizeof(struct iptmsg))))
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))
3852 +#ifndef NETLINK_NETFILTER
3853 +#define NETLINK_NETFILTER 6
3856 +/* netfilter netlink message types are split in two pieces:
3857 + * 8 bit subsystem, 8bit operation.
3860 +#define NFNL_SUBSYS_ID(x) ((x & 0xff00) >> 8)
3861 +#define NFNL_MSG_TYPE(x) (x & 0x00ff)
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,
3870 + NFNL_SUBSYS_COUNT,
3875 +#include <linux/capability.h>
3877 +struct nfnl_callback
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);
3884 +struct nfnetlink_subsystem
3886 + /* Internal use. */
3887 + struct list_head list;
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 */
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); })
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)
3907 +#define nfnl_shlock() down(&nfnl_sem)
3908 +#define nfnl_shlock_nowait() down_trylock(&nfnl_sem)
3910 +#ifndef CONFIG_NF_NETLINK
3911 +#define nfnl_shunlock() up(&nfnl_sem)
3913 +#define nfnl_shunlock() do { up(&nfnl_sem); \
3914 + if(nfnl && nfnl->receive_queue.qlen) \
3915 + nfnl->data_ready(nfnl, 0); \
3919 +extern void nfnl_lock(void);
3920 +extern void nfnl_unlock(void);
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);
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,
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
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>
3946 +/* CTNETLINK for ip_conntrack */
3948 +enum cntl_msg_types {
3949 + CTNL_MSG_NEWCONNTRACK,
3950 + CTNL_MSG_GETCONNTRACK,
3951 + CTNL_MSG_DELCONNTRACK,
3953 + CTNL_MSG_NEWEXPECT,
3954 + CTNL_MSG_GETEXPECT,
3955 + CTNL_MSG_DELEXPECT,
3956 + CTNL_MSG_CONFIRMEXPECT,
3961 +/* ctnetlink attribute types.
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 */
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] */
3984 + CTA_MAX = CTA_EXP_HELP
3987 +/* Attribute specific data structures.
3990 +#ifdef CONFIG_IP_NF_NAT_NEEDED
3991 +#include <linux/netfilter_ipv4/ip_nat.h>
3993 + unsigned int num_manips;
3994 + struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
3996 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
3999 + unsigned char num_proto; /* Protocol number IPPROTO_X */
4000 + union ip_conntrack_proto proto;
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;
4010 +/* ctnetlink multicast groups: reports any change of ctinfo,
4011 + * ctstatus, or protocol state change.
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
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
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
4030 NET_IPV4_FIB_HASH=19,
4031 + NET_IPV4_NETFILTER=20,
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,
4039 +/* /proc/sys/net/ipv4/netfilter */
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,
4057 /* /proc/sys/net/ipv6 */
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
4064 extern struct dst_entry * ip6_route_output(struct sock *sk,
4067 +extern int ip6_route_me_harder(struct sk_buff *skb);
4069 extern void ip6_route_init(void);
4070 extern void ip6_route_cleanup(void);
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
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);
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
4087 extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
4088 extern int udp_disconnect(struct sock *sk, int flags);
4090 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
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
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.
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>
4113 } queue_handler[NPROTO];
4116 + * nf_register_hook - Register with a netfilter hook
4117 + * @reg: Hook operations to be registered
4119 int nf_register_hook(struct nf_hook_ops *reg)
4121 struct list_head *i;
4127 + * nf_unregister_hook - Unregister from a netfilter hook
4128 + * @reg: hook operations to be unregistered
4130 void nf_unregister_hook(struct nf_hook_ops *reg)
4132 br_write_lock_bh(BR_NETPROTO_LOCK);
4133 @@ -373,6 +384,18 @@
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
4143 + * This function registers a queue handler with netfilter. There can only
4144 + * be one queue handler for every protocol family.
4146 + * A queue handler _must_ reinject every packet via nf_reinject, no
4149 int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
4152 @@ -390,7 +413,12 @@
4156 -/* The caller must flush their queue before this */
4158 + * nf_unregister_queue_handler - Unregister queue handler from netfilter
4159 + * @pf: protocol family
4161 + * The caller must flush their queue before unregistering
4163 int nf_unregister_queue_handler(int pf)
4165 br_write_lock_bh(BR_NETPROTO_LOCK);
4166 @@ -502,6 +530,15 @@
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
4176 + * This is the function called by a queue handler to reinject a
4179 void nf_reinject(struct sk_buff *skb, struct nf_info *info,
4180 unsigned int verdict)
4182 @@ -563,67 +600,134 @@
4184 struct iphdr *iph = (*pskb)->nh.iph;
4186 - struct rt_key key = { dst:iph->daddr,
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
4194 - struct net_device *dev_src = NULL;
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)))
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;
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.
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
4225 + key.fwmark = (*pskb)->nfmark;
4230 + if (ip_route_output_key(&rt, &key) != 0)
4233 - /* Drop old route. */
4234 - dst_release((*pskb)->dst);
4236 - (*pskb)->dst = &rt->u.dst;
4237 + /* Drop old route. */
4238 + dst_release((*pskb)->dst);
4239 + (*pskb)->dst = &rt->u.dst;
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)
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);
4253 + dst_release(&rt->u.dst);
4254 + dst_release(odst);
4257 + if ((*pskb)->dst->error)
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;
4266 - nskb = skb_realloc_headroom(*pskb,
4267 - (*pskb)->dst->dev->hard_header_len);
4272 + nskb = skb_realloc_headroom(*pskb, hh_len);
4276 skb_set_owner_w(nskb, (*pskb)->sk);
4288 #endif /*CONFIG_INET*/
4290 +/* Internal logging interface, which relies on the real
4291 + LOG target modules */
4293 +#define NF_LOG_PREFIXLEN 128
4295 +static struct nf_logging_t nf_logging[NPROTO] = {};
4296 +static int reported = 0;
4298 +void nf_log_register(int pf, const struct nf_logging_t *logging)
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;
4305 + br_write_unlock_bh(BR_NETPROTO_LOCK);
4308 +void nf_log_unregister(int pf, const struct nf_logging_t *logging)
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;
4315 + br_write_unlock_bh(BR_NETPROTO_LOCK);
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, ...)
4326 + char prefix[NF_LOG_PREFIXLEN];
4328 + if (nf_logging[pf].nf_log_packet) {
4329 + va_start(args, fmt);
4330 + vsnprintf(prefix, sizeof(prefix), fmt, 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");
4340 +void nf_log(int pf,
4341 + char *pfh, size_t len,
4342 + const char *fmt, ...)
4345 + char prefix[NF_LOG_PREFIXLEN];
4347 + if (nf_logging[pf].nf_log) {
4348 + va_start(args, fmt);
4349 + vsnprintf(prefix, sizeof(prefix), fmt, 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");
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
4366 mainmenu_option next_comment
4367 comment ' IP: Netfilter Configuration'
4369 +tristate 'Netfilter netlink interface' CONFIG_IP_NF_NETLINK
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
4376 + dep_tristate ' Connection tracking netlink interface' CONFIG_IP_NF_NETLINK_CONNTRACK $CONFIG_IP_NF_CONNTRACK
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
4394 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
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
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
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
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
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
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
4434 dep_tristate ' DSCP match support' CONFIG_IP_NF_MATCH_DSCP $CONFIG_IP_NF_IPTABLES
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
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
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
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
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
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
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
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
4490 + if [ "$CONFIG_IP_NF_TALK" = "y" ]; then
4491 + define_tristate CONFIG_IP_NF_NAT_TALK $CONFIG_IP_NF_NAT
4494 + if [ "$CONFIG_IP_NF_H323" = "m" ]; then
4495 + define_tristate CONFIG_IP_NF_NAT_H323 m
4497 + if [ "$CONFIG_IP_NF_H323" = "y" ]; then
4498 + define_tristate CONFIG_IP_NF_NAT_H323 $CONFIG_IP_NF_NAT
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
4506 + if [ "$CONFIG_IP_NF_AMANDA" = "y" ]; then
4507 + define_tristate CONFIG_IP_NF_NAT_AMANDA $CONFIG_IP_NF_NAT
4510 + if [ "$CONFIG_IP_NF_PPTP" = "m" ]; then
4511 + define_tristate CONFIG_IP_NF_NAT_PPTP m
4513 + if [ "$CONFIG_IP_NF_PPTP" = "y" ]; then
4514 + define_tristate CONFIG_IP_NF_NAT_PPTP $CONFIG_IP_NF_NAT
4517 + if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "m" ]; then
4518 + define_tristate CONFIG_IP_NF_NAT_PROTO_GRE m
4520 + if [ "$CONFIG_IP_NF_CT_PROTO_GRE" = "y" ]; then
4521 + define_tristate CONFIG_IP_NF_NAT_PROTO_GRE $CONFIG_IP_NF_NAT
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
4528 define_tristate CONFIG_IP_NF_NAT_IRC $CONFIG_IP_NF_NAT
4531 + if [ "$CONFIG_IP_NF_QUAKE3" = "m" ]; then
4532 + define_tristate CONFIG_IP_NF_NAT_QUAKE3 m
4534 + if [ "$CONFIG_IP_NF_QUAKE3" = "y" ]; then
4535 + define_tristate CONFIG_IP_NF_NAT_QUAKE3 $CONFIG_IP_NF_NAT
4538 + if [ "$CONFIG_IP_NF_MMS" = "m" ]; then
4539 + define_tristate CONFIG_IP_NF_NAT_MMS m
4541 + if [ "$CONFIG_IP_NF_MMS" = "y" ]; then
4542 + define_tristate CONFIG_IP_NF_NAT_MMS $CONFIG_IP_NF_NAT
4545 + if [ "$CONFIG_IP_NF_CUSEEME" = "m" ]; then
4546 + define_tristate CONFIG_IP_NF_NAT_CUSEEME m
4548 + if [ "$CONFIG_IP_NF_CUSEEME" = "y" ]; then
4549 + define_tristate CONFIG_IP_NF_NAT_CUSEEME $CONFIG_IP_NF_NAT
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
4556 define_tristate CONFIG_IP_NF_NAT_FTP $CONFIG_IP_NF_NAT
4559 + if [ "$CONFIG_IP_NF_TFTP" = "m" ]; then
4560 + define_tristate CONFIG_IP_NF_NAT_TFTP m
4562 + if [ "$CONFIG_IP_NF_TFTP" = "y" ]; then
4563 + define_tristate CONFIG_IP_NF_NAT_TFTP $CONFIG_IP_NF_NAT
4570 dep_tristate ' DSCP target support' CONFIG_IP_NF_TARGET_DSCP $CONFIG_IP_NF_MANGLE
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
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
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
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
4590 if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then
4591 dep_tristate ' ARP packet filtering' CONFIG_IP_NF_ARPFILTER $CONFIG_IP_NF_ARPTABLES
4593 +if [ "$CONFIG_IP_NF_ARPTABLES" != "n" ]; then
4594 + dep_tristate ' ARP payload mangling' CONFIG_IP_NF_ARP_MANGLE $CONFIG_IP_NF_ARPTABLES
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
4603 ipfwadm-objs := $(ip_nf_compat-objs) ipfwadm_core.o
4604 ipchains-objs := $(ip_nf_compat-objs) ipchains_core.o
4606 +# netfilter netlink interface
4607 +obj-$(CONFIG_IP_NF_NETLINK) += nfnetlink.o
4608 +ifdef CONFIG_IP_NF_NETLINK
4609 + export-objs += nfnetlink.o
4612 +# nfnetlink modules
4613 +obj-$(CONFIG_IP_NF_NETLINK_CONNTRACK) += nfnetlink_conntrack.o
4615 # connection tracking
4616 obj-$(CONFIG_IP_NF_CONNTRACK) += ip_conntrack.o
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
4623 +obj-$(CONFIG_IP_NF_NAT_TALK) += ip_nat_talk.o
4627 +obj-$(CONFIG_IP_NF_H323) += ip_conntrack_h323.o
4628 +ifdef CONFIG_IP_NF_H323
4629 + export-objs += ip_conntrack_h323.o
4631 +obj-$(CONFIG_IP_NF_NAT_H323) += ip_nat_h323.o
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
4640 +# NAT protocol helpers
4641 +obj-$(CONFIG_IP_NF_NAT_PROTO_GRE) += ip_nat_proto_gre.o
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
4648 +obj-$(CONFIG_IP_NF_PPTP) += ip_conntrack_pptp.o
4649 +ifdef CONFIG_IP_NF_NAT_PPTP
4650 + export-objs += ip_conntrack_pptp.o
4652 +obj-$(CONFIG_IP_NF_MMS) += ip_conntrack_mms.o
4653 +ifdef CONFIG_IP_NF_MMS
4654 + export-objs += ip_conntrack_mms.o
4656 +obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
4657 +ifdef CONFIG_IP_NF_AMANDA
4658 + export-objs += ip_conntrack_amanda.o
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
4666 +obj-$(CONFIG_IP_NF_EGG) += ip_conntrack_egg.o
4668 +ifdef CONFIG_IP_NF_FTP
4669 export-objs += ip_conntrack_ftp.o
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
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
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
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
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
4708 obj-$(CONFIG_IP_NF_MATCH_PKTTYPE) += ipt_pkttype.o
4709 obj-$(CONFIG_IP_NF_MATCH_MULTIPORT) += ipt_multiport.o
4711 +obj-$(CONFIG_IP_NF_MATCH_MPORT) += ipt_mport.o
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
4717 +obj-$(CONFIG_IP_NF_MATCH_TIME) += ipt_time.o
4720 +obj-$(CONFIG_IP_NF_MATCH_RANDOM) += ipt_random.o
4722 +obj-$(CONFIG_IP_NF_MATCH_PSD) += ipt_psd.o
4724 +obj-$(CONFIG_IP_NF_MATCH_OSF) += ipt_osf.o
4727 +obj-$(CONFIG_IP_NF_MATCH_NTH) += ipt_nth.o
4729 +obj-$(CONFIG_IP_NF_MATCH_IPV4OPTIONS) += ipt_ipv4options.o
4732 +obj-$(CONFIG_IP_NF_MATCH_FUZZY) += ipt_fuzzy.o
4734 +obj-$(CONFIG_IP_NF_MATCH_RECENT) += ipt_recent.o
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
4740 obj-$(CONFIG_IP_NF_MATCH_LENGTH) += ipt_length.o
4742 +obj-$(CONFIG_IP_NF_MATCH_U32) += ipt_u32.o
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
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
4780 +obj-$(CONFIG_IP_NF_TARGET_NETLINK) += ipt_NETLINK.o
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
4788 # generic ARP tables
4789 obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o
4790 +obj-$(CONFIG_IP_NF_ARP_MANGLE) += arpt_mangle.o
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
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);
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
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>
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)
4818 + const struct arpt_mangle *mangle = targinfo;
4819 + struct arphdr *arp;
4820 + unsigned char *arpptr;
4823 + if (skb_shared(*pskb) || skb_cloned(*pskb)) {
4824 + struct sk_buff *nskb;
4826 + nskb = skb_copy(*pskb, GFP_ATOMIC);
4830 + skb_set_owner_w(nskb, (*pskb)->sk);
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))
4844 + memcpy(arpptr, mangle->src_devaddr, hln);
4847 + if (mangle->flags & ARPT_MANGLE_SIP) {
4848 + if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
4849 + (arpptr + pln > (**pskb).tail))
4851 + memcpy(arpptr, &mangle->u_s.src_ip, pln);
4854 + if (mangle->flags & ARPT_MANGLE_TDEV) {
4855 + if (ARPT_DEV_ADDR_LEN_MAX < hln ||
4856 + (arpptr + hln > (**pskb).tail))
4858 + memcpy(arpptr, mangle->tgt_devaddr, hln);
4861 + if (mangle->flags & ARPT_MANGLE_TIP) {
4862 + if (ARPT_MANGLE_ADDR_LEN_MAX < pln ||
4863 + (arpptr + pln > (**pskb).tail))
4865 + memcpy(arpptr, &mangle->u_t.tgt_ip, pln);
4867 + return mangle->target;
4871 +checkentry(const char *tablename, const struct arpt_entry *e, void *targinfo,
4872 + unsigned int targinfosize, unsigned int hook_mask)
4874 + const struct arpt_mangle *mangle = targinfo;
4876 + if (mangle->flags & ~ARPT_MANGLE_MASK ||
4877 + !(mangle->flags & ARPT_MANGLE_MASK))
4880 + if (mangle->target != NF_DROP && mangle->target != NF_ACCEPT &&
4881 + mangle->target != ARPT_CONTINUE)
4886 +static struct arpt_target arpt_mangle_reg
4890 + .checkentry = checkentry,
4891 + .me = THIS_MODULE,
4894 +static int __init init(void)
4896 + if (arpt_register_target(&arpt_mangle_reg))
4902 +static void __exit fini(void)
4904 + arpt_unregister_target(&arpt_mangle_reg);
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
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
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.
4923 + * Module load syntax:
4924 + * insmod ip_conntrack_amanda.o [master_timeout=n]
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
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>
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>
4944 +static unsigned int master_timeout = 300;
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");
4952 +DECLARE_LOCK(ip_amanda_lock);
4953 +struct module *ip_conntrack_amanda = THIS_MODULE;
4955 +#define MAXMATCHLEN 6
4956 +struct conn conns[NUM_MSGS] = {
4963 +#define DEBUGP printk
4965 +#define DEBUGP(format, args...)
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)
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;
4983 + /* Can't track connections formed before we registered */
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);
4991 + /* If packet is coming from Amanda server */
4992 + if (dir == IP_CT_DIR_ORIGINAL)
4995 + /* Not whole UDP header? */
4996 + if (udplen < sizeof(struct udphdr)) {
4997 + printk("ip_conntrack_amanda_help: udplen = %u\n",
4998 + (unsigned)udplen);
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 "
5007 + udph, udplen, NIPQUAD(iph->saddr),
5008 + NIPQUAD(iph->daddr));
5012 + /* Search for the CONNECT string */
5013 + while (data < data_limit) {
5014 + if (!memcmp(data, "CONNECT ", 8)) {
5019 + if (memcmp(data, "CONNECT ", 8))
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));
5027 + while (*data != 0x0a && data < data_limit) {
5031 + for (i = 0; i < NUM_MSGS; i++) {
5032 + if (!memcmp(data, conns[i].match,
5033 + conns[i].matchlen)) {
5036 + struct ip_conntrack_expect expect;
5037 + struct ip_ct_amanda_expect
5038 + *exp_amanda_info =
5039 + &expect.help.exp_amanda_info;
5041 + memset(&expect, 0, sizeof(expect));
5043 + data += conns[i].matchlen;
5044 + /* this is not really tcp, but let's steal an
5045 + * idea from a tcp stream helper :-)
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);
5052 + exp_amanda_info->port =
5053 + simple_strtoul(data, &data, 10);
5054 + exp_amanda_info->len = data - portchr;
5056 + /* eat whitespace */
5057 + while (*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);
5064 + LOCK_BH(&ip_amanda_lock);
5066 + expect.tuple = ((struct ip_conntrack_tuple)
5067 + { { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip,
5069 + { ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip,
5070 + { htons(exp_amanda_info->port) },
5072 + expect.mask = ((struct ip_conntrack_tuple)
5074 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
5076 + expect.expectfn = NULL;
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) ==
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
5095 + * Perhaps I should use the
5096 + * exp_amanda_info instead of
5100 + UNLOCK_BH(&ip_amanda_lock);
5101 + } /* if memcmp(conns) */
5102 + } /* for .. NUM_MSGS */
5104 + } /* while (*data != 0x0a && data < data_limit) */
5109 +static struct ip_conntrack_helper amanda_helper;
5111 +static void fini(void)
5113 + DEBUGP("ip_ct_amanda: unregistering helper for port 10080\n");
5114 + ip_conntrack_helper_unregister(&amanda_helper);
5117 +static int __init init(void)
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";
5132 + DEBUGP("ip_ct_amanda: registering helper for port 10080\n");
5134 + ret = ip_conntrack_helper_register(&amanda_helper);
5137 + printk("ip_ct_amanda: ERROR registering helper\n");
5144 +EXPORT_SYMBOL(ip_amanda_lock);
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
5153 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
5155 + * (C) 2000-2003 by the netfilter core team <coreteam@netfilter.org>
5157 * 23 Apr 2001: Harald Welte <laforge@gnumonks.org>
5158 * - new API and handling of conntrack/nat helpers
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
5168 -#define __NO_VERSION__
5170 #include <linux/version.h>
5171 #include <linux/config.h>
5172 #include <linux/types.h>
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>
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;
5193 extern struct ip_conntrack_protocol ip_conntrack_generic_protocol;
5200 + * ip_ct_find_proto - Find layer 4 protocol helper for given protocol number
5201 + * @protocol: protocol number
5203 struct ip_conntrack_protocol *ip_ct_find_proto(u_int8_t protocol)
5205 struct ip_conntrack_protocol *p;
5206 @@ -107,20 +114,19 @@
5207 nf_conntrack_put(&ct->infos[0]);
5210 -static inline u_int32_t
5211 +static int ip_conntrack_hash_rnd_initted;
5212 +static unsigned int ip_conntrack_hash_rnd;
5215 hash_conntrack(const struct ip_conntrack_tuple *tuple)
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);
5235 @@ -144,12 +150,22 @@
5236 tuple->dst.ip = iph->daddr;
5237 tuple->dst.protonum = iph->protocol;
5239 + tuple->src.u.all = tuple->dst.u.all = 0;
5241 ret = protocol->pkt_to_tuple((u_int32_t *)iph + iph->ihl,
5248 +ip_conntrack_get_tuple(const struct iphdr *iph, size_t len,
5249 + struct ip_conntrack_tuple *tuple,
5250 + struct ip_conntrack_protocol *protocol)
5252 + return get_tuple(iph, len, tuple, protocol);
5256 invert_tuple(struct ip_conntrack_tuple *inverse,
5257 const struct ip_conntrack_tuple *orig,
5259 inverse->dst.ip = orig->src.ip;
5260 inverse->dst.protonum = orig->dst.protonum;
5262 + inverse->src.u.all = inverse->dst.u.all = 0;
5264 return protocol->invert_tuple(inverse, orig);
5269 destroy_expect(struct ip_conntrack_expect *exp)
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));
5278 @@ -259,16 +277,14 @@
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)
5285 struct list_head *exp_entry, *next;
5286 struct ip_conntrack_expect *exp;
5288 DEBUGP("remove_expectations(%p)\n", ct);
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,
5297 @@ -276,6 +292,11 @@
5298 * the un-established ones only */
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;
5309 @@ -290,20 +311,18 @@
5311 clean_from_lists(struct ip_conntrack *ct)
5313 + unsigned int ho, hr;
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]);
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]);
5332 /* Destroy all un-established, pending expectations */
5333 - remove_expectations(ct);
5334 + remove_expectations(ct, 1);
5339 IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
5340 IP_NF_ASSERT(!timer_pending(&ct->timeout));
5342 - if (ct->master && master_ct(ct))
5343 - ip_conntrack_put(master_ct(ct));
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);
5351 WRITE_LOCK(&ip_conntrack_lock);
5352 + /* Delete us from our own list to prevent corruption later */
5353 + list_del(&ct->sibling_list);
5355 /* Delete our master expectation */
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);
5368 WRITE_UNLOCK(&ip_conntrack_lock);
5370 atomic_dec(&ip_conntrack_count);
5373 -static void death_by_timeout(unsigned long ul_conntrack)
5374 +void ip_ct_death_by_timeout(unsigned long ul_conntrack)
5376 struct ip_conntrack *ct = (void *)ul_conntrack;
5378 @@ -369,16 +391,24 @@
5379 const struct ip_conntrack *ignored_conntrack)
5381 struct ip_conntrack_tuple_hash *h;
5382 + unsigned int hash = hash_conntrack(tuple);
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);
5393 -/* Find a connection corresponding to a tuple. */
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
5399 + * This function increments the reference count of the found
5400 + * conntrack (if any).
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 @@
5409 -/* Return conntrack and conntrack_info given skb->nfct->master */
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
5415 + * This function resolves the respective conntrack and conntrack_info
5416 + * structures for the connection this packet (skb) is part of.
5418 struct ip_conntrack *
5419 ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
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);
5429 @@ -475,8 +513,14 @@
5433 -/* Returns true if a connection correspondings to the tuple (required
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
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.
5444 ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
5445 const struct ip_conntrack *ignored_conntrack)
5447 connection. Too bad: we're in trouble anyway. */
5448 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
5450 - return !(i->ctrack->status & IPS_ASSURED);
5451 + return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
5454 static int early_drop(struct list_head *chain)
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 *);
5462 atomic_inc(&h->ctrack->ct_general.use);
5463 READ_UNLOCK(&ip_conntrack_lock);
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);
5472 ip_conntrack_put(h->ctrack);
5473 @@ -616,7 +660,13 @@
5475 return ip_ct_tuple_mask_cmp(rtuple, &i->tuple, &i->mask);
5479 + * ip_ct_find_helper - Find application helper according to tuple
5480 + * @tuple: tuple for which helper needs to be found
5482 + * This function is used to determine if any registered conntrack helper
5483 + * is to be used for the given tuple.
5485 struct ip_conntrack_helper *ip_ct_find_helper(const struct ip_conntrack_tuple *tuple)
5487 return LIST_FIND(&helpers, helper_cmp,
5488 @@ -633,11 +683,16 @@
5490 struct ip_conntrack *conntrack;
5491 struct ip_conntrack_tuple repl_tuple;
5492 - size_t hash, repl_hash;
5494 struct ip_conntrack_expect *expected;
5496 static unsigned int drop_next = 0;
5498 + if (!ip_conntrack_hash_rnd_initted) {
5499 + get_random_bytes(&ip_conntrack_hash_rnd, 4);
5500 + ip_conntrack_hash_rnd_initted = 1;
5503 hash = hash_conntrack(tuple);
5505 if (ip_conntrack_max &&
5507 DEBUGP("Can't invert tuple.\n");
5510 - repl_hash = hash_conntrack(&repl_tuple);
5512 conntrack = kmem_cache_alloc(ip_conntrack_cachep, GFP_ATOMIC);
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;
5521 INIT_LIST_HEAD(&conntrack->sibling_list);
5523 - /* Mark clearly that it's not in the hash table. */
5524 - conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list.next = NULL;
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);
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))
5541 /* Look up the conntrack helper for master connections only */
5543 conntrack->helper = ip_ct_find_helper(&repl_tuple);
5544 @@ -710,19 +769,17 @@
5545 && ! del_timer(&expected->timeout))
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)) {
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;
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 @@
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",
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",
5582 *ctinfo = IP_CT_RELATED;
5583 @@ -907,6 +964,14 @@
5584 return ip_ct_tuple_mask_cmp(&i->tuple, tuple, &intersect_mask);
5588 + * ip_conntrack_unexpect_related - Unexpect a related connection
5589 + * @expect: expecattin to be removed
5591 + * This function removes an existing expectation, that has not yet been
5592 + * confirmed (i.e. expectation was issued, but expected connection didn't
5595 inline void ip_conntrack_unexpect_related(struct ip_conntrack_expect *expect)
5597 WRITE_LOCK(&ip_conntrack_lock);
5598 @@ -924,7 +989,20 @@
5599 WRITE_UNLOCK(&ip_conntrack_lock);
5602 -/* Add a related connection. */
5604 + * ip_conntrack_expect_related - Expect a related connection
5605 + * @related_to: master conntrack
5606 + * @expect: expectation with all values filled in
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.
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.
5617 int ip_conntrack_expect_related(struct ip_conntrack *related_to,
5618 struct ip_conntrack_expect *expect)
5620 @@ -936,8 +1014,8 @@
5621 * so there is no need to use the tuple lock too */
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);
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;
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));
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));
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 @@
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);
5690 /* add to expected list for this connection */
5691 list_add(&new->expected_list, &related_to->sibling_list);
5692 @@ -1056,7 +1132,15 @@
5696 -/* Change tuple in an existing expectation */
5698 + * ip_conntrack_change_expect - Change tuple in existing expectation
5699 + * @expect: expectation which is to be changed
5700 + * @newtuple: new tuple for expect
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.
5706 int ip_conntrack_change_expect(struct ip_conntrack_expect *expect,
5707 struct ip_conntrack_tuple *newtuple)
5709 @@ -1064,15 +1148,14 @@
5711 MUST_BE_READ_LOCKED(&ip_conntrack_lock);
5712 WRITE_LOCK(&ip_conntrack_expect_tuple_lock);
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 @@
5733 -/* Alter reply tuple (maybe alter helper). If it's already taken,
5734 - return 0 and don't do alteration. */
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
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
5744 int ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
5745 const struct ip_conntrack_tuple *newreply)
5747 @@ -1123,6 +1213,13 @@
5752 + * ip_conntrack_helper_register - Register a conntrack application helper
5753 + * @me: structure describing the helper
5755 + * This function is called by conntrack application helpers to register
5756 + * themselves with the conntrack core.
5758 int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
5761 @@ -1139,13 +1236,20 @@
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;
5774 + * ip_conntrack_helper_unregister - Unregister a conntrack application helper
5775 + * @me: structure describing the helper
5777 + * This function is called by conntrack application helpers to unregister
5778 + * themselvers from the conntrack core.
5780 void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
5783 @@ -1167,7 +1271,14 @@
5787 -/* Refresh conntrack for this many jiffies. */
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
5793 + * This function is called by protocol helpers and application helpers in
5794 + * order to change the expiration timer of a conntrack entry.
5796 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
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;
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);
5812 @@ -1186,7 +1299,16 @@
5813 WRITE_UNLOCK(&ip_conntrack_lock);
5816 -/* Returns new sk_buff, or NULL */
5819 + * ip_ct_gather_frags - Gather fragments of a particular skb
5820 + * @skb: pointer to sk_buff of fragmented IP packet
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.
5825 + * Returns new sk_buff, or NULL
5828 ip_ct_gather_frags(struct sk_buff *skb)
5830 @@ -1274,6 +1396,16 @@
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
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).
5845 ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, 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. */
5855 ip_conntrack_put(h->ctrack);
5856 @@ -1299,9 +1431,14 @@
5857 getorigdst(struct sock *sk, int optval, void *user, int *len)
5859 struct ip_conntrack_tuple_hash *h;
5860 - struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { sk->sport } },
5861 - { sk->daddr, { sk->dport },
5863 + struct ip_conntrack_tuple tuple;
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;
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,
5878 -#define NET_IP_CONNTRACK_MAX 2089
5879 -#define NET_IP_CONNTRACK_MAX_NAME "ip_conntrack_max"
5881 -#ifdef CONFIG_SYSCTL
5882 -static struct ctl_table_header *ip_conntrack_sysctl_header;
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 },
5890 -static ctl_table ip_conntrack_dir_table[] = {
5891 - {NET_IPV4, "ipv4", NULL, 0, 0555, ip_conntrack_table, 0, 0, 0, 0, 0},
5895 -static ctl_table ip_conntrack_root_table[] = {
5896 - {CTL_NET, "net", NULL, 0, 0555, ip_conntrack_dir_table, 0, 0, 0, 0, 0},
5899 -#endif /*CONFIG_SYSCTL*/
5901 static int kill_all(const struct ip_conntrack *i, void *data)
5904 @@ -1377,9 +1491,6 @@
5905 supposed to kill the mall. */
5906 void ip_conntrack_cleanup(void)
5908 -#ifdef CONFIG_SYSCTL
5909 - unregister_sysctl_table(ip_conntrack_sysctl_header);
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;
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));
5923 @@ -1458,23 +1569,19 @@
5924 for (i = 0; i < ip_conntrack_htable_size; i++)
5925 INIT_LIST_HEAD(&ip_conntrack_hash[i]);
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.
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;
5936 -#endif /*CONFIG_SYSCTL*/
5938 /* For use by ipt_REJECT */
5939 ip_ct_attach = ip_conntrack_attach;
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;
5951 -err_free_ct_cachep:
5952 - kmem_cache_destroy(ip_conntrack_cachep);
5954 vfree(ip_conntrack_hash);
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
5960 +/* Eggdrop extension for IP connection tracking, Version 0.0.5
5961 + * based on ip_conntrack_irc.c
5963 + * This module only supports the share userfile-send command,
5964 + * used by eggdrops to share it's userfile.
5966 + * There are no support for NAT at the moment.
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.
5973 + * Module load syntax:
5975 + * please give the ports of all Eggdrops You have running
5976 + * on your system, the default port is 3333.
5978 + * 2001-04-19: Security update. IP addresses are now compared
5979 + * to prevent unauthorized "related" access.
5981 + * 2002-03-25: Harald Welte <laforge@gnumonks.org>:
5982 + * Port to netfilter 'newnat' API.
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>
5991 +#include <linux/netfilter_ipv4/lockhelp.h>
5992 +#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
5994 +#define MAX_PORTS 8
5995 +static int ports[MAX_PORTS];
5996 +static int ports_c = 0;
5997 +static unsigned int egg_timeout = 300;
5999 +MODULE_AUTHOR("Magnus Sandin <magnus@sandin.cx>");
6000 +MODULE_DESCRIPTION("Eggdrop (userfile-sharing) connection tracking module");
6001 +MODULE_LICENSE("GPL");
6003 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6004 +MODULE_PARM_DESC(ports, "port numbers of eggdrop servers");
6007 +DECLARE_LOCK(ip_egg_lock);
6008 +struct module *ip_conntrack_egg = THIS_MODULE;
6011 +#define DEBUGP printk
6013 +#define DEBUGP(format, args...)
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 */
6024 + if (data > data_end)
6027 + *ip = simple_strtoul(data, &data, 10);
6029 + /* skip blanks between ip and port */
6030 + while (*data == ' ' && data < data_end)
6033 + *port = simple_strtoul(data, &data, 10);
6038 +static int help(const struct iphdr *iph, size_t len,
6039 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
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;
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;
6052 + u_int16_t egg_port;
6054 + DEBUGP("entered\n");
6056 + /* If packet is coming from IRC server */
6057 + if (dir != IP_CT_DIR_REPLY)
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);
6067 + /* Not whole TCP header? */
6068 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
6069 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
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));
6083 + data_limit = (char *) data + datalen;
6084 + while (datalen > 5 && bytes_scanned < 128) {
6085 + if (memcmp(data, "s us ", 5)) {
6094 + DEBUGP("Userfile-share found in connection "
6095 + "%u.%u.%u.%u -> %u.%u.%u.%u\n",
6096 + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
6098 + if (parse_command((char *) data, data_limit, &egg_ip,
6100 + DEBUGP("no data in userfile-share pkt\n");
6104 + memset(&exp, 0, sizeof(exp));
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);
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;
6121 + exp.mask.dst.u.tcp.port = 0xffff;
6122 + exp.mask.dst.protonum = 0xffff;
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));
6128 + ip_conntrack_expect_related(ct, &exp);
6134 +static struct ip_conntrack_helper egg_helpers[MAX_PORTS];
6135 +static char egg_names[MAX_PORTS][14]; /* eggdrop-65535 */
6137 +static void deregister_helpers(void) {
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]);
6146 +static int __init init(void)
6151 + /* If no port given, default to standard eggdrop port */
6152 + if (ports[0] == 0)
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;
6168 + tmpname = &egg_names[i][0];
6169 + if (ports[i] == 3333)
6170 + sprintf(tmpname, "eggdrop");
6172 + sprintf(tmpname, "eggdrop-%d", ports[i]);
6173 + egg_helpers[i].name = tmpname;
6175 + DEBUGP("port #%d: %d\n", i, ports[i]);
6177 + ret = ip_conntrack_helper_register(&egg_helpers[i]);
6180 + printk("ip_conntrack_egg: ERROR registering helper "
6181 + "for port %d\n", ports[i]);
6182 + deregister_helpers();
6190 +static void __exit fini(void)
6192 + deregister_helpers();
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
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);
6207 static struct ftp_search {
6208 enum ip_conntrack_dir dir;
6211 "229 ", sizeof("229 ") - 1, '(', ')',
6213 - try_espv_response,
6214 + try_epsv_response,
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],
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]);
6240 @@ -366,11 +366,11 @@
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]) } },
6247 exp->mask = ((struct ip_conntrack_tuple)
6248 { { 0xFFFFFFFF, { 0 } },
6249 - { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6250 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6252 exp->expectfn = NULL;
6255 ports[0] = FTP_PORT;
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;
6266 -#ifdef CONFIG_IP_NF_NAT_NEEDED
6267 EXPORT_SYMBOL(ip_ftp_lock);
6270 MODULE_LICENSE("GPL");
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
6277 + * H.323 'brute force' extension for H.323 connection tracking.
6278 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
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>
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>
6300 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
6301 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
6302 +MODULE_LICENSE("GPL");
6304 +DECLARE_LOCK(ip_h323_lock);
6305 +struct module *ip_conntrack_h323 = THIS_MODULE;
6308 +#define DEBUGP printk
6310 +#define DEBUGP(format, args...)
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)
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;
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));
6335 + /* Can't track connections formed before we registered */
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);
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);
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));
6362 + data_limit = (unsigned char *) data + datalen;
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;
6380 + exp->seq = ntohl(tcph->seq) + i;
6382 + exp->tuple = ((struct ip_conntrack_tuple)
6383 + { { ct->tuplehash[!dir].tuple.src.ip,
6386 + { .tcp = { data_port } },
6388 + exp->mask = ((struct ip_conntrack_tuple)
6389 + { { 0xFFFFFFFF, { 0 } },
6390 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6392 + exp->expectfn = NULL;
6394 + /* Ignore failure; should only happen with NAT */
6395 + ip_conntrack_expect_related(ct, exp);
6397 + UNLOCK_BH(&ip_h323_lock);
6405 +/* H.245 helper is not registered! */
6406 +static struct ip_conntrack_helper h245 =
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 */
6420 +static int h225_expect(struct ip_conntrack *ct)
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);
6427 + return NF_ACCEPT; /* unused */
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)
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;
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));
6452 + /* Can't track connections formed before we registered */
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);
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);
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));
6479 + data_limit = (unsigned char *) data + datalen;
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);
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);
6500 + memset(&expect, 0, sizeof(expect));
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;
6509 + exp->seq = ntohl(tcph->seq) + i;
6511 + exp->tuple = ((struct ip_conntrack_tuple)
6512 + { { ct->tuplehash[!dir].tuple.src.ip,
6515 + { .tcp = { data_port } },
6517 + exp->mask = ((struct ip_conntrack_tuple)
6518 + { { 0xFFFFFFFF, { 0 } },
6519 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6521 + exp->expectfn = h225_expect;
6523 + /* Ignore failure */
6524 + ip_conntrack_expect_related(ct, exp);
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));
6530 + UNLOCK_BH(&ip_h323_lock);
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);
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);
6555 +static struct ip_conntrack_helper h225 =
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 */
6569 +static int __init init(void)
6571 + return ip_conntrack_helper_register(&h225);
6574 +static void __exit fini(void)
6576 + /* Unregister H.225 helper */
6577 + ip_conntrack_helper_unregister(&h225);
6580 +EXPORT_SYMBOL(ip_h323_lock);
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
6591 -#define MAXMATCHLEN 6
6592 +#define MINMATCHLEN 5
6594 DECLARE_LOCK(ip_irc_lock);
6595 struct module *ip_conntrack_irc = THIS_MODULE;
6597 *ip = simple_strtoul(data, &data, 10);
6599 /* skip blanks between ip and port */
6600 - while (*data == ' ')
6601 + while (*data == ' ') {
6602 + if (data >= data_end)
6608 *port = simple_strtoul(data, &data, 10);
6610 @@ -153,13 +155,17 @@
6613 data_limit = (char *) data + datalen;
6614 - while (data < (data_limit - (22 + MAXMATCHLEN))) {
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)) {
6625 + /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */
6627 DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n",
6628 NIPQUAD(iph->saddr), ntohs(tcph->source),
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);
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())
6650 "Forged DCC command from "
6651 @@ -209,11 +221,11 @@
6653 exp->tuple = ((struct ip_conntrack_tuple)
6655 - { htonl(dcc_ip), { htons(dcc_port) },
6656 + { ct->tuplehash[dir].tuple.src.ip, { .tcp = { htons(dcc_port) } },
6658 exp->mask = ((struct ip_conntrack_tuple)
6660 - { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
6661 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
6663 exp->expectfn = NULL;
6667 for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6668 hlpr = &irc_helpers[i];
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;
6678 -#ifdef CONFIG_IP_NF_NAT_NEEDED
6679 EXPORT_SYMBOL(ip_irc_lock);
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
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
6692 + * ip_conntrack_mms.c v0.3 2002-09-22
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.
6699 + * Module load syntax:
6700 + * insmod ip_conntrack_mms.o ports=port1,port2,...port<MAX_PORTS>
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.
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
6709 + * The SDP project people are reverse-engineering MMS:
6710 + * http://get.to/sdp
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>
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>
6725 +DECLARE_LOCK(ip_mms_lock);
6726 +struct module *ip_conntrack_mms = THIS_MODULE;
6728 +#define MAX_PORTS 8
6729 +static int ports[MAX_PORTS];
6730 +static int ports_c;
6732 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
6736 +#define DEBUGP printk
6738 +#define DEBUGP(format, args...)
6741 +EXPORT_SYMBOL(ip_mms_lock);
6743 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
6744 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) connection tracking module");
6745 +MODULE_LICENSE("GPL");
6747 +/* #define isdigit(c) (c >= '0' && c <= '9') */
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)
6753 + for (i = 0; i < unicode_size; ++i) {
6754 + string[i] = (char)(unicode[i]);
6756 + string[unicode_size] = 0x00;
6759 +__inline static int atoi(char *s)
6762 + while (isdigit(*s)) {
6763 + i = i*10 + *(s++) - '0';
6768 +/* convert ip address string like "192.168.0.10" to unsigned int */
6769 +__inline static u_int32_t asciiiptoi(char *s)
6771 + unsigned int i, j, k;
6773 + for(i=k=0; k<3; ++k, ++s, i<<=8) {
6775 + for(j=0; (*(++s) != '.') && (j<3); ++j)
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)
6791 + int unicode_size, i;
6792 + char tempstring[28]; /* "\\255.255.255.255\UDP\65535" */
6793 + char getlengthstring[28];
6795 + for(unicode_size=0;
6796 + (char) *(data+(MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2)) != (char)0;
6798 + if ((unicode_size == 28) || (MMS_SRV_UNICODE_STRING_OFFSET+unicode_size*2 >= datalen))
6799 + return -1; /* out of bounds - incomplete packet */
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));
6804 + /* IP address ? */
6805 + *mms_ip = asciiiptoi(tempstring+2);
6807 + i=sprintf(getlengthstring, "%u.%u.%u.%u", HIPQUAD(*mms_ip));
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;
6816 + *mms_port = atoi(tempstring+7+i);
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 */
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)
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;
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;
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);
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);
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));
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...
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),
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");
6897 + memset(&expect, 0, sizeof(expect));
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),
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);
6913 + DEBUGP("ip_conntrack_mms: tcph->seq = %u\n", tcph->seq);
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;
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);
6923 + exp->tuple = ((struct ip_conntrack_tuple)
6924 + { { ct->tuplehash[!dir].tuple.src.ip, { 0 } },
6926 + { .tcp = { (__u16) ntohs(mms_port) } },
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);
6940 +static struct ip_conntrack_helper mms[MAX_PORTS];
6941 +static char mms_names[MAX_PORTS][10];
6943 +/* Not __exit: called from init() */
6944 +static void fini(void)
6947 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
6948 + DEBUGP("ip_conntrack_mms: unregistering helper for port %d\n",
6950 + ip_conntrack_helper_unregister(&mms[i]);
6954 +static int __init init(void)
6959 + if (ports[0] == 0)
6960 + ports[0] = MMS_PORT;
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;
6974 + tmpname = &mms_names[i][0];
6975 + if (ports[i] == MMS_PORT)
6976 + sprintf(tmpname, "mms");
6978 + sprintf(tmpname, "mms-%d", ports[i]);
6979 + mms[i].name = tmpname;
6981 + DEBUGP("ip_conntrack_mms: registering helper for port %d\n",
6983 + ret = ip_conntrack_helper_register(&mms[i]);
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
7001 + * ip_conntrack_pptp.c - Version 1.9
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
7011 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
7013 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
7016 + * - We blindly assume that control connections are always
7017 + * established in PNS->PAC direction. This is a violation
7020 + * TODO: - finish support for multiple calls within one session
7021 + * (needs expect reservations in newnat)
7022 + * - testing of incoming PPTP calls
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
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>
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>
7049 +#define IP_CT_PPTP_VERSION "1.9"
7051 +MODULE_LICENSE("GPL");
7052 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
7053 +MODULE_DESCRIPTION("Netfilter connection tracking helper module for PPTP");
7055 +DECLARE_LOCK(ip_pptp_lock);
7058 +#include "ip_conntrack_pptp_priv.h"
7059 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
7060 + ": " format, ## args)
7062 +#define DEBUGP(format, args...)
7066 +#define MINS * 60 SECS
7067 +#define HOURS * 60 MINS
7068 +#define DAYS * 24 HOURS
7070 +#define PPTP_GRE_TIMEOUT (10 MINS)
7071 +#define PPTP_GRE_STREAM_TIMEOUT (5 DAYS)
7073 +static int pptp_expectfn(struct ip_conntrack *ct)
7075 + struct ip_conntrack *master;
7076 + struct ip_conntrack_expect *exp;
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;
7083 + master = master_ct(ct);
7085 + DEBUGP(" no master!!!\n");
7091 + DEBUGP("no expectation!!\n");
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);
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);
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;
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,
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);
7135 +/* timeout GRE data connections */
7136 +static int pptp_timeout_related(struct ip_conntrack *ct)
7138 + struct list_head *cur_item, *next;
7139 + struct ip_conntrack_expect *exp;
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,
7148 + ip_ct_gre_keymap_destroy(exp);
7149 + if (!exp->sibling) {
7150 + ip_conntrack_unexpect_related(exp);
7154 + DEBUGP("killing conntrack %p\n",
7156 + exp->sibling->proto.gre.timeout = 0;
7157 + exp->sibling->proto.gre.stream_timeout = 0;
7159 + if (del_timer(&exp->sibling->timeout))
7160 + ip_ct_death_by_timeout((unsigned long)exp->sibling);
7166 +/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
7168 +exp_gre(struct ip_conntrack *master,
7171 + u_int16_t peer_callid)
7173 + struct ip_conntrack_expect exp;
7174 + struct ip_conntrack_tuple inv_tuple;
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;
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;
7196 + exp.expectfn = pptp_expectfn;
7198 + exp.help.exp_pptp_info.pac_call_id = ntohs(callid);
7199 + exp.help.exp_pptp_info.pns_call_id = ntohs(peer_callid);
7201 + DEBUGP("calling expect_related ");
7202 + DUMP_TUPLE_RAW(&exp.tuple);
7204 + /* Add GRE keymap entries */
7205 + if (ip_ct_gre_keymap_add(&exp, &exp.tuple, 0) != 0)
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);
7214 + if (ip_conntrack_expect_related(master, &exp) != 0) {
7215 + ip_ct_gre_keymap_destroy(&exp);
7216 + DEBUGP("cannot expect_related()\n");
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));
7226 + DEBUGP("calling expect_related ");
7227 + DUMP_TUPLE_RAW(&exp.tuple);
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 :( */
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");
7247 +pptp_inbound_pkt(struct tcphdr *tcph,
7248 + struct pptp_pkt_hdr *pptph,
7250 + struct ip_conntrack *ct,
7251 + enum ip_conntrack_info ctinfo)
7253 + struct PptpControlHeader *ctlh;
7254 + union pptp_ctrl_union pptpReq;
7256 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
7257 + u_int16_t msg, *cid, *pcid;
7260 + ctlh = (struct PptpControlHeader *)
7261 + ((char *) pptph + sizeof(struct pptp_pkt_hdr));
7262 + pptpReq.rawreq = (void *)
7263 + ((char *) ctlh + sizeof(struct PptpControlHeader));
7265 + msg = ntohs(ctlh->messageType);
7266 + DEBUGP("inbound control message %s\n", strMName[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",
7276 + if (pptpReq.srep->resultCode == PPTP_START_OK)
7277 + info->sstate = PPTP_SESSION_CONFIRMED;
7279 + info->sstate = PPTP_SESSION_ERROR;
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",
7289 + if (pptpReq.strep->resultCode == PPTP_STOP_OK)
7290 + info->sstate = PPTP_SESSION_NONE;
7292 + info->sstate = PPTP_SESSION_ERROR;
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]);
7301 + if (info->cstate != PPTP_CALL_OUT_REQ &&
7302 + info->cstate != PPTP_CALL_OUT_CONF) {
7303 + DEBUGP("%s without OUTCALL_REQ\n", strMName[msg]);
7306 + if (pptpReq.ocack->resultCode != PPTP_OUTCALL_CONNECT) {
7307 + info->cstate = PPTP_CALL_NONE;
7311 + cid = &pptpReq.ocack->callID;
7312 + pcid = &pptpReq.ocack->peersCallID;
7314 + info->pac_call_id = ntohs(*cid);
7316 + if (htons(info->pns_call_id) != *pcid) {
7317 + DEBUGP("%s for unknown callid %u\n",
7318 + strMName[msg], ntohs(*pcid));
7322 + DEBUGP("%s, CID=%X, PCID=%X\n", strMName[msg],
7323 + ntohs(*cid), ntohs(*pcid));
7325 + info->cstate = PPTP_CALL_OUT_CONF;
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");
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]);
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);
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]);
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",
7357 + pcid = &pptpReq.iccon->peersCallID;
7358 + cid = &info->pac_call_id;
7360 + if (info->pns_call_id != ntohs(*pcid)) {
7361 + DEBUGP("%s for unknown CallID %u\n",
7362 + strMName[msg], ntohs(*cid));
7366 + DEBUGP("%s, PCID=%X\n", strMName[msg], ntohs(*pcid));
7367 + info->cstate = PPTP_CALL_IN_CONF;
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");
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;
7382 + /* untrack this call id, unexpect GRE packets */
7383 + pptp_timeout_related(ct);
7386 + case PPTP_WAN_ERROR_NOTIFY:
7389 + case PPTP_ECHO_REQUEST:
7390 + case PPTP_ECHO_REPLY:
7391 + /* I don't have to explain these ;) */
7394 + DEBUGP("invalid %s (TY=%d)\n", (msg <= PPTP_MSG_MAX)
7395 + ? strMName[msg]:strMName[0], msg);
7404 +pptp_outbound_pkt(struct tcphdr *tcph,
7405 + struct pptp_pkt_hdr *pptph,
7407 + struct ip_conntrack *ct,
7408 + enum ip_conntrack_info ctinfo)
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;
7415 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
7416 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
7418 + msg = ntohs(ctlh->messageType);
7419 + DEBUGP("outbound control message %s\n", strMName[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",
7428 + info->sstate = PPTP_SESSION_REQUESTED;
7430 + case PPTP_STOP_SESSION_REQUEST:
7431 + /* client requests end of control session */
7432 + info->sstate = PPTP_SESSION_STOPREQ;
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",
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);
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",
7456 + if (pptpReq.icack->resultCode != PPTP_INCALL_ACCEPT) {
7457 + info->cstate = PPTP_CALL_NONE;
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));
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);
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");
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;
7483 + case PPTP_SET_LINK_INFO:
7485 + case PPTP_ECHO_REQUEST:
7486 + case PPTP_ECHO_REPLY:
7487 + /* I don't have to explain these ;) */
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 */
7500 +/* track caller id inside control connection, call expect_related */
7502 +conntrack_pptp_help(const struct iphdr *iph, size_t len,
7503 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
7506 + struct pptp_pkt_hdr *pptph;
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;
7512 + int dir = CTINFO2DIR(ctinfo);
7513 + struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
7515 + int oldsstate, oldcstate;
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);
7525 + /* not a complete TCP header? */
7526 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
7527 + DEBUGP("tcplen = %u\n", tcplen);
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;
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;
7544 + /* untrack this call id, unexpect GRE packets */
7545 + pptp_timeout_related(ct);
7549 + pptph = (struct pptp_pkt_hdr *) ((void *) tcph + tcph->doff * 4);
7550 + datalimit = (void *) pptph + datalen;
7552 + /* not a full pptp packet header? */
7553 + if ((void *) pptph+sizeof(*pptph) >= datalimit) {
7554 + DEBUGP("no full PPTP header, can't track\n");
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");
7565 + oldsstate = info->sstate;
7566 + oldcstate = info->cstate;
7568 + LOCK_BH(&ip_pptp_lock);
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);
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);
7585 +/* control protocol helper */
7586 +static struct ip_conntrack_helper pptp = {
7587 + .list = { NULL, NULL },
7589 + .flags = IP_CT_HELPER_F_REUSE_EXPECT,
7590 + .me = THIS_MODULE,
7591 + .max_expected = 2,
7593 + .tuple = { .src = { .ip = 0,
7594 + .u = { .tcp = { .port =
7595 + __constant_htons(PPTP_CONTROL_PORT) } }
7598 + .u = { .all = 0 },
7599 + .protonum = IPPROTO_TCP
7602 + .mask = { .src = { .ip = 0,
7603 + .u = { .tcp = { .port = 0xffff } }
7606 + .u = { .all = 0 },
7607 + .protonum = 0xffff
7610 + .help = conntrack_pptp_help
7613 +/* ip_conntrack_pptp initialization */
7614 +static int __init init(void)
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);
7625 + printk("ip_conntrack_pptp version %s loaded\n", IP_CT_PPTP_VERSION);
7629 +static void __exit fini(void)
7631 + ip_conntrack_helper_unregister(&pptp);
7632 + printk("ip_conntrack_pptp version %s unloaded\n", IP_CT_PPTP_VERSION);
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
7643 +#ifndef _IP_CT_PPTP_PRIV_H
7644 +#define _IP_CT_PPTP_PRIV_H
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",
7655 + "OUT_CALL_REQUEST",
7657 + "IN_CALL_REQUEST",
7659 + "IN_CALL_CONNECT",
7660 + "CALL_CLEAR_REQUEST",
7661 + "CALL_DISCONNECT_NOTIFY",
7662 + "WAN_ERROR_NOTIFY",
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
7671 #include <linux/netfilter.h>
7672 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
7674 -#define GENERIC_TIMEOUT (600*HZ)
7675 +unsigned long ip_ct_generic_timeout = 600*HZ;
7677 static int generic_pkt_to_tuple(const void *datah, size_t datalen,
7678 struct ip_conntrack_tuple *tuple)
7680 struct iphdr *iph, size_t len,
7681 enum ip_conntrack_info conntrackinfo)
7683 - ip_ct_refresh(conntrack, GENERIC_TIMEOUT);
7684 + ip_ct_refresh(conntrack, ip_ct_generic_timeout);
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
7693 + * ip_conntrack_proto_gre.c - Version 1.2
7695 + * Connection tracking protocol helper module for GRE.
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.
7700 + * It has an optional key field, which may help us distinguishing two
7701 + * connections between the same two hosts.
7703 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
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.
7709 + * Documentation about PPTP can be found in RFC 2637
7711 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
7713 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
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>
7726 +#include <linux/netfilter_ipv4/lockhelp.h>
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)
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>
7737 +#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
7738 +#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
7740 +MODULE_LICENSE("GPL");
7741 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
7742 +MODULE_DESCRIPTION("netfilter connection tracking protocol helper for GRE");
7744 +/* shamelessly stolen from ip_conntrack_proto_udp.c */
7745 +#define GRE_TIMEOUT (30*HZ)
7746 +#define GRE_STREAM_TIMEOUT (180*HZ)
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))
7757 +#define DEBUGP(x, args...)
7758 +#define DUMP_TUPLE_GRE(x)
7761 +/* GRE KEYMAP HANDLING FUNCTIONS */
7762 +static LIST_HEAD(gre_keymap_list);
7764 +static inline int gre_key_cmpfn(const struct ip_ct_gre_keymap *km,
7765 + const struct ip_conntrack_tuple *t)
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));
7773 +/* look up the source key for a given tuple */
7774 +static u_int32_t gre_keymap_lookup(struct ip_conntrack_tuple *t)
7776 + struct ip_ct_gre_keymap *km;
7779 + READ_LOCK(&ip_ct_gre_lock);
7780 + km = LIST_FIND(&gre_keymap_list, gre_key_cmpfn,
7781 + struct ip_ct_gre_keymap *, t);
7783 + READ_UNLOCK(&ip_ct_gre_lock);
7787 + key = km->tuple.src.u.gre.key;
7788 + READ_UNLOCK(&ip_ct_gre_lock);
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)
7797 + struct ip_ct_gre_keymap *km;
7799 + km = kmalloc(sizeof(*km), GFP_ATOMIC);
7803 + /* initializing list head should be sufficient */
7804 + memset(km, 0, sizeof(*km));
7806 + memcpy(&km->tuple, t, sizeof(*t));
7809 + exp->proto.gre.keymap_orig = km;
7811 + exp->proto.gre.keymap_reply = km;
7813 + DEBUGP("adding new entry %p: ", km);
7814 + DUMP_TUPLE_GRE(&km->tuple);
7816 + WRITE_LOCK(&ip_ct_gre_lock);
7817 + list_append(&gre_keymap_list, km);
7818 + WRITE_UNLOCK(&ip_ct_gre_lock);
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)
7827 + DEBUGP("changing entry %p to: ", km);
7828 + DUMP_TUPLE_GRE(t);
7830 + WRITE_LOCK(&ip_ct_gre_lock);
7831 + memcpy(&km->tuple, t, sizeof(km->tuple));
7832 + WRITE_UNLOCK(&ip_ct_gre_lock);
7835 +/* destroy the keymap entries associated with specified expect */
7836 +void ip_ct_gre_keymap_destroy(struct ip_conntrack_expect *exp)
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;
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;
7852 + WRITE_UNLOCK(&ip_ct_gre_lock);
7856 +/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
7858 +/* invert gre part of tuple */
7859 +static int gre_invert_tuple(struct ip_conntrack_tuple *tuple,
7860 + const struct ip_conntrack_tuple *orig)
7862 + tuple->dst.u.gre.protocol = orig->dst.u.gre.protocol;
7863 + tuple->dst.u.gre.version = orig->dst.u.gre.version;
7865 + tuple->dst.u.gre.key = orig->src.u.gre.key;
7866 + tuple->src.u.gre.key = orig->dst.u.gre.key;
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)
7875 + struct gre_hdr *grehdr = (struct gre_hdr *) datah;
7876 + struct gre_hdr_pptp *pgrehdr = (struct gre_hdr_pptp *) datah;
7879 + /* core guarantees 8 protocol bytes, no need for size check */
7881 + tuple->dst.u.gre.version = grehdr->version;
7882 + tuple->dst.u.gre.protocol = grehdr->protocol;
7884 + switch (grehdr->version) {
7885 + case GRE_VERSION_1701:
7886 + if (!grehdr->key) {
7887 + DEBUGP("Can't track GRE without key\n");
7890 + tuple->dst.u.gre.key = *(gre_key(grehdr));
7893 + case GRE_VERSION_PPTP:
7894 + if (ntohs(grehdr->protocol) != GRE_PROTOCOL_PPTP) {
7895 + DEBUGP("GRE_VERSION_PPTP but unknown proto\n");
7898 + tuple->dst.u.gre.key = htonl(ntohs(pgrehdr->call_id));
7902 + printk(KERN_WARNING "unknown GRE version %hu\n",
7903 + tuple->dst.u.gre.version);
7907 + srckey = gre_keymap_lookup(tuple);
7910 + DEBUGP("found src key %x for tuple ", ntohl(srckey));
7911 + DUMP_TUPLE_GRE(tuple);
7913 + tuple->src.u.gre.key = srckey;
7918 +/* print gre part of tuple */
7919 +static unsigned int gre_print_tuple(char *buffer,
7920 + const struct ip_conntrack_tuple *tuple)
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));
7929 +/* print private data for conntrack */
7930 +static unsigned int gre_print_conntrack(char *buffer,
7931 + const struct ip_conntrack *ct)
7933 + return sprintf(buffer, "timeout=%u, stream_timeout=%u ",
7934 + (ct->proto.gre.timeout / HZ),
7935 + (ct->proto.gre.stream_timeout / HZ));
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)
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);
7950 + ip_ct_refresh(ct, ct->proto.gre.timeout);
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)
7960 + DUMP_TUPLE_GRE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
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;
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)
7974 + struct ip_conntrack_expect *master = ct->master;
7976 + DEBUGP(" entering\n");
7979 + DEBUGP("no master exp for ct %p\n", ct);
7983 + ip_ct_gre_keymap_destroy(master);
7986 +/* protocol helper struct */
7987 +static struct ip_conntrack_protocol gre = { { NULL, NULL }, IPPROTO_GRE,
7992 + gre_print_conntrack,
7999 +/* ip_conntrack_proto_gre initialization */
8000 +static int __init init(void)
8004 + if ((retcode = ip_conntrack_protocol_register(&gre))) {
8005 + printk(KERN_ERR "Unable to register conntrack protocol "
8006 + "helper for gre: %d\n", retcode);
8013 +static void __exit fini(void)
8015 + struct list_head *pos, *n;
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);
8024 + WRITE_UNLOCK(&ip_ct_gre_lock);
8026 + ip_conntrack_protocol_unregister(&gre);
8029 +EXPORT_SYMBOL(ip_ct_gre_keymap_add);
8030 +EXPORT_SYMBOL(ip_ct_gre_keymap_change);
8031 +EXPORT_SYMBOL(ip_ct_gre_keymap_destroy);
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
8039 #include <linux/icmp.h>
8040 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
8042 -#define ICMP_TIMEOUT (30*HZ)
8043 +unsigned long ip_ct_icmp_timeout = 30*HZ;
8046 #define DEBUGP printk
8048 ct->timeout.function((unsigned long)ct);
8050 atomic_inc(&ct->proto.icmp.count);
8051 - ip_ct_refresh(ct, ICMP_TIMEOUT);
8052 + ip_ct_refresh(ct, ip_ct_icmp_timeout);
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
8060 -#define __NO_VERSION__
8061 #include <linux/types.h>
8062 #include <linux/sched.h>
8063 #include <linux/timer.h>
8065 #define HOURS * 60 MINS
8066 #define DAYS * 24 HOURS
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, */
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;
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 */
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);
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);
8124 && tcph->ack_seq == conntrack->proto.tcp.handshake_ack)
8125 set_bit(IPS_ASSURED_BIT, &conntrack->status);
8127 - ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);
8128 + WRITE_UNLOCK(&tcp_lock);
8129 + ip_ct_refresh(conntrack, *tcp_timeouts[newconntrack]);
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
8137 #include <linux/udp.h>
8138 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
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;
8145 static int udp_pkt_to_tuple(const void *datah, size_t datalen,
8146 struct ip_conntrack_tuple *tuple)
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);
8158 - ip_ct_refresh(conntrack, UDP_TIMEOUT);
8159 + ip_ct_refresh(conntrack, ip_ct_udp_timeout);
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
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
8171 + * ip_conntrack_quake3.c v0.04 2002-08-31
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.
8178 + * Module load syntax:
8179 + * insmod ip_conntrack_quake3.o ports=port1,port2,...port<MAX_PORTS>
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
8185 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
8188 +#include <linux/module.h>
8189 +#include <linux/ip.h>
8190 +#include <linux/udp.h>
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>
8197 +struct module *ip_conntrack_quake3 = THIS_MODULE;
8199 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
8200 +MODULE_DESCRIPTION("Netfilter connection tracking module for Quake III Arena");
8201 +MODULE_LICENSE("GPL");
8203 +#define MAX_PORTS 8
8204 +static int ports[MAX_PORTS];
8205 +static int ports_c = 0;
8207 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8208 +MODULE_PARM_DESC(ports, "port numbers of Quake III master servers");
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 */
8214 +#define DEBUGP printk
8216 +#define DEBUGP(format, args...)
8219 +struct quake3_search quake3s_conntrack = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
8221 +static int quake3_help(const struct iphdr *iph, size_t len,
8222 + struct ip_conntrack *ct,
8223 + enum ip_conntrack_info ctinfo)
8225 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
8226 + int dir = CTINFO2DIR(ctinfo);
8227 + struct ip_conntrack_expect exp;
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);
8235 + } else { DEBUGP("ip_conntrack_quake3: it's ok ! Conntrackinfo = %u\n", ctinfo); }
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);
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 ) ) ) );
8246 + memset(&exp, 0, sizeof(exp));
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)) } },
8254 + exp.mask = ((struct ip_conntrack_tuple)
8255 + { { 0xFFFFFFFF, { 0 } },
8256 + { 0xFFFFFFFF, { .udp = { 0xFFFF } }, 0xFFFF }});
8257 + exp.expectfn = NULL;
8259 + ip_conntrack_expect_related(ct, &exp);
8264 + return(NF_ACCEPT);
8267 +static struct ip_conntrack_helper quake3[MAX_PORTS];
8268 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
8270 +static void fini(void)
8274 + for(i = 0 ; (i < ports_c); i++) {
8275 + DEBUGP("ip_conntrack_quake3: unregistering helper for port %d\n",
8277 + ip_conntrack_helper_unregister(&quake3[i]);
8281 +static int __init init(void)
8287 + ports[0]=QUAKE3_MASTER_PORT;
8289 + for(i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
8290 + /* Create helper structure */
8291 + memset(&quake3[i], 0, sizeof(struct ip_conntrack_helper));
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;
8300 + tmpname = &quake3_names[i][0];
8301 + if (ports[i] == QUAKE3_MASTER_PORT)
8302 + sprintf(tmpname, "quake3");
8304 + sprintf(tmpname, "quake3-%d", i);
8305 + quake3[i].name = tmpname;
8307 + DEBUGP("ip_conntrack_quake3: registering helper for port %d\n",
8310 + ret=ip_conntrack_helper_register(&quake3[i]);
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
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
8332 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8333 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
8339 + * ip_conntrack_rpc_tpc.c,v 2.2 2003/01/12 18:30:00
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.
8346 + * Module load syntax:
8347 + * insmod ip_conntrack_rpc_tcp.o ports=port1,port2,...port<MAX_PORTS>
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.
8354 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
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>
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>
8388 +#define MAX_PORTS 8
8389 +static int ports[MAX_PORTS];
8390 +static int ports_n_c = 0;
8393 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8394 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8397 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8398 +MODULE_DESCRIPTION("RPC TCP connection tracking module");
8399 +MODULE_LICENSE("GPL");
8402 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_tcp: " \
8405 +#define DEBUGP(format, args...)
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>
8413 +/* For future conections RPC, using client's cache bindings
8414 + * I'll use ip_conntrack_lock to lock these lists */
8416 +LIST_HEAD(request_p_list_tcp);
8419 +static void delete_request_p(unsigned long request_p_ul)
8421 + struct request_p *p = (void *)request_p_ul;
8423 + WRITE_LOCK(&ipct_rpc_tcp_lock);
8424 + LIST_DELETE(&request_p_list_tcp, p);
8425 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8431 +static void req_cl(struct request_p * r)
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);
8442 +static void clean_request(struct list_head *list)
8444 + struct list_head *first = list->prev;
8445 + struct list_head *temp = list->next;
8446 + struct list_head *aux;
8448 + if (list_empty(list))
8451 + while (first != temp) {
8453 + req_cl((struct request_p *)temp);
8456 + req_cl((struct request_p *)temp);
8461 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
8464 + struct request_p *req_p;
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);
8472 + /* Refresh timeout */
8473 + if (del_timer(&req_p->timeout)) {
8474 + req_p->timeout.expires = jiffies + EXP;
8475 + add_timer(&req_p->timeout);
8477 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8481 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
8483 + /* Allocate new request_p */
8484 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
8486 + DEBUGP("can't allocate request_p\n");
8489 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
8490 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
8493 + /* Initialize timer */
8494 + init_timer(&req_p->timeout);
8495 + req_p->timeout.function = delete_request_p;
8496 + add_timer(&req_p->timeout);
8499 + WRITE_LOCK(&ipct_rpc_tcp_lock);
8500 + list_prepend(&request_p_list_tcp, req_p);
8501 + WRITE_UNLOCK(&ipct_rpc_tcp_lock);
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)
8511 + struct request_p *req_p;
8513 + struct ip_conntrack_expect expect, *exp = &expect;
8515 + /* Translstion's buffer for XDR */
8516 + u_int16_t port_buf;
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.
8528 + /* perform direction dependant RPC work */
8529 + if (dir == IP_CT_DIR_ORIGINAL) {
8533 + /* Get RPC requestor */
8534 + if (IXDR_GET_INT32(data) != 3) {
8535 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
8538 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
8542 + /* Jump Credentials and Verfifier */
8543 + data += IXDR_GET_INT32(data) + 2;
8544 + data += IXDR_GET_INT32(data) + 2;
8546 + /* Get RPC procedure */
8547 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
8548 + (unsigned int)IXDR_GET_INT32(data));
8550 + /* Get RPC protocol and store against client parameters */
8552 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
8553 + ct->tuplehash[dir].tuple.src.u.all);
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));
8560 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
8561 + (unsigned int)IXDR_GET_INT32(data));
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);
8571 + /* Drop unexpected packets */
8573 + DEBUGP("packet is not expected. [skip]\n");
8577 + /* Verifies if packet is really an RPC reply packet */
8579 + if (IXDR_GET_INT32(data) != 1) {
8580 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
8584 + /* Is status accept? */
8586 + if (IXDR_GET_INT32(data)) {
8587 + DEBUGP("packet is not an RPC accept. [skip]\n");
8591 + /* Get Verifier length. Jump verifier */
8593 + data = data + IXDR_GET_INT32(data) + 2;
8595 + /* Is accpet status "success"? */
8596 + if (IXDR_GET_INT32(data)) {
8597 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
8601 + /* Get server port number */
8603 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
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.
8610 + DEBUGP("port found: %u\n", port_buf);
8612 + memset(&expect, 0, sizeof(expect));
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;
8620 + switch (req_p->proto) {
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;
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;
8639 + exp->expectfn = NULL;
8641 + ip_conntrack_expect_related(ct, &expect);
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);
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);
8657 + DEBUGP("packet evaluated. [expect]\n");
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)
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;
8674 + int dir = CTINFO2DIR(ctinfo);
8678 + DEBUGP("new packet to evaluate ..\n");
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");
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");
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");
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");
8713 + /* perform direction dependant protocol work */
8714 + if (dir == IP_CT_DIR_ORIGINAL) {
8716 + DEBUGP("packet is from the initiator. [cont]\n");
8718 + /* Tests if packet len is ok */
8719 + if ((tcplen - (tcph->doff * 4)) != 60) {
8720 + DEBUGP("packet length is not correct. [skip]\n");
8726 + DEBUGP("packet is from the receiver. [cont]\n");
8728 + /* Tests if packet len is ok */
8729 + if ((tcplen - (tcph->doff * 4)) != 32) {
8730 + DEBUGP("packet length is not correct. [skip]\n");
8735 + /* Get to the data */
8738 + /* Check the RPC data */
8739 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_tcp);
8746 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
8748 +static void fini(void);
8751 +static int __init init(void)
8754 + static char name[10];
8757 + /* If no port given, default to standard RPC port */
8758 + if (ports[0] == 0)
8759 + ports[0] = RPC_PORT;
8761 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
8762 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
8764 + if (ports[port] == RPC_PORT)
8765 + sprintf(name, "rpc");
8767 + sprintf(name, "rpc-%d", port);
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;
8775 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
8776 + rpc_helpers[port].mask.dst.protonum = 0xffff;
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);
8783 + rpc_helpers[port].help = help;
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));
8797 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
8800 + printk("ERROR registering port %d\n",
8811 +/* This function is intentionally _NOT_ defined as __exit, because
8812 + * it is needed by the init function */
8813 +static void fini(void)
8817 + DEBUGP("cleaning request list\n");
8818 + clean_request(&request_p_list_tcp);
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]);
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);
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
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
8844 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
8845 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
8851 + * ip_conntrack_rpc_udp.c,v 2.2 2003/01/12 18:30:00
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.
8858 + * Module load syntax:
8859 + * insmod ip_conntrack_rpc_udp.o ports=port1,port2,...port<MAX_PORTS>
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.
8866 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
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>
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>
8900 +#define MAX_PORTS 8
8901 +static int ports[MAX_PORTS];
8902 +static int ports_n_c = 0;
8905 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
8906 +MODULE_PARM_DESC(ports, "port numbers (TCP/UDP) of RPC portmapper servers");
8909 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
8910 +MODULE_DESCRIPTION("RPC UDP connection tracking module");
8911 +MODULE_LICENSE("GPL");
8914 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rpc_udp: " \
8917 +#define DEBUGP(format, args...)
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>
8925 +/* For future conections RPC, using client's cache bindings
8926 + * I'll use ip_conntrack_lock to lock these lists */
8928 +LIST_HEAD(request_p_list_udp);
8931 +static void delete_request_p(unsigned long request_p_ul)
8933 + struct request_p *p = (void *)request_p_ul;
8935 + WRITE_LOCK(&ipct_rpc_udp_lock);
8936 + LIST_DELETE(&request_p_list_udp, p);
8937 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
8943 +static void req_cl(struct request_p * r)
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);
8954 +static void clean_request(struct list_head *list)
8956 + struct list_head *first = list->prev;
8957 + struct list_head *temp = list->next;
8958 + struct list_head *aux;
8960 + if (list_empty(list))
8963 + while (first != temp) {
8965 + req_cl((struct request_p *)temp);
8968 + req_cl((struct request_p *)temp);
8973 +static void alloc_request_p(u_int32_t xid, u_int16_t proto, u_int32_t ip,
8976 + struct request_p *req_p;
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);
8984 + /* Refresh timeout */
8985 + if (del_timer(&req_p->timeout)) {
8986 + req_p->timeout.expires = jiffies + EXP;
8987 + add_timer(&req_p->timeout);
8989 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
8993 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
8995 + /* Allocate new request_p */
8996 + req_p = (struct request_p *) kmalloc(sizeof(struct request_p), GFP_ATOMIC);
8998 + DEBUGP("can't allocate request_p\n");
9001 + *req_p = ((struct request_p) {{ NULL, NULL }, xid, ip, port, proto,
9002 + { { NULL, NULL }, jiffies + EXP, (unsigned long)req_p,
9005 + /* Initialize timer */
9006 + init_timer(&req_p->timeout);
9007 + req_p->timeout.function = delete_request_p;
9008 + add_timer(&req_p->timeout);
9011 + WRITE_LOCK(&ipct_rpc_udp_lock);
9012 + list_prepend(&request_p_list_udp, req_p);
9013 + WRITE_UNLOCK(&ipct_rpc_udp_lock);
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)
9023 + struct request_p *req_p;
9025 + struct ip_conntrack_expect expect, *exp = &expect;
9027 + /* Translstion's buffer for XDR */
9028 + u_int16_t port_buf;
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.
9040 + /* perform direction dependant RPC work */
9041 + if (dir == IP_CT_DIR_ORIGINAL) {
9045 + /* Get RPC requestor */
9046 + if (IXDR_GET_INT32(data) != 3) {
9047 + DEBUGP("RPC packet contains an invalid (non \"get\") requestor. [skip]\n");
9050 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
9054 + /* Jump Credentials and Verfifier */
9055 + data = data + IXDR_GET_INT32(data) + 2;
9056 + data = data + IXDR_GET_INT32(data) + 2;
9058 + /* Get RPC procedure */
9059 + DEBUGP("RPC packet contains procedure request [%u]. [cont]\n",
9060 + (unsigned int)IXDR_GET_INT32(data));
9062 + /* Get RPC protocol and store against client parameters */
9064 + alloc_request_p(xid, IXDR_GET_INT32(data), ct->tuplehash[dir].tuple.src.ip,
9065 + ct->tuplehash[dir].tuple.src.u.all);
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));
9072 + DEBUGP("allocated RPC request for protocol %u. [done]\n",
9073 + (unsigned int)IXDR_GET_INT32(data));
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);
9083 + /* Drop unexpected packets */
9085 + DEBUGP("packet is not expected. [skip]\n");
9089 + /* Verifies if packet is really an RPC reply packet */
9091 + if (IXDR_GET_INT32(data) != 1) {
9092 + DEBUGP("packet is not a valid RPC reply. [skip]\n");
9096 + /* Is status accept? */
9098 + if (IXDR_GET_INT32(data)) {
9099 + DEBUGP("packet is not an RPC accept. [skip]\n");
9103 + /* Get Verifier length. Jump verifier */
9105 + data = data + IXDR_GET_INT32(data) + 2;
9107 + /* Is accpet status "success"? */
9108 + if (IXDR_GET_INT32(data)) {
9109 + DEBUGP("packet is not an RPC accept status of success. [skip]\n");
9113 + /* Get server port number */
9115 + port_buf = (u_int16_t) IXDR_GET_INT32(data);
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.
9122 + DEBUGP("port found: %u\n", port_buf);
9124 + memset(&expect, 0, sizeof(expect));
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;
9132 + switch (req_p->proto) {
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;
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;
9151 + exp->expectfn = NULL;
9153 + ip_conntrack_expect_related(ct, &expect);
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);
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);
9169 + DEBUGP("packet evaluated. [expect]\n");
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)
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);
9189 + const u_int16_t *chsm = (const u_int16_t *)udph + 3;
9192 + DEBUGP("new packet to evaluate ..\n");
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");
9201 + /* FIXME: Source route IP option packets --RR */
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");
9211 + /* perform direction dependant protocol work */
9212 + if (dir == IP_CT_DIR_ORIGINAL) {
9214 + DEBUGP("packet is from the initiator. [cont]\n");
9216 + /* Tests if packet len is ok */
9217 + if ((udplen - sizeof(struct udphdr)) != 56) {
9218 + DEBUGP("packet length is not correct. [skip]\n");
9224 + DEBUGP("packet is from the receiver. [cont]\n");
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");
9234 + /* Tests if packet len is ok */
9235 + if ((udplen - sizeof(struct udphdr)) != 28) {
9236 + DEBUGP("packet length is not correct. [skip]\n");
9242 + /* Get to the data */
9243 + /* udp *data == *correct */
9245 + /* Check the RPC data */
9246 + crp_ret = check_rpc_packet(data, dir, ct, request_p_list_udp);
9253 +static struct ip_conntrack_helper rpc_helpers[MAX_PORTS];
9255 +static void fini(void);
9258 +static int __init init(void)
9261 + static char name[10];
9264 + /* If no port given, default to standard RPC port */
9265 + if (ports[0] == 0)
9266 + ports[0] = RPC_PORT;
9268 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9269 + memset(&rpc_helpers[port], 0, sizeof(struct ip_conntrack_helper));
9271 + if (ports[port] == RPC_PORT)
9272 + sprintf(name, "rpc");
9274 + sprintf(name, "rpc-%d", port);
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;
9282 + rpc_helpers[port].tuple.dst.protonum = IPPROTO_UDP;
9283 + rpc_helpers[port].mask.dst.protonum = 0xffff;
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);
9290 + rpc_helpers[port].help = help;
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));
9304 + ret = ip_conntrack_helper_register(&rpc_helpers[port]);
9307 + printk("ERROR registering port %d\n",
9318 +/* This function is intentionally _NOT_ defined as __exit, because
9319 + * it is needed by the init function */
9320 +static void fini(void)
9324 + DEBUGP("cleaning request list\n");
9325 + clean_request(&request_p_list_udp);
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]);
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);
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
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
9350 + * ip_conntrack_rsh.c,v 1.0 2002/07/17 14:49:26
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.
9357 + * Module load syntax:
9358 + * insmod ip_conntrack_rsh.o ports=port1,port2,...port<MAX_PORTS>
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
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.
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
9375 + * I have no idea what "unix rshd man pages" these guys have .. but that
9376 + * is some pretty detailed docco!
9379 + * 4. Of the rsh protocol.
9380 + * -----------------------
9382 + * The rshd listens on TCP port #514. The following info is from the unix
9383 + * rshd man pages :
9385 + * "Service Request Protocol
9387 + * When the rshd daemon receives a service request, it initiates the
9388 + * following protocol:
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.
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.
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.
9406 + * 4. The rshd daemon retrieves the following information from the initial
9409 + * * A null-terminated string of at most 16 bytes interpreted as
9410 + * the user name of the user on the client host.
9412 + * * A null-terminated string of at most 16 bytes interpreted as
9413 + * the user name to be used on the local server host.
9415 + * * Another null-terminated string interpreted as a command line
9416 + * to be passed to a shell on the local server host.
9418 + * 5. The rshd daemon attempts to validate the user using the following steps:
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.
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.
9430 + * c. If the $HOME/.rhosts file exists, the rshd daemon tries to
9431 + * authenticate the user by checking the .rhosts file.
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.
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."
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>
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>
9456 +#define MAX_PORTS 8
9457 +static int ports[MAX_PORTS];
9458 +static int ports_n_c = 0;
9460 +MODULE_AUTHOR("Ian (Larry) Latter <Ian.Latter@mq.edu.au>");
9461 +MODULE_DESCRIPTION("RSH connection tracking module");
9462 +MODULE_LICENSE("GPL");
9464 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
9465 +MODULE_PARM_DESC(ports, "port numbers of RSH servers");
9468 +DECLARE_LOCK(ip_rsh_lock);
9469 +struct module *ip_conntrack_rsh = THIS_MODULE;
9472 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ip_conntrack_rsh: " \
9475 +#define DEBUGP(format, args...)
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)
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;
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?
9500 + DEBUGP("entered\n");
9502 + /* bail if packet is not from RSH client */
9503 + if (dir == IP_CT_DIR_REPLY)
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);
9513 + /* Not whole TCP header? */
9514 + if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) {
9515 + DEBUGP("tcplen = %u\n", (unsigned) tcplen);
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));
9529 + /* find the rsh stderr port */
9532 + for ( ; *data != 0 && maxoctet != 0; data++, maxoctet--) {
9537 + if (*data < 48 || *data > 57) {
9538 + DEBUGP("these aren't the packets you're looking for ..\n");
9541 + port = port * 10 + ( *data - 48 );
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");
9552 + LOCK_BH(&ip_rsh_lock);
9554 + /* new(,related) connection is;
9555 + * reply + dst (uint)port + src port (0:1023)
9557 + memset(&expect, 0, sizeof(expect));
9559 + /* save some discovered data, in case someone ever wants to write
9560 + * a NAT module for this bastard ..
9562 + exp_rsh_info->port = port;
9564 + DEBUGP("wrote info port=%u\n", exp_rsh_info->port);
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;
9574 + exp->mask.src.ip = 0xffffffff;
9575 + exp->mask.dst.ip = 0xffffffff;
9577 + exp->mask.src.u.tcp.port = htons(0xfc00);
9578 + exp->mask.dst.u.tcp.port = htons(0xfc00);
9579 + exp->mask.dst.protonum = 0xffff;
9581 + exp->expectfn = NULL;
9583 + ip_conntrack_expect_related(ct, &expect);
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));
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);
9601 +static struct ip_conntrack_helper rsh_helpers[MAX_PORTS];
9603 +static void fini(void);
9605 +static int __init init(void)
9608 + static char name[10];
9611 + /* If no port given, default to standard RSH port */
9612 + if (ports[0] == 0)
9613 + ports[0] = RSH_PORT;
9615 + for (port = 0; (port < MAX_PORTS) && ports[port]; port++) {
9616 + memset(&rsh_helpers[port], 0, sizeof(struct ip_conntrack_helper));
9618 + if (ports[port] == RSH_PORT)
9619 + sprintf(name, "rsh");
9621 + sprintf(name, "rsh-%d", port);
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;
9629 + rsh_helpers[port].tuple.dst.protonum = IPPROTO_TCP;
9630 + rsh_helpers[port].mask.dst.protonum = 0xffff;
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);
9637 + rsh_helpers[port].help = help;
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));
9651 + ret = ip_conntrack_helper_register(&rsh_helpers[port]);
9654 + printk("ERROR registering port %d\n",
9664 +/* This function is intentionally _NOT_ defined as __exit, because
9665 + * it is needed by the init function */
9666 +static void fini(void)
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]);
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
9681 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
9684 +#include <linux/config.h>
9685 #include <linux/types.h>
9686 #include <linux/ip.h>
9687 #include <linux/netfilter.h>
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>
9695 #include <net/checksum.h>
9697 #define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
9702 -print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
9703 +print_conntrack(char *buffer, struct ip_conntrack *conntrack)
9706 struct ip_conntrack_protocol *proto
9708 len += print_tuple(buffer + len,
9709 &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
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,
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);
9725 len += sprintf(buffer + len, "\n");
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 };
9732 +/* Sysctl support */
9734 +#ifdef CONFIG_SYSCTL
9736 +/* From ip_conntrack_core.c */
9737 +extern int ip_conntrack_max;
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;
9749 +/* From ip_conntrack_proto_udp.c */
9750 +extern unsigned long ip_ct_udp_timeout;
9751 +extern unsigned long ip_ct_udp_timeout_stream;
9753 +/* From ip_conntrack_proto_icmp.c */
9754 +extern unsigned long ip_ct_icmp_timeout;
9756 +/* From ip_conntrack_proto_icmp.c */
9757 +extern unsigned long ip_ct_generic_timeout;
9759 +static struct ctl_table_header *ip_ct_sysctl_header;
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,
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},
9804 +#define NET_IP_CONNTRACK_MAX 2089
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,
9814 +static ctl_table ip_ct_ipv4_table[] = {
9815 + {NET_IPV4, "ipv4", NULL, 0, 0555, ip_ct_netfilter_table, 0, 0, 0, 0, 0},
9819 +static ctl_table ip_ct_net_table[] = {
9820 + {CTL_NET, "net", NULL, 0, 0555, ip_ct_ipv4_table, 0, 0, 0, 0, 0},
9824 static int init_or_cleanup(int init)
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;
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");
9842 +#ifdef CONFIG_SYSCTL
9843 + unregister_sysctl_table(ip_ct_sysctl_header);
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 @@
9852 -/* FIXME: Allow NULL functions and sub in pointers to generic for
9855 + * ip_conntrack_protocol_register - Register layer 4 protocol helper
9856 + * @proto: structure describing this layer 4 protocol helper
9858 + * This function is called by layer 4 protocol helpers to register
9859 + * themselves with the conntrack core.
9861 int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
9864 struct list_head *i;
9866 + /* FIXME: Allow NULL functions and sub in pointers to generic for
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 @@
9876 + * ip_conntrack_protocol_unregister - Unregister layer 4 protocol helper
9877 + * @proto: structure describing this layer 4 protocol helper
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.
9883 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
9885 WRITE_LOCK(&ip_conntrack_lock);
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);
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);
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
9920 + * talk extension for IP connection tracking.
9921 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
9928 + * Module load syntax:
9929 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[01]
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
9935 + * The default is talk=1 ntalk=1 ntalk2=1
9937 + * The helper does not support simultaneous talk requests.
9940 + * ASCII art on talk protocols
9943 + * caller server callee server
9950 + * caller client ----------- callee client
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
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)
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>
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>
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");
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");
9991 +DECLARE_LOCK(ip_talk_lock);
9992 +struct module *ip_conntrack_talk = THIS_MODULE;
9995 +#define DEBUGP printk
9997 +#define DEBUGP(format, args...)
10000 +static int talk_expect(struct ip_conntrack *ct);
10001 +static int ntalk_expect(struct ip_conntrack *ct);
10003 +static int (*talk_expectfn[2])(struct ip_conntrack *ct) = {talk_expect, ntalk_expect};
10005 +static int talk_help_response(const struct iphdr *iph, size_t len,
10006 + struct ip_conntrack *ct,
10007 + enum ip_conntrack_info ctinfo,
10012 + struct talk_addr *addr)
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;
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),
10022 + if (!(answer == SUCCESS && type == mode))
10023 + return NF_ACCEPT;
10025 + memset(&expect, 0, sizeof(expect));
10027 + if (type == ANNOUNCE) {
10029 + DEBUGP("ip_ct_talk_help_response: ANNOUNCE\n");
10031 + /* update the talk info */
10032 + LOCK_BH(&ip_talk_lock);
10033 + exp_talk_info->port = htons(talk_port);
10035 + /* expect callee client -> caller server message */
10036 + exp->tuple = ((struct ip_conntrack_tuple)
10037 + { { ct->tuplehash[dir].tuple.src.ip,
10039 + { ct->tuplehash[dir].tuple.dst.ip,
10040 + { .tcp = { htons(talk_port) } },
10042 + exp->mask = ((struct ip_conntrack_tuple)
10043 + { { 0xFFFFFFFF, { 0 } },
10044 + { 0xFFFFFFFF, { .tcp = { 0xFFFF } }, 0xFFFF }});
10046 + exp->expectfn = talk_expectfn[talk_port - TALK_PORT];
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));
10052 + /* Ignore failure; should only happen with NAT */
10053 + ip_conntrack_expect_related(ct, &expect);
10054 + UNLOCK_BH(&ip_talk_lock);
10056 + if (type == LOOK_UP) {
10058 + DEBUGP("ip_ct_talk_help_response: LOOK_UP\n");
10060 + /* update the talk info */
10061 + LOCK_BH(&ip_talk_lock);
10062 + exp_talk_info->port = addr->ta_port;
10064 + /* expect callee client -> caller client connection */
10065 + exp->tuple = ((struct ip_conntrack_tuple)
10066 + { { ct->tuplehash[!dir].tuple.src.ip,
10069 + { addr->ta_port },
10071 + exp->mask = ((struct ip_conntrack_tuple)
10072 + { { 0xFFFFFFFF, { 0 } },
10073 + { 0xFFFFFFFF, { 0xFFFF }, 0xFFFF }});
10075 + exp->expectfn = NULL;
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));
10081 + /* Ignore failure; should only happen with NAT */
10082 + ip_conntrack_expect_related(ct, &expect);
10083 + UNLOCK_BH(&ip_talk_lock);
10086 + return NF_ACCEPT;
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,
10096 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10097 + const char *data = (const char *)udph + sizeof(struct udphdr);
10098 + int dir = CTINFO2DIR(ctinfo);
10101 + DEBUGP("ip_ct_talk_help: help entered\n");
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;
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;
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;
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));
10130 + if (dir == IP_CT_DIR_ORIGINAL)
10131 + return NF_ACCEPT;
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
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
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));
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;
10163 +static int lookup_help(const struct iphdr *iph, size_t len,
10164 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10166 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, LOOK_UP);
10169 +static int lookup_nhelp(const struct iphdr *iph, size_t len,
10170 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10172 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, LOOK_UP);
10175 +static struct ip_conntrack_helper lookup_helpers[2] =
10176 + { { { NULL, NULL },
10177 + "talk", /* name */
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 */
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 */
10200 +static int talk_expect(struct ip_conntrack *ct)
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);
10207 + return NF_ACCEPT; /* unused */
10210 +static int ntalk_expect(struct ip_conntrack *ct)
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);
10217 + return NF_ACCEPT; /* unused */
10220 +static int help(const struct iphdr *iph, size_t len,
10221 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10223 + return talk_help(iph, len, ct, ctinfo, TALK_PORT, ANNOUNCE);
10226 +static int nhelp(const struct iphdr *iph, size_t len,
10227 + struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
10229 + return talk_help(iph, len, ct, ctinfo, NTALK_PORT, ANNOUNCE);
10232 +static struct ip_conntrack_helper talk_helpers[2] =
10233 + { { { NULL, NULL },
10234 + "talk", /* name */
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 */
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 */
10257 +static int __init init(void)
10260 + ip_conntrack_helper_register(&talk_helpers[0]);
10261 + if (ntalk > 0 || ntalk2 > 0)
10262 + ip_conntrack_helper_register(&talk_helpers[1]);
10267 +static void __exit fini(void)
10270 + ip_conntrack_helper_unregister(&talk_helpers[0]);
10271 + if (ntalk > 0 || ntalk2 > 0)
10272 + ip_conntrack_helper_unregister(&talk_helpers[1]);
10275 +EXPORT_SYMBOL(ip_talk_lock);
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
10284 + * Licensed under GNU GPL version 2 Copyright Magnus Boden <mb@ozaba.mine.nu>
10287 + * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
10288 + * - port to newnat API
10292 +#include <linux/module.h>
10293 +#include <linux/ip.h>
10294 +#include <linux/udp.h>
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>
10301 +MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
10302 +MODULE_DESCRIPTION("Netfilter connection tracking module for tftp");
10303 +MODULE_LICENSE("GPL");
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");
10314 +#define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ": " \
10317 +#define DEBUGP(format, args...)
10320 +static int tftp_help(const struct iphdr *iph, size_t len,
10321 + struct ip_conntrack *ct,
10322 + enum ip_conntrack_info ctinfo)
10324 + struct udphdr *udph = (void *)iph + iph->ihl * 4;
10325 + struct tftphdr *tftph = (void *)udph + 8;
10326 + struct ip_conntrack_expect exp;
10328 + switch (ntohs(tftph->opcode)) {
10329 + /* RRQ and WRQ works the same way */
10330 + case TFTP_OPCODE_READ:
10331 + case TFTP_OPCODE_WRITE:
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));
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;
10344 + DEBUGP("expect: ");
10345 + DUMP_TUPLE(&exp.tuple);
10346 + DUMP_TUPLE(&exp.mask);
10347 + ip_conntrack_expect_related(ct, &exp);
10350 + DEBUGP("Unknown opcode\n");
10352 + return NF_ACCEPT;
10355 +static struct ip_conntrack_helper tftp[MAX_PORTS];
10356 +static char tftp_names[MAX_PORTS][10];
10358 +static void fini(void)
10362 + for (i = 0 ; i < ports_c; i++) {
10363 + DEBUGP("unregistering helper for port %d\n",
10365 + ip_conntrack_helper_unregister(&tftp[i]);
10369 +static int __init init(void)
10375 + ports[0]=TFTP_PORT;
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;
10389 + tmpname = &tftp_names[i][0];
10390 + if (ports[i] == TFTP_PORT)
10391 + sprintf(tmpname, "tftp");
10393 + sprintf(tmpname, "tftp-%d", i);
10394 + tftp[i].name = tmpname;
10396 + DEBUGP("port #%d: %d\n", i, ports[i]);
10398 + ret=ip_conntrack_helper_register(&tftp[i]);
10400 + printk("ERROR registering helper for port %d\n",
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
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
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.
10425 + * Module load syntax:
10426 + * insmod ip_nat_amanda.o
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>
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>
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);
10448 +#define DEBUGP(format, args...)
10449 +#define DUMP_OFFSET(x)
10452 +MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
10453 +MODULE_DESCRIPTION("Amanda network address translation module");
10454 +MODULE_LICENSE("GPL");
10456 +/* protects amanda part of conntracks */
10457 +DECLARE_LOCK_EXTERN(ip_amanda_lock);
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)
10465 + struct ip_nat_multi_range mr;
10466 + u_int32_t newdstip, newsrcip, newip;
10468 + struct ip_ct_amanda_expect *exp_info;
10469 + struct ip_conntrack *master = master_ct(ct);
10471 + IP_NF_ASSERT(info);
10472 + IP_NF_ASSERT(master);
10474 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
10476 + DEBUGP("nat_expected: We have a connection!\n");
10477 + exp_info = &ct->master->help.exp_amanda_info;
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));
10484 + port = exp_info->port;
10486 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
10487 + newip = newsrcip;
10489 + newip = newdstip;
10491 + DEBUGP("nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
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;
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) } });
10505 + return ip_nat_setup_info(ct, &mr, hooknum);
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)
10514 + /* DATA 99999 MESG 99999 INDEX 99999 */
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;
10521 + MUST_BE_LOCKED(&ip_amanda_lock);
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));
10526 + /* Alter conntrack's expectations. */
10528 + /* We can read expect here without conntrack lock, since it's
10529 + only set in ip_conntrack_amanda, with ip_amanda_lock held
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)
10542 + sprintf(buffer, "%u", port);
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));
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)
10558 + DEBUGP("ip_nat_amanda: no exp!!");
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;
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);
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");
10590 + exp->help.exp_amanda_info.offset = 0;
10591 + UNLOCK_BH(&ip_amanda_lock);
10593 + DEBUGP("ip_nat_amanda: NF_ACCEPT\n");
10594 + return NF_ACCEPT;
10597 +static struct ip_nat_helper ip_nat_amanda_helper;
10599 +/* This function is intentionally _NOT_ defined as __exit, because
10600 + * it is needed by init() */
10601 +static void fini(void)
10603 + DEBUGP("ip_nat_amanda: unregistering nat helper\n");
10604 + ip_nat_helper_unregister(&ip_nat_amanda_helper);
10607 +static int __init init(void)
10610 + struct ip_nat_helper *hlpr;
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;
10619 + hlpr->me = THIS_MODULE;
10620 + hlpr->expect = amanda_nat_expected;
10622 + hlpr->name = "amanda";
10625 + ("ip_nat_amanda: Trying to register nat helper\n");
10626 + ret = ip_nat_helper_register(hlpr);
10630 + ("ip_nat_amanda: error registering nat helper\n");
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
10644 /* NAT for netfilter; shared with compatibility layer. */
10646 /* (c) 1999 Paul `Rusty' Russell. Licenced under the GNU General
10647 - Public Licence. */
10649 -#define __NO_VERSION__
10651 + * Public Licence.
10652 + * (c) 2000-2002 by the netfilter core team <coreteam@netfilter.org>
10654 #include <linux/version.h>
10655 #include <linux/module.h>
10656 #include <linux/types.h>
10658 static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
10660 struct ip_nat_info *info = &conn->nat.info;
10661 + unsigned int hs, hp;
10663 if (!info->initialized)
10665 @@ -77,27 +77,31 @@
10666 IP_NF_ASSERT(info->bysource.conntrack);
10667 IP_NF_ASSERT(info->byipsproto.conntrack);
10669 + hs = hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src,
10670 + conn->tuplehash[IP_CT_DIR_ORIGINAL]
10671 + .tuple.dst.protonum);
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);
10678 WRITE_LOCK(&ip_nat_lock);
10679 - LIST_DELETE(&bysource[hash_by_src(&conn->tuplehash[IP_CT_DIR_ORIGINAL]
10681 - conn->tuplehash[IP_CT_DIR_ORIGINAL]
10682 - .tuple.dst.protonum)],
10683 - &info->bysource);
10685 - LIST_DELETE(&byipsproto
10686 - [hash_by_ipsproto(conn->tuplehash[IP_CT_DIR_REPLY]
10688 - conn->tuplehash[IP_CT_DIR_REPLY]
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);
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.) */
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
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.
10712 ip_nat_cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck)
10714 @@ -123,7 +127,14 @@
10718 -/* Is this tuple already taken? (not by us) */
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
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.
10728 ip_nat_used_tuple(const struct ip_conntrack_tuple *tuple,
10729 const struct ip_conntrack *ignored_conntrack)
10730 @@ -162,8 +173,8 @@
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))
10741 @@ -247,11 +258,12 @@
10742 const struct ip_conntrack *conntrack)
10744 unsigned int score = 0;
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,
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);
10757 @@ -434,7 +446,7 @@
10758 *tuple = *orig_tuple;
10759 while ((rptr = find_best_ips_proto_fast(tuple, mr, conntrack, hooknum))
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. */
10766 @@ -511,6 +523,19 @@
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
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.
10781 + * Note: The reply mappings are created automagically by this function.
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;
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))));
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",
10804 DEBUGP("Original: ");
10805 - DUMP_TUPLE(&orig_tp);
10806 + DUMP_TUPLE_RAW(&orig_tp);
10808 - DUMP_TUPLE(&new_tuple);
10809 + DUMP_TUPLE_RAW(&new_tuple);
10812 /* We now have two tuples (SRCIP/SRCPT/DSTIP/DSTPT):
10813 @@ -641,6 +668,14 @@
10816 info->initialized |= (1 << HOOK2MANIP(hooknum));
10819 + IP_NF_ASSERT(info->bysource.conntrack);
10820 + replace_in_hashes(conntrack, info);
10822 + place_in_hashes(conntrack, info);
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;
10834 DEBUGP("do_bindings: helper existing for (%p)\n", ct);
10836 @@ -817,19 +853,21 @@
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",
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,
10848 if (ret != NF_ACCEPT) {
10849 READ_UNLOCK(&ip_conntrack_lock);
10852 + helper_called = 1;
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,
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
10872 @@ -926,9 +964,9 @@
10873 &info->manips[i].manip,
10874 !info->manips[i].maniptype,
10876 - /* Outer packet needs to have IP header NATed like
10878 - } else if (info->manips[i].hooknum == hooknum) {
10879 + /* Outer packet needs to have IP header NATed like
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;
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);
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
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
10904 + * ip_nat_cuseeme.c v0.0.7 2003-02-18
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.
10911 + * Module load syntax:
10912 + * insmod ip_nat_cuseeme.o ports=port1,port2,...port<MAX_PORTS>
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.
10917 + * CuSeeMe Protocol Documentation:
10918 + * http://cu-seeme.net/squeek/tech/contents.html
10922 +#include <linux/module.h>
10923 +#include <linux/netfilter_ipv4.h>
10924 +#include <linux/ip.h>
10925 +#include <linux/udp.h>
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>
10934 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
10935 +MODULE_DESCRIPTION("Netfilter NAT helper for CuSeeMe");
10936 +MODULE_LICENSE("GPL");
10938 +#define MAX_PORTS 8
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");
10948 +#define DEBUGP printk
10950 +#define DEBUGP(format, args...)
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,
10959 + unsigned int datalen)
10961 + char new_port_ip[6];
10962 + struct cu_header *cu_head=(struct cu_header *)data;
10964 + DEBUGP("ip_nat_cuseeme: outgoing packet, ID %u, dest_family %u\n",
10965 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
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);
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));
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,
10994 + unsigned int datalen)
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;
11003 + DEBUGP("ip_nat_cuseeme: incoming packet, ID %u, dest_family %u\n",
11004 + ntohs(cu_head->data_type), ntohs(cu_head->dest_family));
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);
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));
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);
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));
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);
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);
11071 + off+=sizeof(struct client_info);
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));
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)
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];
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" : "???"
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;
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;
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);
11125 + cuseeme_mangle_incoming(ct, info, ctinfo, pskb, data, datalen);
11127 + return NF_ACCEPT;
11130 +static struct ip_nat_helper cuseeme[MAX_PORTS];
11131 +static char cuseeme_names[MAX_PORTS][14]; /* cuseeme-65535 */
11133 +static void fini(void)
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]);
11143 +static int __init init(void)
11149 + ports[0] = CUSEEME_PORT;
11151 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
11152 + memset(&cuseeme[i], 0, sizeof(struct ip_nat_helper));
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; */
11165 + tmpname = &cuseeme_names[i][0];
11166 + if (ports[i] == CUSEEME_PORT)
11167 + sprintf(tmpname, "cuseeme");
11169 + sprintf(tmpname, "cuseeme-%d", ports[i]);
11170 + cuseeme[i].name = tmpname;
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]);
11177 + printk("ip_nat_cuseeme: unable to register helper for port %d\n",
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
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) } });
11199 return ip_nat_setup_info(ct, &mr, hooknum);
11201 @@ -306,9 +306,6 @@
11202 ports[0] = FTP_PORT;
11204 for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
11206 - memset(&ftp[i], 0, sizeof(struct ip_nat_helper));
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
11216 + * H.323 'brute force' extension for NAT alteration.
11217 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
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>
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>
11240 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
11241 +MODULE_DESCRIPTION("H.323 'brute force' connection tracking module");
11242 +MODULE_LICENSE("GPL");
11244 +DECLARE_LOCK_EXTERN(ip_h323_lock);
11245 +struct module *ip_nat_h323 = THIS_MODULE;
11248 +#define DEBUGP printk
11250 +#define DEBUGP(format, args...)
11253 +/* FIXME: Time out? --RR */
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);
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);
11268 +static struct ip_nat_helper h245 =
11269 + { { NULL, NULL },
11270 + "H.245", /* name */
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 */
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)
11287 + struct ip_nat_multi_range mr;
11288 + u_int32_t newdstip, newsrcip, newip;
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;
11295 + IP_NF_ASSERT(info);
11296 + IP_NF_ASSERT(master);
11298 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
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;
11304 + LOCK_BH(&ip_h323_lock);
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));
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));
11324 + port = exp_info->port;
11325 + is_h225 = master_info->is_h225 == H225_PORT;
11326 + UNLOCK_BH(&ip_h323_lock);
11328 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
11329 + newip = newsrcip;
11331 + newip = newdstip;
11333 + DEBUGP("h225_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
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;
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 } });
11349 + ret = ip_nat_setup_info(ct, &mr, hooknum);
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;
11359 +static int h323_signal_address_fixup(struct ip_conntrack *ct,
11360 + struct sk_buff **pskb,
11361 + enum ip_conntrack_info ctinfo)
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;
11373 + MUST_BE_LOCKED(&ip_h323_lock);
11375 + DEBUGP("h323_signal_address_fixup: %s %s\n",
11376 + between(info->seq[IP_CT_DIR_ORIGINAL], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
11378 + between(info->seq[IP_CT_DIR_REPLY], ntohl(tcph->seq), ntohl(tcph->seq) + datalen)
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)))
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],
11388 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
11389 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
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))
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",
11404 + ntohl(tcph->seq),
11405 + ntohl(tcph->seq) + datalen);
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;
11416 + newip = ct->tuplehash[!info->dir].tuple.src.ip;
11417 + port = ct->tuplehash[!info->dir].tuple.src.u.tcp.port;
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))));
11425 + /* Modify the packet */
11426 + *(u_int32_t *)(data + info->offset[i]) = newip;
11427 + *(u_int16_t *)(data + info->offset[i] + 4) = port;
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))));
11435 + /* fix checksum information */
11437 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
11441 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
11442 + csum_partial((char *)tcph, tcph->doff*4,
11444 + ip_send_check(iph);
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)
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;
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);
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",
11476 + ntohl(tcph->seq),
11477 + ntohl(tcph->seq) + tcplen - tcph->doff * 4);
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;
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;
11498 + is_h225 = (master_info->is_h225 == H225_PORT);
11501 + newtuple.dst.protonum = IPPROTO_TCP;
11502 + newtuple.src.u.tcp.port = expect->tuple.src.u.tcp.port;
11504 + newtuple.dst.protonum = IPPROTO_UDP;
11505 + newtuple.src.u.udp.port = expect->tuple.src.u.udp.port;
11508 + /* Try to get same port: if not, try to change it. */
11509 + for (port = ntohs(info->port); port != 0; port++) {
11511 + newtuple.dst.u.tcp.port = htons(port);
11513 + newtuple.dst.u.udp.port = htons(port);
11515 + if (ip_conntrack_change_expect(expect, &newtuple) == 0)
11519 + DEBUGP("h323_data_fixup: no free port found!\n");
11523 + port = htons(port);
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))));
11529 + /* Modify the packet */
11530 + *(u_int32_t *)(data + info->offset) = newip;
11531 + *(u_int16_t *)(data + info->offset + 4) = port;
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))));
11537 + /* fix checksum information */
11538 + /* FIXME: usually repeated multiple times in the case of H.245! */
11540 + (*pskb)->csum = csum_partial((char *)tcph + tcph->doff*4,
11541 + tcplen - tcph->doff*4, 0);
11544 + tcph->check = tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr,
11545 + csum_partial((char *)tcph, tcph->doff*4,
11547 + ip_send_check(iph);
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)
11560 + struct ip_ct_h225_expect *exp_info;
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;
11581 + LOCK_BH(&ip_h323_lock);
11582 + if (!h323_signal_address_fixup(ct, pskb, ctinfo)) {
11583 + UNLOCK_BH(&ip_h323_lock);
11586 + UNLOCK_BH(&ip_h323_lock);
11587 + return NF_ACCEPT;
11590 + exp_info = &exp->help.exp_h225_info;
11592 + LOCK_BH(&ip_h323_lock);
11593 + if (!h323_data_fixup(exp_info, ct, pskb, ctinfo, exp)) {
11594 + UNLOCK_BH(&ip_h323_lock);
11597 + UNLOCK_BH(&ip_h323_lock);
11599 + return NF_ACCEPT;
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 */
11615 +static int __init init(void)
11619 + ret = ip_nat_helper_register(&h225);
11622 + printk("ip_nat_h323: cannot initialize the module!\n");
11627 +static void __exit fini(void)
11629 + ip_nat_helper_unregister(&h225);
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
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
11645 #include <linux/version.h>
11646 #include <linux/config.h>
11648 #include <net/icmp.h>
11649 #include <net/ip.h>
11650 #include <net/tcp.h>
11651 +#include <net/udp.h>
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 @@
11659 - struct tcphdr *tcph;
11662 struct ip_nat_seq *this_way, *other_way;
11664 DEBUGP("ip_nat_resize_packet: old_size = %u, new_size = %u\n",
11665 (*skb)->len, new_size);
11667 - iph = (*skb)->nh.iph;
11668 - tcph = (void *)iph + iph->ihl*4;
11669 - data = (void *)tcph + tcph->doff*4;
11671 dir = CTINFO2DIR(ctinfo);
11673 this_way = &ct->nat.info.seq[dir];
11674 @@ -84,37 +82,50 @@
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;
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);
11688 - LOCK_BH(&ip_nat_seqofs_lock);
11689 + LOCK_BH(&ip_nat_seqofs_lock);
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
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;
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
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 -
11715 - UNLOCK_BH(&ip_nat_seqofs_lock);
11716 + UNLOCK_BH(&ip_nat_seqofs_lock);
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);
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).
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
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
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;
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));
11760 /* insert data from buffer */
11761 memcpy(data + match_offset, rep_buffer, rep_len);
11762 @@ -207,6 +219,125 @@
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
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)
11781 + * Takes care about all the nasty sequence number changes, checksumming,
11782 + * skb enlargement, ...
11784 + * FIXME: should be unified with ip_nat_mangle_tcp_packet!!
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)
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;
11802 + udplen = (*skb)->len - iph->ihl*4;
11803 + newudplen = udplen - match_len + rep_len;
11804 + newlen = iph->ihl*4 + newudplen;
11806 + if (newlen > 65535) {
11807 + if (net_ratelimit())
11808 + printk("ip_nat_mangle_udp_packet: nat'ed packet "
11809 + "exceeds maximum packet size\n");
11813 + if ((*skb)->len != newlen) {
11814 + if (!ip_nat_resize_packet(skb, ct, ctinfo, newlen)) {
11815 + printk("resize_packet failed!!\n");
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);
11825 + if (net_ratelimit())
11826 + printk("Out of memory cloning TCP packet\n");
11829 + /* Rest of kernel will get very unhappy if we pass it
11830 + a suddenly-orphaned skbuff */
11832 + skb_set_owner_w(nskb, (*skb)->sk);
11837 + /* skb may be copied !! */
11838 + iph = (*skb)->nh.iph;
11839 + udph = (void *)iph + iph->ihl*4;
11840 + data = (void *)udph + sizeof(struct udphdr);
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));
11848 + /* insert data from buffer */
11849 + memcpy(data + match_offset, rep_buffer, rep_len);
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);
11857 + DEBUGP("ip_nat_mangle_udp_packet: Shrinking packet from "
11858 + "%u to %u bytes\n", (*skb)->len, newlen);
11859 + skb_trim(*skb, newlen);
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);
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),
11874 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
11875 + newudplen, IPPROTO_UDP,
11876 + csum_partial((char *)udph,
11877 + sizeof(struct udphdr),
11881 + ip_send_check(iph);
11886 /* Adjust one found SACK option including checksum correction */
11888 @@ -255,54 +386,49 @@
11892 -/* TCP SACK sequence number adjustment, return 0 if sack found and adjusted */
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)
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;
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);
11916 dir = CTINFO2DIR(ctinfo);
11918 - while (length > 0) {
11919 - int opcode = *ptr++;
11920 + while (ptr < optend) {
11921 + int opcode = ptr[0];
11926 - return !sack_adjusted;
11934 - if (opsize > length) /* no partial opts */
11935 - return !sack_adjusted;
11937 + /* no partial opts */
11938 + if (ptr + opsize > optend || opsize < 2)
11940 if (opcode == TCPOPT_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]);
11950 - sack_adjusted = 1;
11953 - length -= opsize;
11957 - return !sack_adjusted;
11960 /* TCP sequence number adjustment */
11961 @@ -363,6 +489,13 @@
11963 #define MODULE_MAX_NAMELEN 32
11966 + * ip_nat_helper_register - Register NAT application helper
11967 + * @me: structure describing the helper
11969 + * This function is called by NAT application helpers to register
11970 + * themselves with the NAT core.
11972 int ip_nat_helper_register(struct ip_nat_helper *me)
11975 @@ -382,9 +515,9 @@
11976 const char *tmp = me->me->name;
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);
11987 @@ -430,6 +563,13 @@
11992 + * ip_nat_helper_unregister - Unregister NAT application helper
11993 + * @me: structure describing the helper
11995 + * This function is called by NAT application helpers to unregister
11996 + * themselves from the NAT core.
11998 void ip_nat_helper_unregister(struct ip_nat_helper *me)
12001 @@ -467,7 +607,8 @@
12002 && ct_helper->me) {
12003 __MOD_DEC_USE_COUNT(ct_helper->me);
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);
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 @@
12017 for (i = 0; (i < MAX_PORTS) && ports[i] != 0; i++) {
12018 hlpr = &ip_nat_irc_helpers[i];
12020 - sizeof(struct ip_nat_helper));
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
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
12033 + * ip_nat_mms.c v0.3 2002-09-22
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.
12040 + * Module load syntax:
12041 + * insmod ip_nat_mms.o ports=port1,port2,...port<MAX_PORTS>
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.
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
12050 + * The SDP project people are reverse-engineering MMS:
12051 + * http://get.to/sdp
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 */
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>
12074 +#define DEBUGP printk
12075 +#define DUMP_BYTES(address, counter) \
12077 + int temp_counter; \
12078 + for(temp_counter=0; temp_counter<counter; ++temp_counter) { \
12079 + DEBUGP("%u ", (u8)*(address+temp_counter)); \
12084 +#define DEBUGP(format, args...)
12085 +#define DUMP_BYTES(address, counter)
12088 +#define MAX_PORTS 8
12089 +static int ports[MAX_PORTS];
12090 +static int ports_c = 0;
12092 +#ifdef MODULE_PARM
12093 +MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_PORTS) "i");
12096 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
12097 +MODULE_DESCRIPTION("Microsoft Windows Media Services (MMS) NAT module");
12098 +MODULE_LICENSE("GPL");
12100 +DECLARE_LOCK_EXTERN(ip_mms_lock);
12102 +/* FIXME: Time out? --RR */
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)
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;
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);
12122 + int zero_padding;
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];
12128 + MUST_BE_LOCKED(&ip_mms_lock);
12130 + /* what was the protocol again ? */
12131 + mms_proto = expect->tuple.dst.protonum;
12132 + sprintf(proto_string, "%u", mms_proto);
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);
12139 + newip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
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);
12155 + sprintf(buffer, "\\\\%u.%u.%u.%u\\%s\\%u",
12157 + expect->tuple.dst.protonum == IPPROTO_UDP ? "UDP"
12158 + : expect->tuple.dst.protonum == IPPROTO_TCP ? "TCP":proto_string,
12160 + DEBUGP("ip_nat_mms: new unicode string=%s\n", buffer);
12162 + memset(unicode_buffer, 0, sizeof(char)*75);
12164 + for (i=0; i<strlen(buffer); ++i)
12165 + *(unicode_buffer+i*2)=*(buffer+i);
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);
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);
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;
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);
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;
12196 + DEBUGP("ip_nat_mms: modified=> chunkLenLV=%u chunkLenLM=%u messageLength=%u\n",
12197 + *mms_chunkLenLV, *mms_chunkLenLM, *mms_messageLength);
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);
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)
12214 + struct ip_nat_multi_range mr;
12215 + u_int32_t newdstip, newsrcip, newip;
12217 + struct ip_conntrack *master = master_ct(ct);
12219 + IP_NF_ASSERT(info);
12220 + IP_NF_ASSERT(master);
12222 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
12224 + DEBUGP("ip_nat_mms: mms_nat_expected: We have a connection!\n");
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));
12234 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
12235 + newip = newsrcip;
12237 + newip = newdstip;
12239 + DEBUGP("ip_nat_mms: mms_nat_expected: IP to %u.%u.%u.%u\n", NIPQUAD(newip));
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;
12246 + return ip_nat_setup_info(ct, &mr, hooknum);
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)
12257 + struct iphdr *iph = (*pskb)->nh.iph;
12258 + struct tcphdr *tcph = (void *) iph + iph->ihl * 4;
12259 + unsigned int datalen;
12261 + struct ip_ct_mms_expect *ct_mms_info;
12264 + DEBUGP("ip_nat_mms: no exp!!");
12266 + ct_mms_info = &exp->help.exp_mms_info;
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;
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" : "???");
12286 + datalen = (*pskb)->len - iph->ihl * 4 - tcph->doff * 4;
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);
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);
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);
12311 + UNLOCK_BH(&ip_mms_lock);
12314 + UNLOCK_BH(&ip_mms_lock);
12316 + return NF_ACCEPT;
12319 +static struct ip_nat_helper mms[MAX_PORTS];
12320 +static char mms_names[MAX_PORTS][10];
12322 +/* Not __exit: called from init() */
12323 +static void fini(void)
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]);
12333 +static int __init init(void)
12338 + if (ports[0] == 0)
12339 + ports[0] = MMS_PORT;
12341 + for (i = 0; (i < MAX_PORTS) && ports[i]; i++) {
12343 + memset(&mms[i], 0, sizeof(struct ip_nat_helper));
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;
12354 + tmpname = &mms_names[i][0];
12355 + if (ports[i] == MMS_PORT)
12356 + sprintf(tmpname, "mms");
12358 + sprintf(tmpname, "mms-%d", i);
12359 + mms[i].name = tmpname;
12361 + DEBUGP("ip_nat_mms: register helper for port %d\n",
12363 + ret = ip_nat_helper_register(&mms[i]);
12366 + printk("ip_nat_mms: error registering "
12367 + "helper for port %d\n", ports[i]);
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
12384 + * ip_nat_pptp.c - Version 1.5
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
12394 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
12396 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
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)
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>)
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>
12430 +#define IP_NAT_PPTP_VERSION "1.5"
12432 +MODULE_LICENSE("GPL");
12433 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
12434 +MODULE_DESCRIPTION("Netfilter NAT helper module for PPTP");
12438 +#include "ip_conntrack_pptp_priv.h"
12439 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
12440 + ": " format, ## args)
12442 +#define DEBUGP(format, args...)
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)
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;
12458 + IP_NF_ASSERT(info);
12459 + IP_NF_ASSERT(master);
12460 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
12462 + DEBUGP("we have a connection!\n");
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;
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);
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);
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);
12499 + /* assume PAC->PNS */
12500 + newip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
12501 + newcid = htonl(ct_pptp_info->pac_call_id);
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",
12512 + DEBUGP("change key to 0x%x\n", ntohl(newcid));
12513 + ret = ip_nat_setup_info(ct, &mr, hooknum);
12515 + UNLOCK_BH(&ip_pptp_lock);
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)
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);
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;
12539 + u_int16_t msg, *cid = NULL, new_callid;
12541 + /* FIXME: size checks !!! */
12542 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
12543 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
12545 + new_callid = htons(ct_pptp_info->pns_call_id);
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 */
12555 + /* save original call ID in nat_info */
12556 + nat_pptp_info->pns_call_id = ct_pptp_info->pns_call_id;
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;
12562 + /* save new call ID in ct info */
12563 + ct_pptp_info->pns_call_id = ntohs(new_callid);
12565 + case PPTP_IN_CALL_REPLY:
12566 + cid = &pptpReq.icreq->callID;
12568 + case PPTP_CALL_CLEAR_REQUEST:
12569 + cid = &pptpReq.clrreq->callID;
12572 + DEBUGP("unknown outbound packet 0x%04x:%s\n", msg,
12573 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
12574 + /* fall through */
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;
12588 + IP_NF_ASSERT(cid);
12590 + DEBUGP("altering call id from 0x%04x to 0x%04x\n",
12591 + ntohs(*cid), ntohs(new_callid));
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));
12598 + return NF_ACCEPT;
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)
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);
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;
12618 + u_int16_t msg, new_cid = 0, new_pcid, *pcid = NULL, *cid = NULL;
12619 + u_int32_t old_dst_ip;
12621 + struct ip_conntrack_tuple t, inv_t;
12622 + struct ip_conntrack_tuple *orig_t, *reply_t;
12624 + /* FIXME: size checks !!! */
12625 + ctlh = (struct PptpControlHeader *) ((void *) pptph + sizeof(*pptph));
12626 + pptpReq.rawreq = (void *) ((void *) ctlh + sizeof(*ctlh));
12628 + new_pcid = htons(nat_pptp_info->pns_call_id);
12630 + switch (msg = ntohs(ctlh->messageType)) {
12631 + case PPTP_OUT_CALL_REPLY:
12632 + pcid = &pptpReq.ocack->peersCallID;
12633 + cid = &pptpReq.ocack->callID;
12635 + DEBUGP("outcall but no expectation\n");
12638 + old_dst_ip = oldexp->tuple.dst.ip;
12639 + t = oldexp->tuple;
12640 + invert_tuplepr(&inv_t, &t);
12642 + /* save original PAC call ID in nat_info */
12643 + nat_pptp_info->pac_call_id = ct_pptp_info->pac_call_id;
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);
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);
12666 + if (!ip_conntrack_change_expect(oldexp, &t)) {
12667 + DEBUGP("successfully changed expect\n");
12669 + DEBUGP("can't change expect\n");
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);
12674 + case PPTP_IN_CALL_CONNECT:
12675 + pcid = &pptpReq.iccon->peersCallID;
12678 + old_dst_ip = oldexp->tuple.dst.ip;
12679 + t = oldexp->tuple;
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;
12686 + /* expectation for PAC->PNS direction */
12687 + t.dst.ip = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
12690 + if (!ip_conntrack_change_expect(oldexp, &t)) {
12691 + DEBUGP("successfully changed expect\n");
12693 + DEBUGP("can't change expect\n");
12696 + case PPTP_IN_CALL_REQUEST:
12697 + /* only need to nat in case PAC is behind NAT box */
12699 + case PPTP_WAN_ERROR_NOTIFY:
12700 + pcid = &pptpReq.wanerr->peersCallID;
12702 + case PPTP_CALL_DISCONNECT_NOTIFY:
12703 + pcid = &pptpReq.disc->callID;
12707 + DEBUGP("unknown inbound packet %s\n",
12708 + (msg <= PPTP_MSG_MAX)? strMName[msg]:strMName[0]);
12709 + /* fall through */
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;
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));
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));
12739 + /* great, at least we don't need to resize packets */
12740 + return NF_ACCEPT;
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)
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;
12757 + DEBUGP("entering\n");
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;
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;
12782 + pptph = (struct pptp_pkt_hdr *) ((void *)tcph + tcph->doff*4);
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;
12791 + LOCK_BH(&ip_pptp_lock);
12793 + if (dir == IP_CT_DIR_ORIGINAL) {
12794 + /* reuqests sent by client to server (PNS->PAC) */
12795 + pptp_outbound_pkt(pskb, ct, ctinfo, exp);
12797 + /* response from the server to the client (PAC->PNS) */
12798 + pptp_inbound_pkt(pskb, ct, ctinfo, exp);
12801 + UNLOCK_BH(&ip_pptp_lock);
12803 + return NF_ACCEPT;
12806 +/* nat helper struct for control connection */
12807 +static struct ip_nat_helper pptp_tcp_helper = {
12808 + .list = { NULL, NULL },
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) }
12817 + .dst = { .ip = 0,
12818 + .u = { .all = 0 },
12819 + .protonum = IPPROTO_TCP
12823 + .mask = { .src = { .ip = 0,
12824 + .u = { .tcp = { .port = 0xFFFF } }
12826 + .dst = { .ip = 0,
12827 + .u = { .all = 0 },
12828 + .protonum = 0xFFFF
12831 + .help = tcp_help,
12832 + .expect = pptp_nat_expected
12836 +static int __init init(void)
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 "
12845 + printk("ip_nat_pptp version %s loaded\n", IP_NAT_PPTP_VERSION);
12849 +static void __exit fini(void)
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);
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
12863 + * ip_nat_proto_gre.c - Version 1.2
12865 + * NAT protocol helper module for GRE.
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.
12870 + * It has an optional key field, which may help us distinguishing two
12871 + * connections between the same two hosts.
12873 + * GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
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.
12879 + * Documentation about PPTP can be found in RFC 2637
12881 + * (C) 2000-2003 by Harald Welte <laforge@gnumonks.org>
12883 + * Development of this code funded by Astaro AG (http://www.astaro.com/)
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>
12895 +MODULE_LICENSE("GPL");
12896 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
12897 +MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
12900 +#define DEBUGP(format, args...) printk(KERN_DEBUG __FILE__ ":" __FUNCTION__ \
12901 + ": " format, ## args)
12903 +#define DEBUGP(x, args...)
12906 +/* is key in given range between min and max */
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)
12915 + if (maniptype == IP_NAT_MANIP_SRC)
12916 + key = tuple->src.u.gre.key;
12918 + key = tuple->dst.u.gre.key;
12920 + return ntohl(key) >= ntohl(min->gre.key)
12921 + && ntohl(key) <= ntohl(max->gre.key);
12924 +/* generate unique tuple ... */
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)
12931 + u_int32_t min, i, range_size;
12932 + u_int32_t key = 0, *keyptr;
12934 + if (maniptype == IP_NAT_MANIP_SRC)
12935 + keyptr = &tuple->src.u.gre.key;
12937 + keyptr = &tuple->dst.u.gre.key;
12939 + if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) {
12941 + switch (tuple->dst.u.gre.version) {
12943 + DEBUGP("NATing GRE version 0 (ct=%p)\n",
12946 + range_size = 0xffffffff;
12948 + case GRE_VERSION_PPTP:
12949 + DEBUGP("%p: NATing GRE PPTP\n",
12952 + range_size = 0xffff;
12955 + printk(KERN_WARNING "nat_gre: unknown GRE version\n");
12961 + min = ntohl(range->min.gre.key);
12962 + range_size = ntohl(range->max.gre.key) - min + 1;
12965 + DEBUGP("min = %u, range_size = %u\n", min, range_size);
12967 + for (i = 0; i < range_size; i++, key++) {
12968 + *keyptr = htonl(min + key % range_size);
12969 + if (!ip_nat_used_tuple(tuple, conntrack))
12973 + DEBUGP("%p: no NAT mapping\n", conntrack);
12978 +/* manipulate a GRE packet according to maniptype */
12980 +gre_manip_pkt(struct iphdr *iph, size_t len,
12981 + const struct ip_conntrack_manip *manip,
12982 + enum ip_nat_manip_type maniptype)
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;
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) {
12993 + if (!greh->key) {
12994 + DEBUGP("can't nat GRE w/o key\n");
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)));
13004 + *(gre_key(greh)) = manip->u.gre.key;
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));
13012 + DEBUGP("can't nat unknown GRE version\n");
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)
13024 + unsigned int len = 0;
13026 + if (mask->dst.u.gre.version)
13027 + len += sprintf(buffer + len, "version=%d ",
13028 + ntohs(match->dst.u.gre.version));
13030 + if (mask->dst.u.gre.protocol)
13031 + len += sprintf(buffer + len, "protocol=0x%x ",
13032 + ntohs(match->dst.u.gre.protocol));
13034 + if (mask->src.u.gre.key)
13035 + len += sprintf(buffer + len, "srckey=0x%x ",
13036 + ntohl(match->src.u.gre.key));
13038 + if (mask->dst.u.gre.key)
13039 + len += sprintf(buffer + len, "dstkey=0x%x ",
13040 + ntohl(match->src.u.gre.key));
13045 +/* print a range of keys */
13046 +static unsigned int
13047 +gre_print_range(char *buffer, const struct ip_nat_range *range)
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));
13055 + return sprintf(buffer, "keys 0x%u-0x%u ",
13056 + ntohl(range->min.gre.key),
13057 + ntohl(range->max.gre.key));
13062 +/* nat helper struct */
13063 +static struct ip_nat_protocol gre =
13064 + { { NULL, NULL }, "GRE", IPPROTO_GRE,
13067 + gre_unique_tuple,
13072 +static int __init init(void)
13074 + if (ip_nat_protocol_register(&gre))
13080 +static void __exit fini(void)
13082 + ip_nat_protocol_unregister(&gre);
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
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
13095 + * ip_nat_quake3.c v0.0.3 2002-08-31
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.
13102 + * Module load syntax:
13103 + * insmod ip_nat_quake3.o ports=port1,port2,...port<MAX_PORTS>
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
13109 + * Thanks to the Ethereal folks for their analysis of the Quake3 protocol.
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
13130 +#include <linux/module.h>
13131 +#include <linux/netfilter_ipv4.h>
13132 +#include <linux/ip.h>
13133 +#include <linux/udp.h>
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>
13142 +MODULE_AUTHOR("Filip Sneppe <filip.sneppe@cronos.be>");
13143 +MODULE_DESCRIPTION("Netfilter NAT helper for Quake III Arena");
13144 +MODULE_LICENSE("GPL");
13146 +#define MAX_PORTS 8
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");
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 */
13158 +#define DEBUGP printk
13160 +#define DEBUGP(format, args...)
13163 +static struct quake3_search quake3s_nat = { "****", "getserversResponse", sizeof("getserversResponse") - 1 };
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)
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);
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" : "???"
13185 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
13186 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
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;
13201 + DEBUGP("no conntrack expectation to modify\n");
13202 + return NF_ACCEPT;
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);
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 ) ) ) );
13214 + memset(&repl, 0, sizeof(repl));
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 ) );
13221 + ip_conntrack_change_expect(exp, &repl);
13224 + return NF_ACCEPT;
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)
13233 + const struct ip_conntrack *master = ct->master->expectant;
13234 + struct ip_nat_multi_range mr;
13235 + u_int32_t newsrcip, newdstip, newip;
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;
13243 + DEBUGP("ip_nat_quake3: quake3_nat_expected: here we are\n");
13244 + DUMP_TUPLE(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
13246 + IP_NF_ASSERT(info);
13247 + IP_NF_ASSERT(master);
13248 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
13250 + newdstip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
13251 + newsrcip = master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip;
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),
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),
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;
13280 + return ip_nat_setup_info(ct,&mr,hooknum);
13283 +static struct ip_nat_helper quake3[MAX_PORTS];
13284 +static char quake3_names[MAX_PORTS][13]; /* quake3-65535 */
13286 +static void fini(void)
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]);
13296 +static int __init init(void)
13302 + ports[0] = QUAKE3_MASTER_PORT;
13304 + for (i = 0 ; (i < MAX_PORTS) && ports[i] ; i++) {
13305 + memset(&quake3[i], 0, sizeof(struct ip_nat_helper));
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;
13316 + tmpname = &quake3_names[i][0];
13317 + if (ports[i] == QUAKE3_MASTER_PORT)
13318 + sprintf(tmpname, "quake3");
13320 + sprintf(tmpname, "quake3-%d", i);
13321 + quake3[i].name = tmpname;
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]);
13328 + printk("ip_nat_quake3: unable to register helper for port %d\n",
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
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 @@
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
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>
13372 @@ -1309,9 +1309,9 @@
13374 IP_NAT_HELPER_F_STANDALONE,
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 } },
13384 @@ -1320,9 +1320,9 @@
13386 IP_NAT_HELPER_F_STANDALONE,
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 } },
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 @@
13401 /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
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;
13409 info = &ct->nat.info;
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;
13419 @@ -130,6 +123,13 @@
13420 ret = call_expect(master_ct(ct), pskb,
13421 hooknum, ct, info);
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,
13430 ret = ip_nat_rule_find(pskb, hooknum, in, out,
13433 @@ -138,13 +138,6 @@
13434 WRITE_UNLOCK(&ip_nat_lock);
13439 - IP_NF_ASSERT(info->bysource.conntrack);
13440 - replace_in_hashes(ct, info);
13442 - place_in_hashes(ct, info);
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);
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;
13461 /* We must be after connection tracking and before packet filtering. */
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};
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 };
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 };
13479 -/* Protocol registration. */
13481 + * ip_nat_protocol_register - Register a layer 4 protocol helper
13482 + * @proto: structure describing this helper
13484 + * This function is called by NAT layer 4 protocol helpers to register
13485 + * themselvers with the NAT core.
13487 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
13490 @@ -261,9 +263,16 @@
13494 -/* Noone stores the protocol anywhere; simply delete it. */
13496 + * ip_nat_protocol_unregister - Unregister a layer 4 protocol helper
13497 + * @proto: sturcture describing the helper
13499 + * This function is called by NAT layer 4 protocol helpers to
13500 + * unregister themselves from the NAT core.
13502 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
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;
13512 +#ifdef CONFIG_IP_NF_NAT_LOCAL
13513 ret = nf_register_hook(&ip_nat_local_out_ops);
13515 printk("ip_nat_init: can't register local out hook.\n");
13516 goto cleanup_outops;
13518 -#ifdef CONFIG_IP_NF_NAT_LOCAL
13519 ret = nf_register_hook(&ip_nat_local_in_ops);
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:
13527 nf_unregister_hook(&ip_nat_local_out_ops);
13530 nf_unregister_hook(&ip_nat_out_ops);
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
13545 + * talk extension for UDP NAT alteration.
13546 + * Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
13553 + * Module load syntax:
13554 + * insmod ip_nat_talk.o talk=[0|1] ntalk=[0|1] ntalk2=[0|1]
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
13560 + * The default is talk=1 ntalk=1 ntalk2=1
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>
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>
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");
13594 +#define DEBUGP printk
13595 +#define IP_NAT_TALK_DEBUG
13597 +#define DEBUGP(format, args...)
13600 +/* FIXME: Time out? --RR */
13603 +mangle_packet(struct sk_buff **pskb,
13604 + struct ip_conntrack *ct,
13607 + struct talk_addr *addr,
13608 + struct talk_addr *ctl_addr)
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;
13614 + /* Fortunately talk sends a structure with the address and
13615 + port in it. The size of the packet won't change. */
13617 + if (ctl_addr == NULL) {
13619 + if (addr->ta_addr == INADDR_ANY)
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;
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;
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;
13644 + /* Fix checksums */
13645 + (*pskb)->csum = csum_partial((char *)udph + sizeof(struct udphdr), udplen - sizeof(struct udphdr), 0);
13647 + udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
13648 + csum_partial((char *)udph, sizeof(struct udphdr), (*pskb)->csum));
13650 + ip_send_check(iph);
13654 +static int talk_help_msg(struct ip_conntrack *ct,
13655 + struct sk_buff **pskb,
13657 + struct talk_addr *addr,
13658 + struct talk_addr *ctl_addr)
13663 + unsigned int verdict = NF_ACCEPT;
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),
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));
13677 + if (!mangle_packet(pskb, ct, newip, port, addr, ctl_addr))
13678 + verdict = NF_DROP;
13683 +static int talk_help_response(struct ip_conntrack *ct,
13684 + struct ip_conntrack_expect *exp,
13685 + struct sk_buff **pskb,
13688 + struct talk_addr *addr)
13692 + struct ip_conntrack_tuple t;
13693 + struct ip_ct_talk_expect *ct_talk_info;
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),
13699 + LOCK_BH(&ip_talk_lock);
13700 + ct_talk_info = &exp->help.exp_talk_info;
13702 + if (!(answer == SUCCESS
13703 + && (type == LOOK_UP || type == ANNOUNCE)
13704 + && exp != NULL)) {
13705 + UNLOCK_BH(&ip_talk_lock);
13706 + return NF_ACCEPT;
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");
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
13721 + t.dst.ip = newip;
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);
13728 + t.dst.u.udp.port = htons(port);
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);
13735 + UNLOCK_BH(&ip_talk_lock);
13737 + if (port == 0 || !mangle_packet(pskb, ct, newip, htons(port), addr, NULL))
13740 + return NF_ACCEPT;
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,
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);
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;
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),
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));
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));
13800 + if (dir == IP_CT_DIR_ORIGINAL) {
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));
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));
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));
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));
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));
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));
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)
13856 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, TALK_PORT);
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)
13866 + return talk_help(ct, exp, info, ctinfo, hooknum, pskb, NTALK_PORT);
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);
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 */
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)
13904 + struct ip_nat_multi_range mr;
13905 + u_int32_t newdstip, newsrcip, newip;
13907 + unsigned int ret;
13909 + struct ip_conntrack *master = master_ct(ct);
13911 + IP_NF_ASSERT(info);
13912 + IP_NF_ASSERT(master);
13914 + IP_NF_ASSERT(!(info->initialized & (1<<HOOK2MANIP(hooknum))));
13916 + DEBUGP("ip_nat_talk_expected: We have a connection!\n");
13918 + LOCK_BH(&ip_talk_lock);
13919 + port = ct->master->help.exp_talk_info.port;
13920 + UNLOCK_BH(&ip_talk_lock);
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" : "???",
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;
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));
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));
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;
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));
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));
13958 + if (HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC)
13959 + newip = newsrcip;
13961 + newip = newdstip;
13963 + DEBUGP("ip_nat_talk_expected: IP to %u.%u.%u.%u, port %u\n", NIPQUAD(newip), ntohs(port));
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;
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 } });
13978 + ret = ip_nat_setup_info(ct, &mr, hooknum);
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];
13988 +static int __init init(void)
13993 + ret = ip_nat_helper_register(&talk_helpers[0]);
13998 + if (ntalk > 0 || ntalk2 > 0) {
13999 + ret = ip_nat_helper_register(&talk_helpers[1]);
14001 + if (ret != 0 && talk > 0)
14002 + ip_nat_helper_unregister(&talk_helpers[0]);
14007 +static void __exit fini(void)
14010 + ip_nat_helper_unregister(&talk_helpers[0]);
14011 + if (ntalk > 0 || ntalk2 > 0)
14012 + ip_nat_helper_unregister(&talk_helpers[1]);
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
14022 + * Licensed under GNU GPL version 2 Copyright Magnus Boden <mb@ozaba.mine.nu>
14025 + * Thu 21 Mar 2002 Harald Welte <laforge@gnumonks.org>
14026 + * - Port to newnat API
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
14032 + * iptables -t nat -A POSTROUTING { -j MASQUERADE , -j SNAT --to-source x.x.x.x }
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.
14040 +#include <linux/module.h>
14041 +#include <linux/netfilter_ipv4.h>
14042 +#include <linux/ip.h>
14043 +#include <linux/udp.h>
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>
14052 +MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>");
14053 +MODULE_DESCRIPTION("Netfilter NAT helper for tftp");
14054 +MODULE_LICENSE("GPL");
14056 +#define MAX_PORTS 8
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");
14066 +#define DEBUGP(format, args...) printk(__FILE__ ":" __FUNCTION__ ": " \
14069 +#define DEBUGP(format, args...)
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)
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;
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;
14090 + DEBUGP("no conntrack expectation to modify\n");
14091 + return NF_ACCEPT;
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;
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);
14108 + DEBUGP("Unknown opcode\n");
14111 + return NF_ACCEPT;
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)
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;
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;
14131 + IP_NF_ASSERT(info);
14132 + IP_NF_ASSERT(master);
14133 + IP_NF_ASSERT(!(info->initialized & (1 << HOOK2MANIP(hooknum))));
14135 + mr.rangesize = 1;
14136 + mr.range[0].flags = IP_NAT_RANGE_MAP_IPS;
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));
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;
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));
14158 + return ip_nat_setup_info(ct,&mr,hooknum);
14161 +static struct ip_nat_helper tftp[MAX_PORTS];
14162 +static char tftp_names[MAX_PORTS][10];
14164 +static void fini(void)
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]);
14174 +static int __init init(void)
14180 + ports[0] = TFTP_PORT;
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;
14192 + tmpname = &tftp_names[i][0];
14193 + if (ports[i] == TFTP_PORT)
14194 + sprintf(tmpname, "tftp");
14196 + sprintf(tmpname, "tftp-%d", i);
14197 + tftp[i].name = tmpname;
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]);
14204 + printk("ip_nat_tftp: unable to register for port %d\n",
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
14220 +/* Kernel module for IP pool management */
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>
14236 +#define DP(format, args...)
14239 +MODULE_LICENSE("GPL");
14241 +#define NR_POOL 16
14242 +static int nr_pool = NR_POOL;/* overwrite this when loading module */
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 */
14253 +static struct ip_pool *POOL;
14255 +static inline struct ip_pool *lookup(ip_pool_t index)
14257 + if (index < 0 || index >= nr_pool) {
14258 + DP("ip_pool:lookup: bad index %d\n", index);
14261 + return POOL+index;
14264 +int ip_pool_match(ip_pool_t index, u_int32_t addr)
14266 + struct ip_pool *pool = lookup(index);
14269 + if (!pool || !pool->members)
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)) {
14277 +#ifdef CONFIG_IP_POOL_STATISTICS
14278 + pool->nr_match++;
14282 +#ifdef CONFIG_IP_POOL_STATISTICS
14286 + read_unlock_bh(&pool->lock);
14290 +static int pool_change(ip_pool_t index, u_int32_t addr, int isdel)
14292 + struct ip_pool *pool;
14295 + pool = lookup(index);
14296 + if ( !pool || !pool->members
14297 + || addr < pool->first_ip || addr > pool->last_ip)
14299 + read_lock_bh(&pool->lock);
14300 + if (pool->members && addr >= pool->first_ip && addr <= pool->last_ip) {
14301 + addr -= pool->first_ip;
14303 + ? (0 != test_and_clear_bit(addr, pool->members))
14304 + : (0 != test_and_set_bit(addr, pool->members));
14306 + read_unlock_bh(&pool->lock);
14310 +int ip_pool_mod(ip_pool_t index, u_int32_t addr, int isdel)
14312 + int res = pool_change(index,addr,isdel);
14314 + if (!isdel) res = !res;
14318 +static inline int bitmap_bytes(u_int32_t a, u_int32_t b)
14320 + return 4*((((b-a+8)/8)+3)/4);
14323 +static inline int poolbytes(ip_pool_t index)
14325 + struct ip_pool *pool = lookup(index);
14327 + return pool ? bitmap_bytes(pool->first_ip, pool->last_ip) : 0;
14330 +static int setpool(
14336 + struct ip_pool_request req;
14338 + DP("ip_pool:setpool: optval=%d, user=%p, len=%d\n", optval, user, len);
14339 + if (!capable(CAP_NET_ADMIN))
14341 + if (optval != SO_IP_POOL)
14343 + if (len != sizeof(req))
14345 + if (copy_from_user(&req, user, sizeof(req)) != 0)
14347 + printk("obsolete op - upgrade your ippool(8) utility.\n");
14351 +static int getpool(
14357 + struct ip_pool_request req;
14358 + struct ip_pool *pool;
14361 + void *newmembers;
14364 + DP("ip_pool:getpool: optval=%d, user=%p\n", optval, user);
14365 + if (!capable(CAP_NET_ADMIN))
14367 + if (optval != SO_IP_POOL)
14369 + if (*len != sizeof(req)) {
14372 + if (copy_from_user(&req, user, sizeof(req)) != 0)
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");
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)
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);
14392 + if (!pool->members)
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);
14402 + if (!pool->members)
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);
14413 + read_lock_bh(&pool->lock);
14414 + if (!pool->members) {
14415 + DP("ip_pool TEST_ADDR no members in pool\n");
14417 + goto unlock_and_return_res;
14419 + req.addr = ntohl(req.addr);
14420 + if (req.addr < pool->first_ip) {
14421 + DP("ip_pool TEST_ADDR address < pool bounds\n");
14423 + goto unlock_and_return_res;
14425 + if (req.addr > pool->last_ip) {
14426 + DP("ip_pool TEST_ADDR address > pool bounds\n");
14428 + goto unlock_and_return_res;
14430 + req.addr = (0 != test_bit((req.addr - pool->first_ip),
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");
14437 + case IP_POOL_DESTROY:
14438 + DP("ip_pool DESTROY not yet implemented.\n");
14440 + case IP_POOL_INIT:
14441 + DP("ip_pool INIT 0x%08x-0x%08x\n", req.addr, req.addr2);
14442 + pool = lookup(req.index);
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");
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);
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);
14463 + goto unlock_and_return_res;
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);
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));
14481 + DP("ip_pool:getpool bad op %d\n", req.op);
14486 +unlock_and_return_res:
14488 + read_unlock_bh(&pool->lock);
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,
14498 +MODULE_PARM(nr_pool, "i");
14500 +static int __init init(void)
14505 + if (nr_pool < 1) {
14506 + printk("ip_pool module init: bad nr_pool %d\n", nr_pool);
14509 + POOL = kmalloc(nr_pool * sizeof(*POOL), GFP_KERNEL);
14511 + printk("ip_pool module init: out of memory for nr_pool %d\n",
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;
14523 + res = nf_register_sockopt(&so_pool);
14524 + DP("ip_pool:init %d pools, result %d\n", nr_pool, res);
14532 +static void __exit fini(void)
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;
14546 + DP("ip_pool:fini these are the famous last words\n");
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);
14559 - goto err_out_unlock;
14560 + goto err_out_free_nskb;
14562 + /* netlink_unicast will either free the nskb or attach it to a socket */
14563 status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
14565 goto err_out_unlock;
14566 @@ -312,6 +313,9 @@
14568 write_unlock_bh(&queue_lock);
14571 +err_out_free_nskb:
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
14580 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
14581 * Copyright (C) 2009-2002 Netfilter core team <coreteam@netfilter.org>
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
14587 * 19 Jan 2002 Harald Welte <laforge@gnumonks.org>
14588 * - increase module usage count as soon as we have rules inside
14591 #include <linux/proc_fs.h>
14593 #include <linux/netfilter_ipv4/ip_tables.h>
14594 +#include <linux/netfilter_ipv4/ip_logging.h>
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",
14606 /*#define DEBUG_IP_FIREWALL*/
14607 /*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
14608 @@ -68,13 +83,12 @@
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).
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
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.
14625 To be cache friendly on SMP, we arrange them like so:
14627 @@ -251,6 +265,39 @@
14628 return (struct ipt_entry *)(base + offset);
14632 +get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
14633 + char **chainname, u_int16_t *rulenum)
14635 + struct ipt_entry_target *t;
14642 + t = ipt_get_target(s);
14643 + if (strcmp(t->u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
14644 + *chainname = t->data;
14651 +/* All zeroes == unconditional rule. */
14653 +unconditional(const struct ipt_ip *ip)
14657 + for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
14658 + if (((__u32 *)ip)[i])
14664 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
14666 ipt_do_table(struct sk_buff **pskb,
14667 @@ -326,6 +373,27 @@
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;
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);
14688 + nf_log_ip_packet(pskb, hook, in, out, "TRACE: %s/%s/%u ",
14689 + table->name, chainname, rulenum);
14692 /* Standard target? */
14693 if (!t->u.kernel.target->target) {
14695 @@ -482,19 +550,6 @@
14696 return find_inlist_lock(&ipt_target, name, "ipt_", error, mutex);
14699 -/* All zeroes == unconditional rule. */
14701 -unconditional(const struct ipt_ip *ip)
14705 - for (i = 0; i < sizeof(*ip)/sizeof(__u32); i++)
14706 - if (((__u32 *)ip)[i])
14712 /* Figures out from what hook each rule can be called: returns 0 if
14713 there are loops. Puts hook bitmask in comefrom. */
14715 @@ -502,6 +557,9 @@
14719 + /* keep track of where we have been: */
14720 + unsigned char *been = vmalloc(newinfo->size);
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 @@
14727 /* Set initial back pointer. */
14728 e->counters.pcnt = pos;
14729 + memset(been, 0, newinfo->size);
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);
14741 @@ -569,10 +629,14 @@
14743 int newpos = t->verdict;
14745 - if (strcmp(t->target.u.user.name,
14746 + if ( (pos < 0 || pos >= newinfo->size
14748 + && strcmp(t->target.u.user.name,
14749 IPT_STANDARD_TARGET) == 0
14751 /* This a jump; chase it. */
14752 + if (pos >= 0 && pos < newinfo->size)
14754 duprintf("Jump rule %u -> %u\n",
14757 @@ -588,6 +652,7 @@
14759 duprintf("Finished chain %u\n", hook);
14765 @@ -1630,7 +1695,7 @@
14766 u_int8_t type, u_int8_t code,
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))
14774 @@ -1699,14 +1764,15 @@
14775 = { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
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)
14783 if ((*count)++ >= start_offset) {
14784 unsigned int namelen;
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 */
14792 @@ -1724,7 +1790,7 @@
14793 if (down_interruptible(&ipt_mutex) != 0)
14796 - LIST_FIND(&ipt_tables, print_name, struct ipt_table *,
14797 + LIST_FIND(&ipt_tables, print_name, void *,
14798 offset, buffer, length, &pos, &count);
14801 @@ -1733,6 +1799,46 @@
14802 *start=(char *)((unsigned long)count-offset);
14806 +static int ipt_get_targets(char *buffer, char **start, off_t offset, int length)
14809 + unsigned int count = 0;
14811 + if (down_interruptible(&ipt_mutex) != 0)
14814 + LIST_FIND(&ipt_target, print_name, void *,
14815 + offset, buffer, length, &pos, &count);
14819 + *start = (char *)((unsigned long)count - offset);
14823 +static int ipt_get_matches(char *buffer, char **start, off_t offset, int length)
14826 + unsigned int count = 0;
14828 + if (down_interruptible(&ipt_mutex) != 0)
14831 + LIST_FIND(&ipt_match, print_name, void *,
14832 + offset, buffer, length, &pos, &count);
14836 + *start = (char *)((unsigned long)count - offset);
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 },
14845 #endif /*CONFIG_PROC_FS*/
14847 static int __init init(void)
14848 @@ -1758,13 +1864,19 @@
14849 #ifdef CONFIG_PROC_FS
14851 struct proc_dir_entry *proc;
14854 - proc = proc_net_create("ip_tables_names", 0, ipt_get_tables);
14856 - nf_unregister_sockopt(&ipt_sockopts);
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);
14863 + proc_net_remove(ipt_proc_entry[i].name);
14864 + nf_unregister_sockopt(&ipt_sockopts);
14867 + proc->owner = THIS_MODULE;
14869 - proc->owner = THIS_MODULE;
14873 @@ -1776,7 +1888,11 @@
14875 nf_unregister_sockopt(&ipt_sockopts);
14876 #ifdef CONFIG_PROC_FS
14877 - proc_net_remove("ip_tables_names");
14880 + for (i = 0; ipt_proc_entry[i].name; i++)
14881 + proc_net_remove(ipt_proc_entry[i].name);
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 @@
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)
14898 + off_t offset, int length)
14900 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14901 - /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */
14904 struct ip_chain *i;
14905 struct ip_fwkernel *j = ip_fw_chains->chain;
14906 unsigned long flags;
14907 @@ -1612,9 +1604,6 @@
14912 - memset(j->counters, 0,
14913 - sizeof(struct ip_counters)*NUM_SLOTS);
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 */
14923 #if defined(CONFIG_IP_FIREWALL) || defined(CONFIG_IP_ACCT)
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)
14929 off_t pos=0, begin=0;
14931 @@ -1181,12 +1180,6 @@
14937 - /* This needs to be done at this specific place! */
14944 @@ -1200,69 +1193,30 @@
14947 #ifdef CONFIG_IP_ACCT
14949 static int ip_acct_procinfo(char *buffer, char **start, off_t offset,
14951 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14957 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14958 - /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */
14961 - return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length,
14963 + return ip_chain_procinfo(IP_FW_ACCT, buffer,start, offset,length);
14968 #ifdef CONFIG_IP_FIREWALL
14970 static int ip_fw_in_procinfo(char *buffer, char **start, off_t offset,
14972 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14978 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14979 - /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */
14982 - return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length,
14984 + return ip_chain_procinfo(IP_FW_IN, buffer,start,offset,length);
14987 static int ip_fw_out_procinfo(char *buffer, char **start, off_t offset,
14989 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
14995 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
14996 - /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */
14999 - return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length,
15001 + return ip_chain_procinfo(IP_FW_OUT, buffer,start,offset,length);
15004 static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
15006 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,29)
15012 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,29)
15013 - /* FIXME: No more `atomic' read and reset. Wonderful 8-( --RR */
15016 - return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length,
15018 + return ip_chain_procinfo(IP_FW_FWD, buffer,start,offset,length);
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
15027 + * This is a module which is used for setting the skb->priority field
15028 + * of an skb for qdisc classification.
15031 +#include <linux/module.h>
15032 +#include <linux/skbuff.h>
15033 +#include <linux/ip.h>
15034 +#include <net/checksum.h>
15036 +#include <linux/netfilter_ipv4/ip_tables.h>
15037 +#include <linux/netfilter_ipv4/ipt_CLASSIFY.h>
15039 +MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
15040 +MODULE_LICENSE("GPL");
15041 +MODULE_DESCRIPTION("iptables qdisc classification target module");
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,
15051 + const struct ipt_classify_target_info *clinfo = targinfo;
15053 + if((*pskb)->priority != clinfo->priority) {
15054 + (*pskb)->priority = clinfo->priority;
15055 + (*pskb)->nfcache |= NFC_ALTERED;
15058 + return IPT_CONTINUE;
15062 +checkentry(const char *tablename,
15063 + const struct ipt_entry *e,
15065 + unsigned int targinfosize,
15066 + unsigned int hook_mask)
15068 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_classify_target_info))){
15069 + printk(KERN_ERR "CLASSIFY: invalid size (%u != %u).\n",
15071 + IPT_ALIGN(sizeof(struct ipt_classify_target_info)));
15075 + if (hook_mask & ~(1 << NF_IP_POST_ROUTING)) {
15076 + printk(KERN_ERR "CLASSIFY: only valid in POST_ROUTING.\n");
15080 + if (strcmp(tablename, "mangle") != 0) {
15081 + printk(KERN_WARNING "CLASSIFY: can only be called from "
15082 + "\"mangle\" table, not \"%s\".\n",
15090 +static struct ipt_target ipt_classify_reg
15091 += { { NULL, NULL }, "CLASSIFY", target, checkentry, NULL, THIS_MODULE };
15093 +static int __init init(void)
15095 + if (ipt_register_target(&ipt_classify_reg))
15101 +static void __exit fini(void)
15103 + ipt_unregister_target(&ipt_classify_reg);
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
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
15115 +#include <linux/module.h>
15116 +#include <linux/skbuff.h>
15117 +#include <linux/ip.h>
15118 +#include <net/checksum.h>
15120 +#include <linux/netfilter_ipv4/ip_tables.h>
15121 +#include <linux/netfilter_ipv4/ipt_CONNMARK.h>
15122 +#include <linux/netfilter_ipv4/ip_conntrack.h>
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,
15132 + const struct ipt_connmark_target_info *markinfo = targinfo;
15134 + enum ip_conntrack_info ctinfo;
15135 + struct ip_conntrack *ct = ip_conntrack_get((*pskb), &ctinfo);
15137 + switch(markinfo->mode) {
15138 + case IPT_CONNMARK_SET:
15139 + ct->mark = markinfo->mark;
15141 + case IPT_CONNMARK_SAVE:
15142 + ct->mark = (*pskb)->nfmark;
15144 + case IPT_CONNMARK_RESTORE:
15145 + if (ct->mark != (*pskb)->nfmark) {
15146 + (*pskb)->nfmark = ct->mark;
15147 + (*pskb)->nfcache |= NFC_ALTERED;
15153 + return IPT_CONTINUE;
15157 +checkentry(const char *tablename,
15158 + const struct ipt_entry *e,
15160 + unsigned int targinfosize,
15161 + unsigned int hook_mask)
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",
15167 + IPT_ALIGN(sizeof(struct ipt_connmark_target_info)));
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);
15181 +static struct ipt_target ipt_connmark_reg
15182 += { { NULL, NULL }, "CONNMARK", target, checkentry, NULL, THIS_MODULE };
15184 +static int __init init(void)
15186 + if (ipt_register_target(&ipt_connmark_reg))
15192 +static void __exit fini(void)
15194 + ipt_unregister_target(&ipt_connmark_reg);
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
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,
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
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>
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,
15231 + struct ipt_imq_info *mr = (struct ipt_imq_info*)targinfo;
15233 + (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
15234 + (*pskb)->nfcache |= NFC_ALTERED;
15236 + return IPT_CONTINUE;
15239 +static int imq_checkentry(const char *tablename,
15240 + const struct ipt_entry *e,
15242 + unsigned int targinfosize,
15243 + unsigned int hook_mask)
15245 + struct ipt_imq_info *mr;
15247 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_imq_info))) {
15248 + printk(KERN_WARNING "IMQ: invalid targinfosize\n");
15251 + mr = (struct ipt_imq_info*)targinfo;
15253 + if (strcmp(tablename, "mangle") != 0) {
15254 + printk(KERN_WARNING
15255 + "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
15260 + if (mr->todev > IMQ_MAX_DEVS) {
15261 + printk(KERN_WARNING
15262 + "IMQ: invalid device specified, highest is %u\n",
15270 +static struct ipt_target ipt_imq_reg = {
15279 +static int __init init(void)
15281 + if (ipt_register_target(&ipt_imq_reg))
15287 +static void __exit fini(void)
15289 + ipt_unregister_target(&ipt_imq_reg);
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
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>
15305 +#include <linux/netfilter_ipv4/ip_tables.h>
15306 +#include <linux/netfilter_ipv4/ipt_IPMARK.h>
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");
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,
15320 + const struct ipt_ipmark_target_info *ipmarkinfo = targinfo;
15322 + struct iphdr *iph = (*pskb)->nh.iph;
15324 + unsigned long mark;
15327 + if(ipmarkinfo->addr == IPT_IPMARK_SRC)
15328 + mark = (unsigned long) iph->saddr;
15330 + mark = (unsigned long) iph->daddr;
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;
15337 + mark &= ipmarkinfo->andmask;
15338 + mark |= ipmarkinfo->ormask;
15340 + if((*pskb)->nfmark != mark) {
15341 + (*pskb)->nfmark = mark;
15342 + (*pskb)->nfcache |= NFC_ALTERED;
15344 + return IPT_CONTINUE;
15348 +checkentry(const char *tablename,
15349 + const struct ipt_entry *e,
15351 + unsigned int targinfosize,
15352 + unsigned int hook_mask)
15354 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_ipmark_target_info))) {
15355 + printk(KERN_WARNING "IPMARK: targinfosize %u != %Zu\n",
15357 + IPT_ALIGN(sizeof(struct ipt_ipmark_target_info)));
15361 + if (strcmp(tablename, "mangle") != 0) {
15362 + printk(KERN_WARNING "IPMARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15369 +static struct ipt_target ipt_ipmark_reg
15370 += { { NULL, NULL }, "IPMARK", target, checkentry, NULL, THIS_MODULE };
15372 +static int __init init(void)
15374 + if (ipt_register_target(&ipt_ipmark_reg))
15380 +static void __exit fini(void)
15382 + ipt_unregister_target(&ipt_ipmark_reg);
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
15392 + * Strip all IP options in the IP packet header.
15394 + * (C) 2001 by Fabrice MARIE <fabrice@netfilter.org>
15395 + * This software is distributed under GNU GPL v2, 1991
15398 +#include <linux/module.h>
15399 +#include <linux/skbuff.h>
15400 +#include <linux/ip.h>
15401 +#include <net/checksum.h>
15403 +#include <linux/netfilter_ipv4/ip_tables.h>
15405 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
15406 +MODULE_DESCRIPTION("Strip all options in IPv4 packets");
15407 +MODULE_LICENSE("GPL");
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,
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;
15424 + /* if no options in packet then nothing to clear. */
15425 + if (iph->ihl * 4 == sizeof(struct iphdr))
15426 + return IPT_CONTINUE;
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;
15435 + skb->nfcache |= NFC_ALTERED;
15437 + return IPT_CONTINUE;
15441 +checkentry(const char *tablename,
15442 + const struct ipt_entry *e,
15444 + unsigned int targinfosize,
15445 + unsigned int hook_mask)
15447 + if (strcmp(tablename, "mangle")) {
15448 + printk(KERN_WARNING "IPV4OPTSSTRIP: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
15451 + /* nothing else to check because no parameters */
15455 +static struct ipt_target ipt_ipv4optsstrip_reg
15456 += { { NULL, NULL }, "IPV4OPTSSTRIP", target, checkentry, NULL, THIS_MODULE };
15458 +static int __init init(void)
15460 + if (ipt_register_target(&ipt_ipv4optsstrip_reg))
15462 + printk("ipt_IPV4OPTSSTRIP loaded\n");
15467 +static void __exit fini(void)
15469 + ipt_unregister_target(&ipt_ipv4optsstrip_reg);
15470 + printk("ipt_IPV4OPTSSTRIP unloaded\n");
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
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>
15491 #include <net/route.h>
15493 +#include <linux/netfilter_ipv4/ip_tables.h>
15494 #include <linux/netfilter_ipv4/ipt_LOG.h>
15495 +#include <linux/netfilter_ipv4/ip_logging.h>
15497 +static unsigned int nflog = 1;
15498 +MODULE_PARM(nflog, "i");
15499 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
15502 #define DEBUGP printk
15503 @@ -20,10 +24,20 @@
15504 #define DEBUGP(format, args...)
15507 +/* FIXME: move to ip.h like in 2.5 */
15518 -}; /* FIXME evil kludge */
15523 /* Use lock to serialize, so printks don't overlap */
15524 static spinlock_t log_lock = SPIN_LOCK_UNLOCKED;
15527 printk("FRAG:%u ", ntohs(iph->frag_off) & IP_OFFSET);
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) {
15535 /* Max length: 127 "OPT (" 15*4*2chars ") " */
15536 @@ -230,13 +245,30 @@
15541 + case IPPROTO_AH: {
15542 + struct ahhdr *ah = protoh;
15544 + /* Max length: 9 "PROTO=AH " */
15545 + printk("PROTO=AH ");
15547 + if (ntohs(iph->frag_off) & IP_OFFSET)
15550 + /* Max length: 25 "INCOMPLETE [65535 bytes] " */
15551 + if (datalen < sizeof (*ah)) {
15552 + printk("INCOMPLETE [%u bytes] ", datalen);
15556 + /* Length: 15 "SPI=0xF1234567 " */
15557 + printk("SPI=0x%x ", ntohl(ah->spi) );
15560 case IPPROTO_ESP: {
15561 struct esphdr *esph = protoh;
15562 - int esp= (iph->protocol==IPPROTO_ESP);
15564 /* Max length: 10 "PROTO=ESP " */
15565 - printk("PROTO=%s ",esp? "ESP" : "AH");
15566 + printk("PROTO=ESP ");
15568 if (ntohs(iph->frag_off) & IP_OFFSET)
15570 @@ -270,23 +302,21 @@
15571 /* maxlen = 230+ 91 + 230 + 252 = 803 */
15574 -static unsigned int
15575 -ipt_log_target(struct sk_buff **pskb,
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,
15583 + const struct ipt_log_info *loginfo,
15584 + const char *level_string,
15585 + const char *prefix)
15587 struct iphdr *iph = (*pskb)->nh.iph;
15588 - const struct ipt_log_info *loginfo = targinfo;
15589 - char level_string[4] = "< >";
15591 - level_string[1] = '0' + (loginfo->level % 8);
15592 spin_lock_bh(&log_lock);
15593 printk(level_string);
15594 printk("%sIN=%s OUT=%s ",
15596 + prefix == NULL ? loginfo->prefix : prefix,
15597 in ? in->name : "",
15598 out ? out->name : "");
15600 @@ -306,10 +336,59 @@
15601 dump_packet(loginfo, iph, (*pskb)->len, 1);
15603 spin_unlock_bh(&log_lock);
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,
15614 + const struct ipt_log_info *loginfo = targinfo;
15615 + char level_string[4] = "< >";
15617 + level_string[1] = '0' + (loginfo->level % 8);
15618 + ipt_log_packet(pskb, hooknum, in, out, loginfo, level_string, NULL);
15620 return IPT_CONTINUE;
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)
15630 + struct ipt_log_info loginfo = {
15632 + .logflags = IPT_LOG_MASK,
15636 + ipt_log_packet(pskb, hooknum, in, out, &loginfo, KERN_WARNING, prefix);
15640 +ip_log_fn(char *pfh, size_t len,
15641 + const char *prefix)
15643 + struct iphdr *iph = (struct iphdr *)pfh;
15644 + struct ipt_log_info loginfo = {
15646 + .logflags = IPT_LOG_MASK,
15650 + spin_lock_bh(&log_lock);
15651 + printk(KERN_WARNING "%s", prefix);
15652 + dump_packet(&loginfo, iph, len, 1);
15654 + spin_unlock_bh(&log_lock);
15657 static int ipt_log_checkentry(const char *tablename,
15658 const struct ipt_entry *e,
15660 @@ -341,17 +420,23 @@
15661 static struct ipt_target ipt_log_reg
15662 = { { NULL, NULL }, "LOG", ipt_log_target, ipt_log_checkentry, NULL,
15664 +static struct nf_logging_t ip_logging_fn
15665 += { ip_log_packet_fn, ip_log_fn };
15667 static int __init init(void)
15669 if (ipt_register_target(&ipt_log_reg))
15673 + nf_ip_log_register(&ip_logging_fn);
15678 static void __exit fini(void)
15681 + nf_ip_log_unregister(&ip_logging_fn);
15682 ipt_unregister_target(&ipt_log_reg);
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;
15694 #ifdef CONFIG_IP_ROUTE_FWMARK
15695 key.fwmark = (*pskb)->nfmark;
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");
15706 + if (rt->u.dst.dev != out) {
15707 + if (net_ratelimit())
15708 + printk("MASQUERADE:"
15709 + " Route sent us somewhere else.\n");
15713 @@ -116,63 +124,37 @@
15717 -device_cmp(const struct ip_conntrack *i, void *ifindex)
15718 +device_cmp(const struct ip_conntrack *i, void *_ina)
15722 + struct in_ifaddr *ina = _ina;
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)
15731 READ_UNLOCK(&masq_lock);
15736 -static int masq_device_event(struct notifier_block *this,
15737 - unsigned long event,
15740 - struct net_device *dev = ptr;
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);
15748 - ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
15751 - return NOTIFY_DONE;
15754 static int masq_inet_event(struct notifier_block *this,
15755 unsigned long event,
15758 - struct net_device *dev = ((struct in_ifaddr *)ptr)->ifa_dev->dev;
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);
15766 - ip_ct_selective_cleanup(device_cmp, (void *)(long)dev->ifindex);
15768 + /* For some configurations, interfaces often come back with
15769 + * the same address. If not, clean up old conntrack
15771 + if (event == NETDEV_UP)
15772 + ip_ct_selective_cleanup(device_cmp, ptr);
15774 return NOTIFY_DONE;
15777 -static struct notifier_block masq_dev_notifier = {
15778 - masq_device_event,
15783 static struct notifier_block masq_inet_notifier = {
15787 + .notifier_call = masq_inet_event
15790 static struct ipt_target masquerade
15791 @@ -185,12 +167,9 @@
15793 ret = ipt_register_target(&masquerade);
15796 - /* Register for device down reports */
15797 - register_netdevice_notifier(&masq_dev_notifier);
15799 /* Register IP address change reports */
15800 register_inetaddr_notifier(&masq_inet_notifier);
15805 @@ -198,7 +177,6 @@
15806 static void __exit fini(void)
15808 ipt_unregister_target(&masquerade);
15809 - unregister_netdevice_notifier(&masq_dev_notifier);
15810 unregister_inetaddr_notifier(&masq_inet_notifier);
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
15817 #include <linux/netfilter_ipv4/ip_tables.h>
15818 #include <linux/netdevice.h>
15819 #include <linux/route.h>
15821 #include <net/route.h>
15824 @@ -41,31 +40,47 @@
15825 #define DEBUGP(format, args...)
15828 -static int route_mirror(struct sk_buff *skb)
15829 +static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
15831 struct iphdr *iph = skb->nh.iph;
15832 + struct dst_entry *odst;
15833 + struct rt_key key = {};
15837 - if (ip_route_output(&rt, iph->saddr, iph->daddr,
15838 - RT_TOS(iph->tos) | RTO_CONN,
15842 + key.dst = iph->saddr;
15843 + key.src = iph->daddr;
15844 + key.tos = RT_TOS(iph->tos);
15846 + if (ip_route_output_key(&rt, &key) != 0)
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)
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);
15861 + dst_release(&rt->u.dst);
15862 + rt = (struct rtable *)skb->dst;
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;
15873 + if (rt->u.dst.error) {
15874 + dst_release(&rt->u.dst);
15883 -ip_rewrite(struct sk_buff *skb)
15884 +static inline void ip_rewrite(struct sk_buff *skb)
15886 struct iphdr *iph = skb->nh.iph;
15887 u32 odaddr = iph->saddr;
15888 @@ -105,32 +120,48 @@
15889 const void *targinfo,
15892 - if (((*pskb)->dst != NULL) &&
15893 - route_mirror(*pskb)) {
15895 - ip_rewrite(*pskb);
15896 + struct rtable *rt;
15897 + struct sk_buff *nskb;
15898 + unsigned int hh_len;
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);
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);
15923 + ip_decrease_ttl(iph);
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)
15933 - return NF_STOLEN;
15934 + hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
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);
15946 + dst_release(nskb->dst);
15947 + nskb->dst = &rt->u.dst;
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);
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
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>
15976 +MODULE_AUTHOR("Gianni Tedesco <gianni@ecsc.co.uk>");
15977 +MODULE_DESCRIPTION("Provides iptables NETLINK target similar to ipchains -o");
15978 +MODULE_LICENSE("GPL");
15981 +#define DEBUGP printk
15983 +#define DEBUGP(format, args...)
15986 +static struct sock *ipfwsk;
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)
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;
16000 + /* Allocate a socket buffer */
16001 + if ( MASK(nld->flags, USE_SIZE) )
16002 + len = nld->size+sizeof(nlhdr);
16004 + len = ntohs(ip->tot_len)+sizeof(nlhdr);
16006 + outskb=alloc_skb(len, GFP_ATOMIC);
16011 + if ( MASK(nld->flags, USE_MARK) )
16012 + nlhdr.mark=(*pskb)->nfmark=nld->mark;
16014 + nlhdr.mark=(*pskb)->nfmark;
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);
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);
16027 + if (net_ratelimit())
16028 + printk(KERN_WARNING "ipt_NETLINK: packet drop due to netlink failure\n");
16031 + if ( MASK(nld->flags, USE_DROP) )
16034 + return IPT_CONTINUE;
16037 +static int ipt_netlink_checkentry(const char *tablename,
16038 + const struct ipt_entry *e,
16040 + unsigned int targinfosize,
16041 + unsigned int hookmask)
16043 + //struct ipt_nldata *nld = (struct ipt_nldata *)targinfo;
16048 +static struct ipt_target ipt_netlink_reg = {
16051 + ipt_netlink_target,
16052 + ipt_netlink_checkentry,
16057 +static int __init init(void)
16059 + DEBUGP("ipt_NETLINK: init module\n");
16061 + if (ipt_register_target(&ipt_netlink_reg) != 0) {
16065 + if ( !(ipfwsk=netlink_kernel_create(NETLINK_FIREWALL, NULL)) ){
16072 +static void __exit fini(void)
16074 + DEBUGP("ipt_NETLINK: cleanup_module\n");
16075 + ipt_unregister_target(&ipt_netlink_reg);
16076 + if(ipfwsk->socket) sock_release(ipfwsk->socket);
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
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).
16089 + Author: Svenning Soerensen <svenning@post5.tele.dk>
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>
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");
16106 +#define DEBUGP printk
16108 +#define DEBUGP(format, args...)
16112 +check(const char *tablename,
16113 + const struct ipt_entry *e,
16115 + unsigned int targinfosize,
16116 + unsigned int hook_mask)
16118 + const struct ip_nat_multi_range *mr = targinfo;
16120 + if (strcmp(tablename, "nat") != 0) {
16121 + DEBUGP(MODULENAME":check: bad table `%s'.\n", tablename);
16124 + if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
16125 + DEBUGP(MODULENAME":check: size %u.\n", targinfosize);
16128 + if (hook_mask & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_POST_ROUTING))) {
16129 + DEBUGP(MODULENAME":check: bad hooks %x.\n", hook_mask);
16132 + if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) {
16133 + DEBUGP(MODULENAME":check: bad MAP_IPS.\n");
16136 + if (mr->rangesize != 1) {
16137 + DEBUGP(MODULENAME":check: bad rangesize %u.\n", mr->rangesize);
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,
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;
16157 + IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING
16158 + || hooknum == NF_IP_POST_ROUTING);
16159 + ct = ip_conntrack_get(*pskb, &ctinfo);
16161 + netmask = ~(mr->range[0].min_ip ^ mr->range[0].max_ip);
16163 + if (hooknum == NF_IP_PRE_ROUTING)
16164 + new_ip = (*pskb)->nh.iph->daddr & ~netmask;
16166 + new_ip = (*pskb)->nh.iph->saddr & ~netmask;
16167 + new_ip |= mr->range[0].min_ip & netmask;
16169 + newrange = ((struct ip_nat_multi_range)
16170 + { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
16172 + mr->range[0].min, mr->range[0].max } } });
16174 + /* Hand modified range to generic setup. */
16175 + return ip_nat_setup_info(ct, &newrange, hooknum);
16178 +static struct ipt_target target_module
16179 += { { NULL, NULL }, MODULENAME, target, check, NULL,
16182 +static int __init init(void)
16184 + return ipt_register_target(&target_module);
16187 +static void __exit fini(void)
16189 + ipt_unregister_target(&target_module);
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
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.
16201 +#include <linux/module.h>
16202 +#include <linux/skbuff.h>
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>
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,
16217 + struct ip_conntrack_protocol *proto;
16218 + struct ip_conntrack_tuple tuple;
16220 + if ((*pskb)->nfct != NULL)
16221 + return IPT_CONTINUE;
16223 + proto = ip_ct_find_proto((*pskb)->nh.iph->protocol);
16225 + if (ip_conntrack_get_tuple((*pskb)->nh.iph, (*pskb)->len,
16227 + && !ip_conntrack_tuple_taken(&tuple, NULL)) {
16228 + (*pskb)->nfct = &ip_conntrack_untracked.infos[IP_CT_NEW];
16229 + nf_conntrack_get((*pskb)->nfct);
16232 + return IPT_CONTINUE;
16236 +checkentry(const char *tablename,
16237 + const struct ipt_entry *e,
16239 + unsigned int targinfosize,
16240 + unsigned int hook_mask)
16242 + if (targinfosize != 0) {
16243 + printk(KERN_WARNING "NOTRACK: targinfosize %u != 0\n",
16248 + if (strcmp(tablename, "raw") != 0) {
16249 + printk(KERN_WARNING "NOTRACK: can only be called from \"raw\" table, not \"%s\"\n", tablename);
16256 +static struct ipt_target ipt_notrack_reg = {
16257 + .list = { NULL, NULL },
16258 + .name = "NOTRACK",
16259 + .target = target,
16260 + .checkentry = checkentry,
16262 + .me = THIS_MODULE
16265 +static int __init init(void)
16267 + if (ipt_register_target(&ipt_notrack_reg))
16273 +static void __exit fini(void)
16275 + ipt_unregister_target(&ipt_notrack_reg);
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
16285 +/* ipt_POOL.c - netfilter target to manipulate IP pools
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.
16292 + * The target normally returns IPT_CONTINUE.
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>
16310 +#define DEBUGP printk
16312 +#define DEBUGP(format, args...)
16315 +/*** NOTE NOTE NOTE NOTE ***
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.
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.
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.)
16333 +do_check(const char *tablename,
16334 + const struct ipt_entry *e,
16336 + unsigned int targinfosize,
16337 + unsigned int hook_mask)
16339 + const struct ipt_pool_info *ipi = targinfo;
16341 + if (targinfosize != IPT_ALIGN(sizeof(*ipi))) {
16342 + DEBUGP("POOL_check: size %u.\n", targinfosize);
16345 + DEBUGP("ipt_POOL:do_check(%d,%d,%d)\n",ipi->src,ipi->dst,ipi->flags);
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,
16357 + const struct ipt_pool_info *ipi = targinfo;
16359 + unsigned int verdict = IPT_CONTINUE;
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;
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;
16384 +static struct ipt_target pool_reg
16385 += { { NULL, NULL }, "POOL", do_target, do_check, NULL, THIS_MODULE };
16387 +static int __init init(void)
16389 + DEBUGP("init ipt_POOL\n");
16390 + return ipt_register_target(&pool_reg);
16393 +static void __exit fini(void)
16395 + DEBUGP("fini ipt_POOL\n");
16396 + ipt_unregister_target(&pool_reg);
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
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).
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>
16421 #include <net/route.h>
16422 #include <linux/netfilter_ipv4/ip_tables.h>
16423 #include <linux/netfilter_ipv4/ipt_REJECT.h>
16425 attach(new_skb, nfct);
16428 +static inline struct rtable *route_reverse(struct sk_buff *skb, int hook)
16430 + struct iphdr *iph = skb->nh.iph;
16431 + struct dst_entry *odst;
16432 + struct rt_key key = {};
16433 + struct rtable *rt;
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);
16441 + if (ip_route_output_key(&rt, &key) != 0)
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)
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);
16456 + dst_release(&rt->u.dst);
16457 + rt = (struct rtable *)skb->dst;
16461 + if (rt->u.dst.error) {
16462 + dst_release(&rt->u.dst);
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)
16473 struct sk_buff *nskb;
16474 struct tcphdr *otcph, *tcph;
16476 u_int16_t tmp_port;
16477 u_int32_t tmp_addr;
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)
16487 + if ((rt = route_reverse(oldskb, hook)) == NULL)
16490 + hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
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);
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),
16503 + dst_release(&rt->u.dst);
16507 + dst_release(nskb->dst);
16508 + nskb->dst = &rt->u.dst;
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);
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,
16523 - dst_release(nskb->dst);
16524 - nskb->dst = &rt->u.dst;
16526 /* "Never happens" */
16527 if (nskb->len > nskb->dst->pmtu)
16529 @@ -154,12 +202,13 @@
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)
16537 + struct udphdr *udph;
16538 struct icmphdr *icmph;
16539 struct sk_buff *nskb;
16541 + u32 saddr,packet_daddr;
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))
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));
16555 + && csum_tcpudp_magic(iph->saddr, iph->daddr,
16556 + datalen, IPPROTO_UDP,
16557 + csum_partial((char *)udph, datalen,
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 @@
16569 - saddr = iph->daddr;
16570 + packet_daddr = saddr = iph->daddr;
16571 if (!(rt->rt_flags & RTCF_LOCAL))
16574 @@ -244,7 +306,16 @@
16576 ip_select_ident(iph, &rt->u.dst, NULL);
16577 iph->protocol=IPPROTO_ICMP;
16578 - iph->saddr=rt->rt_src;
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.
16584 + if (fake_source_address == 1)
16585 + iph->saddr = packet_daddr;
16587 + iph->saddr=rt->rt_src;
16589 iph->daddr=rt->rt_dst;
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);
16599 case IPT_ICMP_HOST_UNREACHABLE:
16600 - send_unreach(*pskb, ICMP_HOST_UNREACH);
16601 + send_unreach(*pskb, ICMP_HOST_UNREACH, reject->fake_source_address);
16603 case IPT_ICMP_PROT_UNREACHABLE:
16604 - send_unreach(*pskb, ICMP_PROT_UNREACH);
16605 + send_unreach(*pskb, ICMP_PROT_UNREACH, reject->fake_source_address);
16607 case IPT_ICMP_PORT_UNREACHABLE:
16608 - send_unreach(*pskb, ICMP_PORT_UNREACH);
16609 + send_unreach(*pskb, ICMP_PORT_UNREACH, reject->fake_source_address);
16611 case IPT_ICMP_NET_PROHIBITED:
16612 - send_unreach(*pskb, ICMP_NET_ANO);
16613 + send_unreach(*pskb, ICMP_NET_ANO, reject->fake_source_address);
16615 case IPT_ICMP_HOST_PROHIBITED:
16616 - send_unreach(*pskb, ICMP_HOST_ANO);
16617 + send_unreach(*pskb, ICMP_HOST_ANO, reject->fake_source_address);
16619 + case IPT_ICMP_ADMIN_PROHIBITED:
16620 + send_unreach(*pskb, ICMP_PKT_FILTERED, reject->fake_source_address);
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. */
16628 @@ -353,6 +427,11 @@
16629 DEBUGP("REJECT: TCP_RESET illegal for non-tcp\n");
16632 + /* cannot fake source address */
16633 + if (rejinfo->fake_source_address != 0) {
16634 + DEBUGP("REJECT: fake-source-address illegal for TCP-RESET\n");
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
16645 + * This implements the ROUTE target, which enables you to setup unusual
16646 + * routes not supported by the standard kernel routing table.
16648 + * Copyright (C) 2002 Cedric de Launois <delaunois@info.ucl.ac.be>
16650 + * v 1.8 2003/07/25
16652 + * This software is distributed under GNU GPL v2, 1991
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>
16667 +#define DEBUGP printk
16669 +#define DEBUGP(format, args...)
16673 +/* Try to route the packet according to the routing keys specified in
16674 + * route_info. Keys are :
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
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
16690 +static int route(struct sk_buff *skb,
16691 + unsigned int ifindex,
16692 + const struct ipt_route_target_info *route_info)
16695 + struct rtable *rt;
16696 + struct iphdr *iph = skb->nh.iph;
16697 + struct rt_key key = {
16701 + tos:RT_TOS(iph->tos)
16704 + /* The destination address may be overloaded by the target */
16705 + if (route_info->gw)
16706 + key.dst = route_info->gw;
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);
16715 + /* Drop old route. */
16716 + dst_release(skb->dst);
16719 + /* Success if no oif specified or if the oif correspond to the
16721 + if (!ifindex || rt->u.dst.dev->ifindex == ifindex) {
16722 + skb->dst = &rt->u.dst;
16723 + skb->dev = skb->dst->dev;
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.
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);
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
16745 +static void ip_direct_send(struct sk_buff *skb)
16747 + struct dst_entry *dst = skb->dst;
16748 + struct hh_cache *hh = dst->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);
16759 + if (net_ratelimit())
16760 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no hdr & no neighbour cache!\n");
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
16771 +static inline int dev_direct_send(struct sk_buff *skb)
16773 + return dev_queue_xmit(skb);
16777 +static unsigned int route_oif(const struct ipt_route_target_info *route_info,
16778 + struct sk_buff *skb)
16780 + unsigned int ifindex = 0;
16781 + struct net_device *dev_out = NULL;
16783 + /* The user set the interface name to use.
16784 + * Getting the current interface index.
16786 + if ((dev_out = dev_get_by_name(route_info->oif))) {
16787 + ifindex = dev_out->ifindex;
16789 + /* Unknown interface name : packet dropped */
16790 + if (net_ratelimit())
16791 + DEBUGP("ipt_ROUTE: oif interface %s not found\n", route_info->oif);
16795 + /* Trying the standard way of routing packets */
16796 + switch (route(skb, ifindex, route_info)) {
16798 + dev_put(dev_out);
16799 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16800 + return IPT_CONTINUE;
16802 + ip_direct_send(skb);
16803 + return NF_STOLEN;
16806 + /* Failed to send to oif. Trying the hard way */
16807 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16810 + if (net_ratelimit())
16811 + DEBUGP("ipt_ROUTE: forcing the use of %i\n",
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
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);
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.
16833 + skb->dev = dev_out;
16834 + dev_direct_send(skb);
16835 + dev_put(dev_out);
16836 + return NF_STOLEN;
16839 + /* Unexpected error */
16840 + dev_put(dev_out);
16846 +static unsigned int route_iif(const struct ipt_route_target_info *route_info,
16847 + struct sk_buff *skb)
16849 + struct net_device *dev_out = NULL;
16850 + unsigned int ifindex = 0;
16852 + /* Getting the current interface index. */
16853 + if ((dev_out = dev_get_by_name(route_info->iif)))
16854 + ifindex = dev_out->ifindex;
16856 + /* Unknown interface name : packet dropped */
16857 + if (net_ratelimit())
16858 + DEBUGP("ipt_ROUTE: iif interface %s not found\n", route_info->oif);
16862 + skb->dev = dev_out;
16863 + dst_release(skb->dst);
16868 + return NF_STOLEN;
16872 +static unsigned int route_gw(const struct ipt_route_target_info *route_info,
16873 + struct sk_buff *skb)
16875 + if (route(skb, 0, route_info)!=1)
16878 + if (route_info->flags & IPT_ROUTE_CONTINUE)
16879 + return IPT_CONTINUE;
16881 + ip_direct_send(skb);
16882 + return NF_STOLEN;
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,
16893 + const struct ipt_route_target_info *route_info = targinfo;
16894 + struct sk_buff *skb = *pskb;
16896 + /* If we are at PREROUTING or INPUT hook
16897 + * the TTL isn't decreased by the IP stack
16899 + if (hooknum == NF_IP_PRE_ROUTING ||
16900 + hooknum == NF_IP_LOCAL_IN) {
16902 + struct iphdr *iph = skb->nh.iph;
16904 + if (iph->ttl <= 1) {
16905 + struct rtable *rt;
16907 + if (ip_route_output(&rt, iph->saddr, iph->daddr,
16908 + RT_TOS(iph->tos) | RTO_CONN,
16913 + if (skb->dev == rt->u.dst.dev) {
16914 + /* Drop old route. */
16915 + dst_release(skb->dst);
16916 + skb->dst = &rt->u.dst;
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);
16927 + ip_decrease_ttl(iph);
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.
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;
16943 + if (route_info->oif[0])
16944 + return route_oif(route_info, *pskb);
16946 + if (route_info->iif[0])
16947 + return route_iif(route_info, *pskb);
16949 + if (route_info->gw)
16950 + return route_gw(route_info, *pskb);
16952 + if (net_ratelimit())
16953 + DEBUGP(KERN_DEBUG "ipt_ROUTE: no parameter !\n");
16955 + return IPT_CONTINUE;
16959 +static int ipt_route_checkentry(const char *tablename,
16960 + const struct ipt_entry *e,
16962 + unsigned int targinfosize,
16963 + unsigned int hook_mask)
16965 + if (strcmp(tablename, "mangle") != 0) {
16966 + printk("ipt_ROUTE: bad table `%s', use the `mangle' table.\n",
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");
16980 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_route_target_info))) {
16981 + printk(KERN_WARNING "ipt_ROUTE: targinfosize %u != %Zu\n",
16983 + IPT_ALIGN(sizeof(struct ipt_route_target_info)));
16991 +static struct ipt_target ipt_route_reg
16992 += { { NULL, NULL }, "ROUTE", ipt_route_target, ipt_route_checkentry, NULL,
16996 +static int __init init(void)
16998 + if (ipt_register_target(&ipt_route_reg))
17005 +static void __exit fini(void)
17007 + ipt_unregister_target(&ipt_route_reg);
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
17017 +/* Same. Just like SNAT, only try to make the connections
17018 + * between client A and server B always have the same source ip.
17020 + * (C) 2000 Rusty Russell. GPL.
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
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.
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>
17051 +MODULE_LICENSE("GPL");
17052 +MODULE_AUTHOR("Martin Josefsson <gandalf@wlug.westbo.se>");
17053 +MODULE_DESCRIPTION("iptables special SNAT module for consistent sourceip");
17056 +#define DEBUGP printk
17058 +#define DEBUGP(format, args...)
17062 +same_check(const char *tablename,
17063 + const struct ipt_entry *e,
17065 + unsigned int targinfosize,
17066 + unsigned int hook_mask)
17068 + unsigned int count, countess, rangeip, index = 0;
17069 + struct ipt_same_info *mr = targinfo;
17073 + if (strcmp(tablename, "nat") != 0) {
17074 + DEBUGP("same_check: bad table `%s'.\n", tablename);
17077 + if (targinfosize != IPT_ALIGN(sizeof(*mr))) {
17078 + DEBUGP("same_check: size %u.\n", targinfosize);
17081 + if (hook_mask & ~(1 << NF_IP_PRE_ROUTING | 1 << NF_IP_POST_ROUTING)) {
17082 + DEBUGP("same_check: bad hooks %x.\n", hook_mask);
17085 + if (mr->rangesize < 1) {
17086 + DEBUGP("same_check: need at least one dest range.\n");
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);
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));
17104 + if (!(mr->range[count].flags & IP_NAT_RANGE_MAP_IPS)) {
17105 + DEBUGP("same_check: bad MAP_IPS.\n");
17108 + rangeip = (ntohl(mr->range[count].max_ip) -
17109 + ntohl(mr->range[count].min_ip) + 1);
17110 + mr->ipnum += rangeip;
17112 + DEBUGP("same_check: range %u, ipnum = %u\n", count, rangeip);
17114 + DEBUGP("same_check: total ipaddresses = %u\n", mr->ipnum);
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);
17123 + DEBUGP("same_check: Allocated %u bytes for %u ipaddresses.\n",
17124 + (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
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);
17130 + mr->iparray[index] = countess;
17131 + DEBUGP("same_check: Added ipaddress `%u.%u.%u.%u' "
17132 + "in index %u.\n",
17133 + HIPQUAD(countess), index);
17141 +same_destroy(void *targinfo,
17142 + unsigned int targinfosize)
17144 + struct ipt_same_info *mr = targinfo;
17146 + kfree(mr->iparray);
17148 + DEBUGP("same_destroy: Deallocated %u bytes for %u ipaddresses.\n",
17149 + (sizeof(u_int32_t) * mr->ipnum), mr->ipnum);
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,
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;
17167 + IP_NF_ASSERT(hooknum == NF_IP_PRE_ROUTING ||
17168 + hooknum == NF_IP_POST_ROUTING);
17169 + ct = ip_conntrack_get(*pskb, &ctinfo);
17171 + t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
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 */
17178 + tmpip = ntohl(t->src.ip);
17180 + if (!(mr->info & IPT_SAME_NODST))
17181 + tmpip += ntohl(t->dst.ip);
17183 + aindex = tmpip % mr->ipnum;
17185 + new_ip = htonl(mr->iparray[aindex]);
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));
17192 + /* Transfer from original range. */
17193 + newrange = ((struct ip_nat_multi_range)
17194 + { 1, { { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS,
17196 + mr->range[0].min, mr->range[0].max } } });
17198 + /* Hand modified range to generic setup. */
17199 + return ip_nat_setup_info(ct, &newrange, hooknum);
17202 +static struct ipt_target same_reg
17203 += { { NULL, NULL }, "SAME", same_target, same_check, same_destroy,
17206 +static int __init init(void)
17208 + return ipt_register_target(&same_reg);
17211 +static void __exit fini(void)
17213 + ipt_unregister_target(&same_reg);
17216 +module_init(init);
17217 +module_exit(fini);
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
17224 + * Kernel module to capture and hold incoming TCP connections using
17225 + * no local per-connection resources.
17227 + * Based on ipt_REJECT.c and offering functionality similar to
17228 + * LaBrea <http://www.hackbusters.net/LaBrea/>.
17230 + * Copyright (c) 2002 Aaron Hopkins <tools@die.net>
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.
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.
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.
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.
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
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>
17268 +#include <net/route.h>
17269 +#include <linux/random.h>
17270 +#include <linux/netfilter_ipv4/ip_tables.h>
17273 +#define DEBUGP printk
17275 +#define DEBUGP(format, args...)
17279 +/* Stolen from ip_finish_output2 */
17280 +static int ip_direct_send(struct sk_buff *skb)
17282 + struct dst_entry *dst = skb->dst;
17283 + struct hh_cache *hh = dst->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);
17294 + if (net_ratelimit())
17295 + printk(KERN_DEBUG "TARPIT ip_direct_send: no header cache and no neighbor!\n");
17302 +static void tarpit_tcp(struct sk_buff *oskb,struct rtable *ort,int local)
17304 + struct sk_buff *nskb;
17305 + struct rtable *nrt;
17306 + struct tcphdr *otcph, *ntcph;
17307 + unsigned int otcplen;
17310 + /* A truncated TCP header isn't going to be useful */
17311 + if (oskb->len < (oskb->nh.iph->ihl*4) + sizeof(struct tcphdr))
17314 + otcph = (struct tcphdr *)((u_int32_t*)oskb->nh.iph
17315 + + oskb->nh.iph->ihl);
17316 + otcplen = oskb->len - oskb->nh.iph->ihl*4;
17318 + /* No replies for RST or FIN */
17319 + if (otcph->rst || otcph->fin)
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)))
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)
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);
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;
17347 + ntcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
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);
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;
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,
17367 + /* Our SYN-ACKs must have a >0 window */
17368 + ntcph->window = (otcph->syn && !otcph->ack) ? htons(5) : 0;
17370 + ntcph->urg_ptr = 0;
17372 + /* Reset flags */
17373 + ((u_int8_t *)ntcph)[13] = 0;
17375 + if (otcph->syn && otcph->ack) {
17377 + ntcph->ack_seq = 0;
17379 + ntcph->syn = otcph->syn;
17381 + ntcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn);
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));
17392 + /* Adjust IP TTL */
17393 + nskb->nh.iph->ttl = sysctl_ip_default_ttl;
17395 + /* Set DF, id = 0 */
17396 + nskb->nh.iph->frag_off = htons(IP_DF);
17397 + nskb->nh.iph->id = 0;
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);
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,
17410 + dst_release(nskb->dst);
17411 + nskb->dst = &nrt->u.dst;
17413 + /* "Never happens" */
17414 + if (nskb->len > nskb->dst->pmtu)
17417 + ip_direct_send (nskb);
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,
17433 + struct sk_buff *skb = *pskb;
17434 + struct rtable *rt = (struct rtable*)skb->dst;
17436 + /* Do we have an input route cache entry? */
17440 + /* No replies to physical multicast/broadcast */
17441 + if (skb->pkt_type != PACKET_HOST && skb->pkt_type != PACKET_OTHERHOST)
17444 + /* Now check at the protocol level */
17445 + if (rt->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
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))
17453 + /* We aren't interested in fragments */
17454 + if (skb->nh.iph->frag_off & htons(IP_OFFSET))
17457 + tarpit_tcp(skb,rt,hooknum == NF_IP_LOCAL_IN);
17463 +static int check(const char *tablename,
17464 + const struct ipt_entry *e,
17466 + unsigned int targinfosize,
17467 + unsigned int hook_mask)
17469 + /* Only allow these for input/forward packet filtering. */
17470 + if (strcmp(tablename, "filter") != 0) {
17471 + DEBUGP("TARPIT: bad table %s'.\n", tablename);
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);
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");
17489 +static struct ipt_target ipt_tarpit_reg
17490 += { { NULL, NULL }, "TARPIT", tarpit, check, NULL, THIS_MODULE };
17492 +static int __init init(void)
17494 + if (ipt_register_target(&ipt_tarpit_reg))
17499 +static void __exit fini(void)
17501 + ipt_unregister_target(&ipt_tarpit_reg);
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
17511 +/* ipt_TCPLAG.c -- kernel module to implement TCPLAG target into netfilter
17512 + * Copyright (C) 2002 Telford Tendys <telford@triode.net.au>
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.
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.
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
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.
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>
17543 +#include <net/route.h>
17544 +#include <linux/netfilter_ipv4/ipt_TCPLAG.h>
17547 +#define DEBUGP printk
17549 +#define DEBUGP(format, args...)
17553 + * We need one spinlock for the hash table.
17555 +static spinlock_t hash_lock = SPIN_LOCK_UNLOCKED;
17557 +typedef struct timeval timeval_T;
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).
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.
17571 +typedef struct tcplag_event_S
17573 + struct tcplag_event_S *next;
17576 + u32 expected_ACK;
17577 + struct timeval stamp;
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.
17587 +typedef struct tcplag_hash_S
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 */
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;
17605 +static void divide_down( timeval_T *T, int c )
17610 + remainder = T->tv_sec % c; /* Only works properly with positive numbers */
17611 + remainder *= 1000000;
17612 + T->tv_usec == remainder;
17616 +int diff_timeval( timeval_T *tv1, timeval_T *tv2 )
17620 + x = tv1->tv_sec - tv2->tv_sec;
17621 + if( x ) return( x );
17622 + x = tv1->tv_usec - tv2->tv_usec;
17626 +void sprint_timeval( char *buf, timeval_T *tv )
17629 + sprintf( buf, "%lu%06lu", tv->tv_sec, tv->tv_usec );
17631 + sprintf( buf, "%lu", tv->tv_usec );
17635 + * This generates the log messages through printk()
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).
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
17650 +static void output( tcplag_hash_T *H, int level, const char *prefix )
17652 + struct timeval ltm, rtm;
17653 + u32 local_ip, remote_ip;
17654 + char r_buf[ 20 ], l_buf[ 20 ];
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.
17660 + if( 0 == H->count_l_SEQ_h_ACK || 0 == H->count_h_SEQ_l_ACK ) return;
17662 + * Calculate average times by dividing down
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 );
17667 + * Sort these two by the lag so the the local is always the short lag
17669 + if( diff_timeval( &H->lag_l_SEQ_h_ACK, &H->lag_h_SEQ_l_ACK ) > 0 )
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;
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;
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.
17692 + * We use sprintf() to partially pre-digest the output
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.
17699 + sprint_timeval( l_buf, <m );
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 ),
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)
17712 +static void reaper( time_t now, int level, const char *prefix )
17716 + now -= max_seconds;
17717 + if( !hashsize ) return;
17718 + if( !hashtab ) return;
17719 + for( i = 0; i < 10; i++ )
17721 + if( ++reaper_ix >= hashsize ) reaper_ix = 0;
17723 +// DEBUGP( KERN_WARNING "reaper checking %u\n", reaper_ix );
17725 + if( hashtab[ reaper_ix ])
17727 + tcplag_hash_T *found = 0;
17729 + spin_lock_bh( &hash_lock );
17730 + if( hashtab[ reaper_ix ])
17732 + if( now > hashtab[ reaper_ix ]->stamp )
17734 + DEBUGP( KERN_WARNING "reaper found expired entry\n" );
17735 + found = hashtab[ reaper_ix ];
17736 + hashtab[ reaper_ix ] = 0;
17739 + spin_unlock_bh( &hash_lock );
17743 + output( found, level, prefix );
17751 + * Convert the connection characteristics into a number
17752 + * (not including the timestamp) FIXME: this is a sucky hash function
17754 +static u32 make_hash( tcplag_hash_T *connection )
17758 + r = connection->low_ip;
17759 + r += connection->high_ip;
17763 +static int compare_connections( tcplag_hash_T *con1, tcplag_hash_T *con2 )
17767 + x = con1->low_ip - con2->low_ip; if( x ) return( x );
17768 + x = con1->high_ip - con2->high_ip;
17772 +static int compare_events( tcplag_event_T *ev1, tcplag_event_T *ev2 )
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;
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.
17792 +static void hash_insert( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17796 + if( !event ) return; /* Just to be safe */
17797 + if( !hashsize ) return;
17798 + if( !hashtab ) return;
17800 + h = make_hash( connection );
17803 + DEBUGP( KERN_WARNING "hash_insert( %u )\n", h );
17805 + spin_lock_bh( &hash_lock );
17806 + for( i = 0; i < hashsize; i++, ({ if( ++h >= hashsize ) { h = 0; }}))
17808 + tcplag_hash_T *co_new = 0;
17810 + * Consider existing entry
17812 + if( hashtab[ h ])
17814 + if( compare_connections( hashtab[ h ], connection )) continue;
17815 + co_new = hashtab[ h ];
17816 + DEBUGP( KERN_WARNING "Existing connection at %u\n", h );
17820 + * Use empty slot for new entry
17822 + if( !hashtab[ h ])
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 );
17833 + tcplag_event_T *ev_new;
17835 + ev_new = kmalloc( sizeof( tcplag_event_T ), GFP_ATOMIC );
17836 + memcpy( ev_new, event, sizeof( tcplag_event_T ));
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 );
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 );
17854 + spin_unlock_bh( &hash_lock );
17858 + * Search the hash table for a matching connection,
17859 + * if we can't find one of those then we are stuffed.
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.
17866 +static int request_complete( tcplag_hash_T *connection, tcplag_event_T *event, int direction )
17870 + if( !event ) return( 0 );
17871 + if( !hashsize ) return( 0 );
17872 + if( !hashtab ) return( 0 );
17873 + h = make_hash( connection );
17876 + DEBUGP( KERN_WARNING "request_complete( %u )\n", h );
17878 + for( i = 0; i < hashsize; i++ )
17880 + tcplag_hash_T *found = 0;
17882 + if( !hashtab[ h ]) return( 0 );
17884 + spin_lock_bh( &hash_lock );
17885 + if( hashtab[ h ])
17887 + if( !compare_connections( hashtab[ h ], connection ))
17889 + tcplag_event_T *ev, **evroot;
17893 + found = hashtab[ h ];
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 );
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 );
17908 + for( ev = *evroot; ev; ev = ev->next )
17910 + if( !compare_events( ev, event ))
17913 + * Calculate the lag (in two parts) and add that to the collection
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 )
17919 + event->stamp.tv_usec += 1000000;
17920 + event->stamp.tv_sec++;
17922 + if( event->stamp.tv_sec < 0 )
17924 + DEBUGP( KERN_WARNING "Negative lag detected\n" );
17928 + tv->tv_sec += event->stamp.tv_sec;
17929 + tv->tv_usec += event->stamp.tv_usec;
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 );
17938 + * Truncate the linked list.
17940 + * Visit each event in the list and return the memory to the pool.
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.
17951 + tcplag_event_T *ev_next = ev->next;
17952 + DEBUGP( KERN_WARNING "Shitcan %u\n", ev->expected_ACK );
17957 + * TODO: overflow limit for *cn, force premature output() if necessary
17958 + * (and drop this connection from the hash table)
17967 + spin_unlock_bh( &hash_lock );
17969 + if( found ) return( 1 );
17970 + if( ++h >= hashsize ) h = 0;
17976 + * Here is our target data:
17978 + * pskb -- The packet itself (see linux/skbuff.h for breakdown)
17982 + * in -- The device that this packet came in on
17983 + * (depending on the chain this may or may not exist)
17985 + * out -- The device that this packet is just about to go
17986 + * out onto (again existance depends on the chain)
17988 + * targinfo -- Our private data (handed through from iptables command util)
17990 + * userinfo -- Some more data
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,
18001 + struct iphdr *iph = ( *pskb )->nh.iph;
18002 + const struct ipt_tcplag *el = targinfo;
18003 + tcplag_hash_T connection;
18004 + tcplag_event_T event;
18007 + * We know we are dealing with IP here
18008 + * Fill in all the obvious fields
18010 + if( iph->saddr > iph->daddr )
18013 + connection.high_ip = iph->saddr;
18014 + connection.low_ip = iph->daddr;
18019 + connection.low_ip = iph->saddr;
18020 + connection.high_ip = iph->daddr;
18022 + do_gettimeofday( &event.stamp );
18024 + * Do a bit of cleaning
18026 + reaper( event.stamp.tv_sec, el->level, el->prefix );
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" );
18033 + * Now start looking at the details
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.
18040 + switch( iph->protocol )
18042 + case IPPROTO_TCP:
18044 + struct tcphdr *tcp;
18046 + if( ntohs( iph->frag_off ) & IP_OFFSET )
18048 + DEBUGP( KERN_WARNING "ignoring fragment\n" );
18051 + tcp = (struct tcphdr *)((u32 *)iph + iph->ihl );
18052 + event.source_port = ntohs( tcp->source );
18053 + event.dest_port = ntohs( tcp->dest );
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
18063 + * Data length requires a bit of fiddling around
18066 + unsigned int data_len;
18067 + if( tcp->syn || tcp->fin )
18069 + data_len = 1; /* Not real data, the SEQ clicks forward by 1 */
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 */
18078 + DEBUGP( KERN_WARNING "Data length calculated at %u\n", data_len );
18080 + if( data_len ) /* Only track events that demand an ACK */
18082 + event.expected_ACK = ntohl( tcp->seq ) + data_len;
18083 + hash_insert( &connection, &event, direction );
18087 + DEBUGP( "Don't bother to insert this, ACK not required\n" );
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.
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 );
18106 + DEBUGP( "Don't bother to check this, ACK not valid\n" );
18110 + return( IPT_CONTINUE );
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
18121 + * targinfo -- Our private data block (handed to us from iptables plug-in)
18123 + * targinfosize -- The size of our private data block
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.
18131 +static int checkentry( const char *tablename,
18132 + const struct ipt_entry *e,
18134 + unsigned int targinfosize,
18135 + unsigned int hook_mask )
18137 + const struct ipt_tcplag *el = targinfo;
18139 + if( targinfosize != IPT_ALIGN( sizeof( struct ipt_tcplag )))
18141 + DEBUGP( "TCPLAG: targinfosize %u != %u\n", targinfosize,
18142 + IPT_ALIGN( sizeof( struct ipt_tcplag )));
18145 + if( el->prefix[ 14 ]) return( 0 ); /* Be sure to have terminated string */
18149 +static struct ipt_target reg =
18159 +static int __init init( void )
18161 + if( ipt_register_target( ® )) return( -EINVAL );
18162 + hashsize = 123; /* should be configurable */
18163 + hashtab = kmalloc( sizeof( void * ) * hashsize, GFP_ATOMIC );
18164 + memset( hashtab, 0, sizeof( void * ) * hashsize );
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.
18173 +static void __exit fini( void )
18177 + ipt_unregister_target( ® );
18179 + * Put back kernel memory
18181 + for( i = 0; i < hashsize; i++ )
18183 + tcplag_hash_T *p;
18185 + if(( p = hashtab[ i ]))
18187 + tcplag_event_T *ev, *evn;
18189 + hashtab[ i ] = 0;
18190 + for( ev = p->h_ACK_list; ev; ev = evn )
18195 + for( ev = p->l_ACK_list; ev; ev = evn )
18203 + kfree( hashtab );
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
18212 +/* This is a module which is used for setting
18213 + * the NFC_TRACE flag in the nfcache field of an skb.
18215 +#include <linux/module.h>
18216 +#include <linux/skbuff.h>
18218 +#include <linux/netfilter_ipv4/ip_tables.h>
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,
18228 + (*pskb)->nfcache |= NFC_TRACE;
18229 + return IPT_CONTINUE;
18233 +checkentry(const char *tablename,
18234 + const struct ipt_entry *e,
18236 + unsigned int targinfosize,
18237 + unsigned int hook_mask)
18239 + if (targinfosize != 0) {
18240 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
18245 + if (strcmp(tablename, "raw") != 0) {
18246 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
18253 +static struct ipt_target ipt_trace_reg = {
18254 + .list = { NULL, NULL },
18256 + .target = target,
18257 + .checkentry = checkentry,
18262 +static int __init init(void)
18264 + if (ipt_register_target(&ipt_trace_reg))
18270 +static void __exit fini(void)
18272 + ipt_unregister_target(&ipt_trace_reg);
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
18282 +/* TTL modification target for IP tables
18283 + * (C) 2000 by Harald Welte <laforge@gnumonks.org>
18287 + * This software is distributed under the terms of GNU GPL
18290 +#include <linux/module.h>
18291 +#include <linux/skbuff.h>
18292 +#include <linux/ip.h>
18293 +#include <net/checksum.h>
18295 +#include <linux/netfilter_ipv4/ip_tables.h>
18296 +#include <linux/netfilter_ipv4/ipt_TTL.h>
18298 +MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>");
18299 +MODULE_DESCRIPTION("IP tables TTL modification module");
18300 +MODULE_LICENSE("GPL");
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)
18306 + struct iphdr *iph = (*pskb)->nh.iph;
18307 + const struct ipt_TTL_info *info = targinfo;
18308 + u_int16_t diffs[2];
18311 + switch (info->mode) {
18312 + case IPT_TTL_SET:
18313 + new_ttl = info->ttl;
18315 + case IPT_TTL_INC:
18316 + new_ttl = iph->ttl + info->ttl;
18317 + if (new_ttl > 255)
18320 + case IPT_TTL_DEC:
18321 + new_ttl = iph->ttl + info->ttl;
18326 + new_ttl = iph->ttl;
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,
18336 + iph->check^0xFFFF));
18337 + (*pskb)->nfcache |= NFC_ALTERED;
18340 + return IPT_CONTINUE;
18343 +static int ipt_ttl_checkentry(const char *tablename,
18344 + const struct ipt_entry *e,
18346 + unsigned int targinfosize,
18347 + unsigned int hook_mask)
18349 + struct ipt_TTL_info *info = targinfo;
18351 + if (targinfosize != IPT_ALIGN(sizeof(struct ipt_TTL_info))) {
18352 + printk(KERN_WARNING "TTL: targinfosize %u != %Zu\n",
18354 + IPT_ALIGN(sizeof(struct ipt_TTL_info)));
18358 + if (strcmp(tablename, "mangle")) {
18359 + printk(KERN_WARNING "TTL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
18363 + if (info->mode > IPT_TTL_MAXMODE) {
18364 + printk(KERN_WARNING "TTL: invalid or unknown Mode %u\n",
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");
18377 +static struct ipt_target ipt_TTL = { { NULL, NULL }, "TTL",
18378 + ipt_ttl_target, ipt_ttl_checkentry, NULL, THIS_MODULE };
18380 +static int __init init(void)
18382 + return ipt_register_target(&ipt_TTL);
18385 +static void __exit fini(void)
18387 + ipt_unregister_target(&ipt_TTL);
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
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>
18401 * Released under the terms of the GPL
18404 * Specify, after how many clock ticks (intel: 100 per second) the queue
18405 * should be flushed even if it is not full yet.
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
18411 #include <linux/module.h>
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>
18421 MODULE_PARM(flushtimeout, "i");
18422 MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
18424 +static unsigned int nflog = 1;
18425 +MODULE_PARM(nflog, "i");
18426 +MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
18428 /* global data structures */
18431 @@ -153,17 +159,17 @@
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)
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;
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));
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;
18475 strncpy(pm->indev_name, in->name, sizeof(pm->indev_name));
18476 @@ -260,8 +269,7 @@
18478 UNLOCK_BH(&ulog_lock);
18480 - return IPT_CONTINUE;
18485 PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18486 @@ -270,8 +278,128 @@
18487 PRINTR("ipt_ULOG: Error building netlink message\n");
18489 UNLOCK_BH(&ulog_lock);
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)
18499 + struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
18501 + ipt_ulog_packet(pskb, hooknum, in, out, loginfo, NULL);
18503 + return IPT_CONTINUE;
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)
18512 + struct ipt_ulog_info loginfo = {
18513 + .nl_group = ULOG_DEFAULT_NLGROUP,
18515 + .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
18519 + ipt_ulog_packet(pskb, hooknum, in, out, &loginfo, prefix);
18522 +static void ip_ulog_fn(char *pfh, size_t len,
18523 + const char *prefix)
18525 + struct ipt_ulog_info loginfo = {
18526 + .nl_group = ULOG_DEFAULT_NLGROUP,
18528 + .qthreshold = ULOG_DEFAULT_QTHRESHOLD,
18532 + ulog_packet_msg_t *pm;
18534 + struct nlmsghdr *nlh;
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;
18541 + size = NLMSG_SPACE(sizeof(*pm) + len);
18543 + ub = &ulog_buffers[groupnum];
18545 + LOCK_BH(&ulog_lock);
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. */
18555 + ulog_send(groupnum);
18557 + if (!(ub->skb = ulog_alloc_skb(size)))
18558 + goto alloc_failure;
18561 + DEBUGP("ipt_ULOG: qlen %d, qthreshold %d\n", ub->qlen,
18562 + loginfo.qthreshold);
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));
18569 + pm = NLMSG_DATA(nlh);
18571 + /* Set fake hook, prefix, timestamp etc. */
18572 + pm->data_len = len;
18573 + pm->timestamp_sec = 0;
18574 + pm->timestamp_usec = 0;
18577 + strncpy(pm->prefix, prefix, sizeof(pm->prefix));
18579 + pm->indev_name[0] = '\0';
18580 + pm->outdev_name[0] = '\0';
18581 + memcpy(pm->payload, pfh, len);
18583 + /* check if we are building multi-part messages */
18584 + if (ub->qlen > 1) {
18585 + ub->lastnlh->nlmsg_flags |= NLM_F_MULTI;
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;
18594 + ub->lastnlh = nlh;
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);
18602 + UNLOCK_BH(&ulog_lock);
18607 + PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
18610 + PRINTR("ipt_ULOG: Error building netlink message\n");
18612 + UNLOCK_BH(&ulog_lock);
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,
18620 +static struct nf_logging_t ip_logging_fn
18621 += { ip_ulog_packet_fn, ip_ulog_fn };
18623 static int __init init(void)
18625 @@ -320,7 +450,6 @@
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);
18639 + nf_ip_log_register(&ip_logging_fn);
18644 @@ -345,6 +476,8 @@
18646 DEBUGP("ipt_ULOG: cleanup_module\n");
18649 + nf_ip_log_unregister(&ip_logging_fn);
18650 ipt_unregister_target(&ipt_ulog_reg);
18651 sock_release(nflognl->socket);
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
18657 +/* XOR target for IP tables
18658 + * (C) 2000 by Tim Vandermeersch <Tim.Vandermeersch@pandora.be>
18659 + * Based on ipt_TTL.c
18663 + * This software is distributed under the terms of GNU GPL
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>
18672 +#include <linux/netfilter_ipv4/ip_tables.h>
18673 +#include <linux/netfilter_ipv4/ipt_XOR.h>
18675 +MODULE_AUTHOR("Tim Vandermeersch <Tim.Vandermeersch@pandora.be>");
18676 +MODULE_DESCRIPTION("IP tables XOR module");
18677 +MODULE_LICENSE("GPL");
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)
18683 + struct ipt_XOR_info *info = (void *) targinfo;
18684 + struct iphdr *iph = (*pskb)->nh.iph;
18685 + struct tcphdr *tcph;
18686 + struct udphdr *udph;
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 ] ^=
18698 + if (info->key[j] == 0x00)
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 ] ^=
18710 + if (info->key[j] == 0x00)
18715 + return IPT_CONTINUE;
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)
18722 + struct ipt_XOR_info *info = targinfo;
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)));
18730 + if (strcmp(tablename, "mangle")) {
18731 + printk(KERN_WARNING "XOR: can only be called from"
18732 + "\"mangle\" table, not \"%s\"\n", tablename);
18736 + if (!strcmp(info->key, "")) {
18737 + printk(KERN_WARNING "XOR: You must specify a key");
18741 + if (info->block_size == 0) {
18742 + printk(KERN_WARNING "XOR: You must specify a block-size");
18749 +static struct ipt_target ipt_XOR = { { NULL, NULL }, "XOR",
18750 + ipt_xor_target, ipt_xor_checkentry, NULL, THIS_MODULE };
18752 +static int __init init(void)
18754 + return ipt_register_target(&ipt_XOR);
18757 +static void __exit fini(void)
18759 + ipt_unregister_target(&ipt_XOR);
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
18769 + * iptables module to match inet_addr_type() of an ip.
18772 +#include <linux/module.h>
18773 +#include <linux/skbuff.h>
18774 +#include <linux/netdevice.h>
18775 +#include <net/route.h>
18777 +#include <linux/netfilter_ipv4/ipt_addrtype.h>
18778 +#include <linux/netfilter_ipv4/ip_tables.h>
18780 +MODULE_LICENSE("GPL");
18782 +static inline int match_type(u_int32_t addr, u_int16_t mask)
18784 + return !!(mask & (1 << inet_addr_type(addr)));
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,
18792 + const struct ipt_addrtype_info *info = matchinfo;
18793 + const struct iphdr *iph = skb->nh.iph;
18796 + if (info->source)
18797 + ret &= match_type(iph->saddr, info->source)^info->invert_source;
18799 + ret &= match_type(iph->daddr, info->dest)^info->invert_dest;
18804 +static int checkentry(const char *tablename, const struct ipt_ip *ip,
18805 + void *matchinfo, unsigned int matchsize,
18806 + unsigned int hook_mask)
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)));
18817 +static struct ipt_match addrtype_match = { { NULL, NULL }, "addrtype", &match,
18818 + &checkentry, NULL, THIS_MODULE };
18820 +static int __init init(void)
18822 + return ipt_register_match(&addrtype_match);
18825 +static void __exit fini(void)
18827 + ipt_unregister_match(&addrtype_match);
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
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
18852 +/*-------------------------------------------*\
18853 +| Netfilter Condition Module |
18855 +| Description: This module allows firewall |
18856 +| rules to match using condition variables |
18857 +| stored in /proc files. |
18859 +| Author: Stephane Ouellette 2002-10-22 |
18860 +| <ouellettes@videotron.ca> |
18863 +| 2003-02-10 Second version with improved |
18864 +| locking and simplified code. |
18866 +| This software is distributed under the |
18867 +| terms of the GNU GPL. |
18868 +\*-------------------------------------------*/
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>
18879 +#ifndef CONFIG_PROC_FS
18880 +#error "Proc file system support is required for this module"
18884 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
18885 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
18886 +MODULE_LICENSE("GPL");
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 */
18897 +static rwlock_t list_lock;
18898 +static struct condition_variable *head = NULL;
18899 +static struct proc_dir_entry *proc_net_condition = NULL;
18903 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
18904 + int length, int *eof, void *data)
18906 + struct condition_variable *var =
18907 + (struct condition_variable *) data;
18909 + if (offset == 0) {
18911 + buffer[0] = (var->enabled) ? '1' : '0';
18912 + buffer[1] = '\n';
18922 +ipt_condition_write_info(struct file *file, const char *buffer,
18923 + unsigned long length, void *data)
18925 + struct condition_variable *var =
18926 + (struct condition_variable *) data;
18929 + /* Match only on the first character */
18930 + switch (buffer[0]) {
18932 + var->enabled = 0;
18935 + var->enabled = 1;
18939 + return (int) length;
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)
18948 + const struct condition_info *info =
18949 + (const struct condition_info *) matchinfo;
18950 + struct condition_variable *var;
18951 + int condition_status = 0;
18953 + read_lock(&list_lock);
18955 + for (var = head; var; var = var->next) {
18956 + if (strcmp(info->name, var->status_proc->name) == 0) {
18957 + condition_status = var->enabled;
18962 + read_unlock(&list_lock);
18964 + return condition_status ^ info->invert;
18970 +checkentry(const char *tablename, const struct ipt_ip *ip,
18971 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
18973 + struct condition_info *info = (struct condition_info *) matchinfo;
18974 + struct condition_variable *var, *newvar;
18976 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
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);
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);
18991 + read_unlock(&list_lock);
18993 + /* At this point, we need to allocate a new condition variable */
18994 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
18999 + /* Create the condition variable's proc file entry */
19000 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
19002 + if (!newvar->status_proc) {
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.
19009 + read_lock(&list_lock);
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);
19019 + read_unlock(&list_lock);
19023 + atomic_set(&newvar->refcount, 1);
19024 + newvar->enabled = 0;
19025 + newvar->status_proc->owner = THIS_MODULE;
19026 + newvar->status_proc->data = newvar;
19028 + newvar->status_proc->read_proc = ipt_condition_read_info;
19029 + newvar->status_proc->write_proc = ipt_condition_write_info;
19031 + write_lock(&list_lock);
19033 + newvar->next = head;
19036 + write_unlock(&list_lock);
19043 +destroy(void *matchinfo, unsigned int matchsize)
19045 + struct condition_info *info = (struct condition_info *) matchinfo;
19046 + struct condition_variable *var, *prev = NULL;
19048 + if (matchsize != IPT_ALIGN(sizeof(struct condition_info)))
19051 + write_lock(&list_lock);
19053 + for (var = head; var && strcmp(info->name, var->status_proc->name);
19054 + prev = var, var = var->next);
19056 + if (var && atomic_dec_and_test(&var->refcount)) {
19058 + prev->next = var->next;
19060 + head = var->next;
19062 + write_unlock(&list_lock);
19063 + remove_proc_entry(var->status_proc->name, proc_net_condition);
19066 + write_unlock(&list_lock);
19070 +static struct ipt_match condition_match = {
19071 + .name = "condition",
19073 + .checkentry = &checkentry,
19074 + .destroy = &destroy,
19075 + .me = THIS_MODULE
19084 + rwlock_init(&list_lock);
19085 + proc_net_condition = proc_mkdir("ipt_condition", proc_net);
19087 + if (proc_net_condition) {
19088 + errorcode = ipt_register_match(&condition_match);
19091 + remove_proc_entry("ipt_condition", proc_net);
19093 + errorcode = -EACCES;
19095 + return errorcode;
19099 +static void __exit
19102 + ipt_unregister_match(&condition_match);
19103 + remove_proc_entry("ipt_condition", proc_net);
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
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
19121 + * Kernel module to match connection tracking information.
19122 + * GPL (C) 1999 Rusty Russell (rusty@rustcorp.com.au).
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>
19135 +MODULE_LICENSE("GPL");
19137 +/* we'll save the tuples of all connections we care about */
19138 +struct ipt_connlimit_conn
19140 + struct list_head list;
19141 + struct ip_conntrack_tuple tuple;
19144 +struct ipt_connlimit_data {
19146 + struct list_head iphash[256];
19149 +static int ipt_iphash(u_int32_t addr)
19153 + hash = addr & 0xff;
19154 + hash ^= (addr >> 8) & 0xff;
19155 + hash ^= (addr >> 16) & 0xff;
19156 + hash ^= (addr >> 24) & 0xff;
19160 +static int count_them(struct ipt_connlimit_data *data,
19161 + u_int32_t addr, u_int32_t mask,
19162 + struct ip_conntrack *ct)
19165 + const static char *tcp[] = { "none", "established", "syn_sent", "syn_recv",
19166 + "fin_wait", "time_wait", "close", "close_wait",
19167 + "last_ack", "listen" };
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;
19175 + spin_lock(&data->lock);
19176 + tuple = ct->tuplehash[0].tuple;
19177 + hash = &data->iphash[ipt_iphash(addr & mask)];
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)) &&
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" */
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");
19198 + if (NULL == found) {
19199 + /* this one is gone */
19201 + list_del(lh->next);
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 */
19209 + list_del(lh->next);
19211 + nf_conntrack_put(&found->ctrack->infos[0]);
19214 + if ((addr & mask) == (conn->tuple.src.ip & mask)) {
19215 + /* same source IP address -> be counted! */
19218 + nf_conntrack_put(&found->ctrack->infos[0]);
19221 + /* save the new connection in our list */
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));
19228 + conn = kmalloc(sizeof(*conn),GFP_ATOMIC);
19229 + if (NULL == conn)
19231 + memset(conn,0,sizeof(*conn));
19232 + INIT_LIST_HEAD(&conn->list);
19233 + conn->tuple = tuple;
19234 + list_add(&conn->list,hash);
19237 + spin_unlock(&data->lock);
19242 +match(const struct sk_buff *skb,
19243 + const struct net_device *in,
19244 + const struct net_device *out,
19245 + const void *matchinfo,
19248 + u_int16_t datalen,
19251 + const struct ipt_connlimit_info *info = matchinfo;
19252 + int connections, match;
19253 + struct ip_conntrack *ct;
19254 + enum ip_conntrack_info ctinfo;
19256 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
19257 + if (NULL == ct) {
19258 + printk("ipt_connlimit: Oops: invalid ct state ?\n");
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 :-) */
19268 + match = (info->inverse) ? (connections <= info->limit) : (connections > info->limit);
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");
19279 +static int check(const char *tablename,
19280 + const struct ipt_ip *ip,
19282 + unsigned int matchsize,
19283 + unsigned int hook_mask)
19285 + struct ipt_connlimit_info *info = matchinfo;
19288 + /* verify size */
19289 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connlimit_info)))
19292 + /* refuse anything but tcp */
19293 + if (ip->proto != IPPROTO_TCP)
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]));
19305 +static void destroy(void *matchinfo, unsigned int matchinfosize)
19307 + struct ipt_connlimit_info *info = matchinfo;
19308 + struct ipt_connlimit_conn *conn;
19309 + struct list_head *hash;
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);
19321 + kfree(info->data);
19324 +static struct ipt_match connlimit_match
19325 += { { NULL, NULL }, "connlimit", &match, &check, &destroy, THIS_MODULE };
19327 +static int __init init(void)
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);
19335 +static void __exit fini(void)
19337 + ipt_unregister_match(&connlimit_match);
19338 + if (ip_conntrack_module)
19339 + __MOD_DEC_USE_COUNT(ip_conntrack_module);
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
19348 +/* Kernel module to match connection mark values. */
19349 +#include <linux/module.h>
19350 +#include <linux/skbuff.h>
19352 +#include <linux/netfilter_ipv4/ip_tables.h>
19353 +#include <linux/netfilter_ipv4/ipt_connmark.h>
19354 +#include <linux/netfilter_ipv4/ip_conntrack.h>
19357 +match(const struct sk_buff *skb,
19358 + const struct net_device *in,
19359 + const struct net_device *out,
19360 + const void *matchinfo,
19363 + u_int16_t datalen,
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);
19372 + return ((ct->mark & info->mask) == info->mark) ^ info->invert;
19376 +checkentry(const char *tablename,
19377 + const struct ipt_ip *ip,
19379 + unsigned int matchsize,
19380 + unsigned int hook_mask)
19382 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_connmark_info)))
19388 +static struct ipt_match connmark_match
19389 += { { NULL, NULL }, "connmark", &match, &checkentry, NULL, THIS_MODULE };
19391 +static int __init init(void)
19393 + return ipt_register_match(&connmark_match);
19396 +static void __exit fini(void)
19398 + ipt_unregister_match(&connmark_match);
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
19408 #define FWINV(bool,invflg) ((bool) ^ !!(sinfo->invflags & invflg))
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;
19414 + statebit = IPT_CONNTRACK_STATE_BIT(ctinfo);
19416 + statebit = IPT_CONNTRACK_STATE_INVALID;
19418 if(sinfo->flags & IPT_CONNTRACK_STATE) {
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
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
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 .
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 .
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>
19464 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
19465 + Expressed in percentage
19468 +#define PAR_LOW 1/100
19469 +#define PAR_HIGH 1
19471 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED ;
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");
19477 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19479 + if (tx >= maxi) return 100;
19481 + if (tx <= mini) return 0;
19483 + return ( (100*(tx-mini)) / (maxi-mini) ) ;
19486 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
19488 + if (tx <= mini) return 100;
19490 + if (tx >= maxi) return 0;
19492 + return ( (100*( maxi - tx )) / ( maxi - mini ) ) ;
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,
19503 + u_int16_t datalen,
19506 + /* From userspace */
19508 + struct ipt_fuzzy_info *info = (struct ipt_fuzzy_info *) matchinfo;
19510 + u_int8_t random_number;
19511 + unsigned long amount ;
19512 + u_int8_t howhigh , howlow ;
19515 + spin_lock_bh(&fuzzy_lock) ; /* Rise the lock */
19517 + info->bytes_total += pskb->len ;
19518 + info->packets_total++ ;
19520 + info->present_time = jiffies ;
19522 + if ( info->present_time >= info->previous_time )
19523 + amount = info->present_time - info->previous_time ;
19525 + /* There was a transition : I choose to re-sample
19526 + and keep the old acceptance rate...
19530 + info->previous_time = info->present_time ;
19531 + info->bytes_total = info->packets_total = 0;
19534 + if ( amount > HZ/10 ) /* More than 100 ms elapsed ... */
19537 + info->mean_rate = (u_int32_t) ( ( HZ * info->packets_total ) \
19540 + info->previous_time = info->present_time ;
19541 + info->bytes_total = info->packets_total = 0 ;
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);
19546 + info->acceptance_rate = (u_int8_t) \
19547 + ( howhigh*PAR_LOW + PAR_HIGH*howlow ) ;
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 ,
19559 + spin_unlock_bh(&fuzzy_lock) ; /* Release the lock */
19562 + if ( info->acceptance_rate < 100 )
19564 + get_random_bytes((void *)(&random_number), 1);
19566 + /* If within the acceptance , it can pass => don't match */
19567 + if ( random_number <= (255 * info->acceptance_rate) / 100 )
19570 + return 1; /* It can't pass ( It matches ) */
19573 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
19578 +ipt_fuzzy_checkentry(const char *tablename,
19579 + const struct ipt_ip *e,
19581 + unsigned int matchsize,
19582 + unsigned int hook_mask)
19585 + const struct ipt_fuzzy_info *info = matchinfo;
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)));
19593 +if ((info->minimum_rate < MINFUZZYRATE ) || (info->maximum_rate > MAXFUZZYRATE)
19594 + || (info->minimum_rate >= info->maximum_rate ))
19596 + printk("ipt_fuzzy: BAD limits , please verify !!!\n");
19603 +static struct ipt_match ipt_fuzzy_reg = {
19607 + ipt_fuzzy_checkentry,
19611 +static int __init init(void)
19613 + if (ipt_register_match(&ipt_fuzzy_reg))
19619 +static void __exit fini(void)
19621 + ipt_unregister_match(&ipt_fuzzy_reg);
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
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>
19638 struct ip_conntrack_expect *exp;
19639 struct ip_conntrack *ct;
19640 enum ip_conntrack_info ctinfo;
19643 ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
19645 @@ -49,23 +51,27 @@
19649 + READ_LOCK(&ip_conntrack_lock);
19650 if (!exp->expectant) {
19651 DEBUGP("ipt_helper: expectation %p without expectant !?!\n",
19657 if (!exp->expectant->helper) {
19658 DEBUGP("ipt_helper: master ct %p has no helper\n",
19664 DEBUGP("master's name = %s , info->name = %s\n",
19665 exp->expectant->helper->name, info->name);
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;
19672 + READ_UNLOCK(&ip_conntrack_lock);
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
19682 + * iptables module to match IP address ranges
19683 + * (c) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
19685 + * Released under the terms of GNU GPLv2.
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>
19694 +MODULE_LICENSE("GPL");
19695 +MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
19696 +MODULE_DESCRIPTION("iptables arbitrary IP range match module");
19699 +#define DEBUGP printk
19701 +#define DEBUGP(format, args...)
19705 +match(const struct sk_buff *skb,
19706 + const struct net_device *in,
19707 + const struct net_device *out,
19708 + const void *matchinfo,
19711 + u_int16_t datalen,
19714 + const struct ipt_iprange_info *info = matchinfo;
19715 + const struct iphdr *iph = skb->nh.iph;
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));
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));
19747 +static int check(const char *tablename,
19748 + const struct ipt_ip *ip,
19750 + unsigned int matchsize,
19751 + unsigned int hook_mask)
19753 + /* verify size */
19754 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_iprange_info)))
19760 +static struct ipt_match iprange_match =
19762 + .list = { NULL, NULL },
19763 + .name = "iprange",
19765 + .checkentry = &check,
19767 + .me = THIS_MODULE
19770 +static int __init init(void)
19772 + return ipt_register_match(&iprange_match);
19775 +static void __exit fini(void)
19777 + ipt_unregister_match(&iprange_match);
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
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
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.
19798 +#include <linux/module.h>
19799 +#include <linux/skbuff.h>
19800 +#include <net/ip.h>
19802 +#include <linux/netfilter_ipv4/ip_tables.h>
19803 +#include <linux/netfilter_ipv4/ipt_ipv4options.h>
19805 +MODULE_LICENSE("GPL");
19808 +match(const struct sk_buff *skb,
19809 + const struct net_device *in,
19810 + const struct net_device *out,
19811 + const void *matchinfo,
19814 + u_int16_t datalen,
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;
19821 + if (iph->ihl * 4 == sizeof(struct iphdr)) {
19822 + /* No options, so we match only the "DONTs" and the "IGNOREs" */
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))
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 */
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 ! */
19844 + opt = &(IPCB(skb)->opt);
19846 + /* source routing */
19847 + if ((info->options & IPT_IPV4OPTION_MATCH_SSRR) == IPT_IPV4OPTION_MATCH_SSRR) {
19848 + if (!((opt->srr) & (opt->is_strictroute)))
19851 + else if ((info->options & IPT_IPV4OPTION_MATCH_LSRR) == IPT_IPV4OPTION_MATCH_LSRR) {
19852 + if (!((opt->srr) & (!opt->is_strictroute)))
19855 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_SRR) == IPT_IPV4OPTION_DONT_MATCH_SRR) {
19859 + /* record route */
19860 + if ((info->options & IPT_IPV4OPTION_MATCH_RR) == IPT_IPV4OPTION_MATCH_RR) {
19864 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_RR) == IPT_IPV4OPTION_DONT_MATCH_RR) {
19869 + if ((info->options & IPT_IPV4OPTION_MATCH_TIMESTAMP) == IPT_IPV4OPTION_MATCH_TIMESTAMP) {
19873 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) == IPT_IPV4OPTION_DONT_MATCH_TIMESTAMP) {
19877 + /* router-alert option */
19878 + if ((info->options & IPT_IPV4OPTION_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_MATCH_ROUTER_ALERT) {
19879 + if (!opt->router_alert)
19882 + else if ((info->options & IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) == IPT_IPV4OPTION_DONT_MATCH_ROUTER_ALERT) {
19883 + if (opt->router_alert)
19892 +checkentry(const char *tablename,
19893 + const struct ipt_ip *ip,
19895 + unsigned int matchsize,
19896 + unsigned int hook_mask)
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)))
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 */
19935 + /* everything looks ok. */
19939 +static struct ipt_match ipv4options_match
19940 += { { NULL, NULL }, "ipv4options", &match, &checkentry, NULL, THIS_MODULE };
19942 +static int __init init(void)
19944 + printk("ipt_ipv4options loading\n");
19945 + return ipt_register_match(&ipv4options_match);
19948 +static void __exit fini(void)
19950 + ipt_unregister_match(&ipv4options_match);
19951 + printk("ipt_ipv4options unloaded\n");
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
19963 - const struct ipt_mark_info *info = matchinfo;
19964 + const struct ipt_mark_info *info = (struct ipt_mark_info *)matchinfo;
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;
19970 + if (info->bit_op == IPT_MARK_BIT_OP_AND)
19971 + return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
19973 + return ((skb->nfmark | info->mask) == info->mark) ^ info->invert;
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
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>
19988 +#include <linux/netfilter_ipv4/ipt_mport.h>
19989 +#include <linux/netfilter_ipv4/ip_tables.h>
19991 +MODULE_LICENSE("GPL");
19994 +#define duprintf(format, args...) printk(format , ## args)
19996 +#define duprintf(format, args...)
19999 +/* Returns 1 if the port is matched by the test, 0 otherwise. */
20001 +ports_match(const struct ipt_mport *minfo, u_int16_t src, u_int16_t dst)
20005 + u_int16_t pflags = minfo->pflags;
20006 + for (i=0, m=1; i<IPT_MULTI_PORTS; i++, m<<=1) {
20010 + && minfo->ports[i] == 65535)
20013 + s = minfo->ports[i];
20015 + if (pflags & m) {
20016 + e = minfo->ports[++i];
20021 + if (minfo->flags & IPT_MPORT_SOURCE
20022 + && src >= s && src <= e)
20025 + if (minfo->flags & IPT_MPORT_DESTINATION
20026 + && dst >= s && dst <= e)
20034 +match(const struct sk_buff *skb,
20035 + const struct net_device *in,
20036 + const struct net_device *out,
20037 + const void *matchinfo,
20040 + u_int16_t datalen,
20043 + const struct udphdr *udp = hdr;
20044 + const struct ipt_mport *minfo = matchinfo;
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");
20056 + /* Must not be a fragment. */
20058 + && ports_match(minfo, ntohs(udp->source), ntohs(udp->dest));
20061 +/* Called when user tries to insert an entry of this type. */
20063 +checkentry(const char *tablename,
20064 + const struct ipt_ip *ip,
20066 + unsigned int matchsize,
20067 + unsigned int hook_mask)
20069 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_mport)))
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));
20078 +static struct ipt_match mport_match
20079 += { { NULL, NULL }, "mport", &match, &checkentry, NULL, THIS_MODULE };
20081 +static int __init init(void)
20083 + return ipt_register_match(&mport_match);
20086 +static void __exit fini(void)
20088 + ipt_unregister_match(&mport_match);
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
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
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
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
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>
20131 +MODULE_LICENSE("GPL");
20134 + * State information.
20138 + u_int16_t number;
20141 +static struct state states[IPT_NTH_NUM_COUNTERS];
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,
20150 + u_int16_t datalen,
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))
20158 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
20162 + spin_lock(&states[counter].lock);
20164 + /* Are we matching every nth packet?*/
20165 + if (info->packet == 0xFF)
20167 + /* We're matching every nth packet and only every nth packet*/
20168 + /* Do we match or invert match? */
20169 + if (info->not == 0)
20171 + if (states[counter].number == 0)
20173 + ++states[counter].number;
20176 + if (states[counter].number >= info->every)
20177 + states[counter].number = 0; /* reset the counter */
20179 + ++states[counter].number;
20184 + if (states[counter].number == 0)
20186 + ++states[counter].number;
20189 + if (states[counter].number >= info->every)
20190 + states[counter].number = 0;
20192 + ++states[counter].number;
20198 + /* We're using the --packet, so there must be a rule for every value */
20199 + if (states[counter].number == info->packet)
20201 + /* only increment the counter when a match happens */
20202 + if (states[counter].number >= info->every)
20203 + states[counter].number = 0; /* reset the counter */
20205 + ++states[counter].number;
20213 + /* don't match */
20214 + spin_unlock(&states[counter].lock);
20218 + spin_unlock(&states[counter].lock);
20223 +ipt_nth_checkentry(const char *tablename,
20224 + const struct ipt_ip *e,
20226 + unsigned int matchsize,
20227 + unsigned int hook_mask)
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))
20234 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IPT_NTH_NUM_COUNTERS-1);
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)));
20244 + states[counter].number = info->startat;
20249 +static struct ipt_match ipt_nth_reg = {
20253 + ipt_nth_checkentry,
20257 +static int __init init(void)
20259 + unsigned counter;
20260 + memset(&states, 0, sizeof(states));
20261 + if (ipt_register_match(&ipt_nth_reg))
20264 + for(counter = 0; counter < IPT_NTH_NUM_COUNTERS; counter++)
20266 + spin_lock_init(&(states[counter].lock));
20269 + printk("ipt_nth match loaded\n");
20273 +static void __exit fini(void)
20275 + ipt_unregister_match(&ipt_nth_reg);
20276 + printk("ipt_nth match unloaded\n");
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
20288 + * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
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.
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.
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
20307 + * OS fingerprint matching module.
20308 + * It simply compares various parameters from SYN packet with
20309 + * some hardcoded ones.
20311 + * Original table was created by Michal Zalewski <lcamtuf@coredump.cx>
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>
20327 +#include <net/sock.h>
20328 +#include <net/ip.h>
20330 +#include <linux/netfilter_ipv4/ip_tables.h>
20332 +#include <linux/netfilter_ipv4/ipt_osf.h>
20334 +//#define OSF_DEBUG
20337 +#define log(x...) printk(KERN_ERR "ipt_osf: " x)
20338 +#define loga(x...) printk(x)
20340 +#define log(x...) do {} while(0)
20341 +#define loga(x...) do {} while(0)
20344 +#define FMATCH_WRONG 0
20345 +#define FMATCH_OK 1
20346 +#define FMATCH_OPT_WRONG 2
20348 +#define OPTDEL ','
20349 +#define OSFPDEL ':'
20350 +#define MAXOPTSTRLEN 128
20351 +#define OSFFLUSH "FLUSH"
20353 +static rwlock_t osf_lock = RW_LOCK_UNLOCKED;
20354 +static struct list_head finger_list;
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);
20361 +static struct ipt_match osf_match =
20372 +match(const struct sk_buff *skb,
20373 + const struct net_device *in,
20374 + const struct net_device *out,
20375 + const void *matchinfo,
20378 + u_int16_t datalen,
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;
20391 + if (!ip || !info)
20394 + tcp = (struct tcphdr *)((u_int32_t *)ip + ip->ihl);
20399 + totlen = ntohs(ip->tot_len);
20400 + df = ((ntohs(ip->frag_off) & IP_DF)?1:0);
20401 + window = ntohs(tcp->window);
20403 + if (tcp->doff*4 > sizeof(struct tcphdr))
20405 + _optp = optp = (char *)(tcp+1);
20406 + optsize = tcp->doff*4 - sizeof(struct tcphdr);
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.
20414 + read_lock(&osf_lock);
20415 + list_for_each(ent, &finger_list)
20417 + f = list_entry(ent, struct osf_finger, flist);
20419 + if (strcmp(info->genre, f->genre))
20424 + if ( ip->ttl == f->ttl &&
20425 + totlen == f->ss &&
20428 + unsigned long foptsize;
20430 + unsigned short mss = 0;
20434 + switch (f->wss.wc)
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);
20445 + if (check_WSS == 4)
20448 + /* Check options */
20451 + for (optnum=0; optnum<f->opt_num; ++optnum)
20452 + foptsize += f->opt[optnum].length;
20455 + if (foptsize > MAX_IPOPTLEN || optsize > MAX_IPOPTLEN || optsize != foptsize)
20460 + fmatch = FMATCH_OK;
20461 + loga("\tYEP : matching without options.\n");
20466 + for (optnum=0; optnum<f->opt_num; ++optnum)
20468 + if (f->opt[optnum].kind == (*optp))
20470 + unsigned char len = f->opt[optnum].length;
20471 + unsigned char *optend = optp + len;
20473 + fmatch = FMATCH_OK;
20475 + if (*optp == OSFOPT_MSS) /* MSS */
20476 + mss = ntohs(*(unsigned short *)(optp+2));
20480 + /* Skip kind and length fields*/
20483 + if (f->opt[optnum].wc.wc != 0)
20485 + unsigned long tmp = 0;
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));
20492 + tmp = ntohl(tmp);
20493 + if (tmp != f->opt[optnum].wc.val)
20494 + fmatch = FMATCH_OPT_WRONG;
20501 + fmatch = FMATCH_OPT_WRONG;
20503 + if (fmatch != FMATCH_OK)
20507 + if (fmatch != FMATCH_OPT_WRONG)
20509 + fmatch = FMATCH_WRONG;
20511 + switch (check_WSS)
20514 + if (window == f->wss.val)
20515 + fmatch = FMATCH_OK;
20517 + case 1: /* MSS */
20518 + if (window == f->wss.val*mss)
20519 + fmatch = FMATCH_OK;
20521 + case 2: /* MTU */
20522 + if (window == f->wss.val*(mss+40))
20523 + fmatch = FMATCH_OK;
20525 + case 3: /* MOD */
20526 + if (window % f->wss.val == 0)
20527 + fmatch = FMATCH_OK;
20533 + if (fmatch == FMATCH_OK)
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);
20545 + read_unlock(&osf_lock);
20547 + return (fmatch == FMATCH_OK)?1:0;
20551 +checkentry(const char *tablename,
20552 + const struct ipt_ip *ip,
20554 + unsigned int matchsize,
20555 + unsigned int hook_mask)
20557 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_osf_info)))
20559 + if (ip->proto != IPPROTO_TCP)
20565 +static struct osf_finger * finger_alloc()
20567 + struct osf_finger *f;
20569 + f = kmalloc(sizeof(struct osf_finger), GFP_KERNEL);
20571 + memset(f, 0, sizeof(struct osf_finger));
20576 +static void finger_free(struct osf_finger *f)
20578 + memset(f, 0, sizeof(struct osf_finger));
20583 +static void osf_parse_opt(struct osf_opt *opt, int *optnum, char *obuf, int olen)
20587 + unsigned long val;
20591 + while (ptr != NULL && i < olen)
20600 + ptr = strchr(&obuf[i], OPTDEL);
20605 + i += (int)(ptr-&obuf[i]);
20612 + op = OSFOPT_SACKP;
20613 + ptr = strchr(&obuf[i], OPTDEL);
20618 + i += (int)(ptr-&obuf[i]);
20626 + ptr = strchr(&obuf[i], OPTDEL);
20631 + i += (int)(ptr-&obuf[i]);
20639 + ptr = strchr(&obuf[i], OPTDEL);
20642 + switch (obuf[i+1])
20644 + case '%': wc = '%'; break;
20645 + case 'S': wc = 'S'; break;
20646 + case 'T': wc = 'T'; break;
20647 + default: wc = 0; break;
20653 + val = simple_strtoul(&obuf[i+2], NULL, 10);
20655 + val = simple_strtoul(&obuf[i+1], NULL, 10);
20656 + i += (int)(ptr-&obuf[i]);
20664 + ptr = strchr(&obuf[i], OPTDEL);
20667 + if (obuf[i+1] == '%')
20672 + val = simple_strtoul(&obuf[i+2], NULL, 10);
20674 + val = simple_strtoul(&obuf[i+1], NULL, 10);
20675 + i += (int)(ptr-&obuf[i]);
20683 + ptr = strchr(&obuf[i], OPTDEL);
20688 + i += (int)(ptr-&obuf[i]);
20695 + ptr = strchr(&obuf[i], OPTDEL);
20699 + i += (int)(ptr-&obuf[i]);
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;
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);
20720 +static int osf_proc_read(char *buf, char **start, off_t off, int count, int *eof, void *data)
20722 + struct list_head *ent;
20723 + struct osf_finger *f = NULL;
20729 + read_lock_bh(&osf_lock);
20730 + list_for_each(ent, &finger_list)
20732 + f = list_entry(ent, struct osf_finger, flist);
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);
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);
20743 + //count += sprintf(buf+count, " OPT: ");
20744 + for (i=0; i<f->opt_num; ++i)
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);
20753 + count += sprintf(buf+count, "\n");
20755 + read_unlock_bh(&osf_lock);
20760 +static int osf_proc_write(struct file *file, const char *buffer, unsigned long count, void *data)
20764 + char quirks[MAXOPTSTRLEN], obuf[MAXOPTSTRLEN];
20765 + struct osf_finger *finger;
20766 + struct list_head *ent, *n;
20768 + char *pbeg, *pend;
20770 + if (count == strlen(OSFFLUSH) && !strncmp(buffer, OSFFLUSH, strlen(OSFFLUSH)))
20773 + write_lock_bh(&osf_lock);
20774 + list_for_each_safe(ent, n, &finger_list)
20777 + finger = list_entry(ent, struct osf_finger, flist);
20778 + list_del(&finger->flist);
20779 + finger_free(finger);
20781 + write_unlock_bh(&osf_lock);
20783 + log("Flushed %d entries.\n", i);
20790 + for (i=0; i<count && buffer[i] != '\0'; ++i)
20791 + if (buffer[i] == ':')
20794 + if (cnt != 7 || i != count)
20796 + log("Wrong input line cnt=%d[7], len=%lu[%lu]\n",
20802 + memset(quirks, 0, sizeof(quirks));
20803 + memset(obuf, 0, sizeof(obuf));
20805 + finger = finger_alloc();
20808 + log("Failed to allocate new fingerprint entry.\n");
20812 + pbeg = (char *)buffer;
20813 + pend = strchr(pbeg, OSFPDEL);
20817 + if (pbeg[0] == 'S')
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;
20825 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
20827 + else if (pbeg[0] == 'T')
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;
20835 + finger->wss.val = simple_strtoul(pbeg+1, NULL, 10);
20837 + if (isdigit(pbeg[0]))
20839 + finger->wss.wc = 0;
20840 + finger->wss.val = simple_strtoul(pbeg, NULL, 10);
20845 + pend = strchr(pbeg, OSFPDEL);
20849 + finger->ttl = simple_strtoul(pbeg, NULL, 10);
20852 + pend = strchr(pbeg, OSFPDEL);
20856 + finger->df = simple_strtoul(pbeg, NULL, 10);
20859 + pend = strchr(pbeg, OSFPDEL);
20863 + finger->ss = simple_strtoul(pbeg, NULL, 10);
20867 + pend = strchr(pbeg, OSFPDEL);
20871 + cnt = snprintf(obuf, sizeof(obuf), "%s", pbeg);
20875 + pend = strchr(pbeg, OSFPDEL);
20879 + cnt = snprintf(quirks, sizeof(quirks), "%s", pbeg);
20883 + pend = strchr(pbeg, OSFPDEL);
20887 + if (pbeg[0] == '@' || pbeg[0] == '*')
20888 + cnt = snprintf(finger->genre,
20889 + ((count-(pbeg+1-buffer)+1) > MAXGENRELEN)?MAXGENRELEN:(count-(pbeg+1-buffer)+1),
20892 + cnt = snprintf(finger->genre,
20893 + ((count-(pbeg-buffer)+1) > MAXGENRELEN)?MAXGENRELEN:(count-(pbeg-buffer)+1),
20898 + cnt = snprintf(finger->details,
20899 + ((count - (pbeg - buffer)+1) > MAXDETLEN)?MAXDETLEN:(count - (pbeg - buffer)+1),
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);
20907 + osf_parse_opt(finger->opt, &finger->opt_num, obuf, sizeof(obuf));
20910 + write_lock_bh(&osf_lock);
20911 + list_add(&finger->flist, &finger_list);
20912 + write_unlock_bh(&osf_lock);
20917 +static int __init osf_init(void)
20920 + struct proc_dir_entry *p;
20922 + log("Startng OS fingerprint matching module.\n");
20924 + INIT_LIST_HEAD(&finger_list);
20926 + err = ipt_register_match(&osf_match);
20929 + log("Failed to register OS fingerprint matching module.\n");
20933 + p = create_proc_entry("sys/net/ipv4/osf", S_IFREG | 0644, NULL);
20936 + ipt_unregister_match(&osf_match);
20940 + p->write_proc = osf_proc_write;
20941 + p->read_proc = osf_proc_read;
20946 +static void __exit osf_fini(void)
20948 + struct list_head *ent, *n;
20949 + struct osf_finger *f;
20951 + remove_proc_entry("sys/net/ipv4/osf", NULL);
20952 + ipt_unregister_match(&osf_match);
20954 + list_for_each_safe(ent, n, &finger_list)
20956 + f = list_entry(ent, struct osf_finger, flist);
20957 + list_del(&f->flist);
20961 + log("OS fingerprint matching module finished.\n");
20964 +module_init(osf_init);
20965 +module_exit(osf_fini);
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
20974 locally generated outgoing packets.
20976 Copyright (C) 2000 Marc Boucher
20978 + 03/26/2003 Patrick McHardy <kaber@trash.net>: LOCAL_IN support
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>
20991 #include <linux/netfilter_ipv4/ipt_owner.h>
20992 #include <linux/netfilter_ipv4/ip_tables.h>
20995 -match_comm(const struct sk_buff *skb, const char *comm)
20996 +match_comm(const struct sock *sk, const char *comm)
20998 struct task_struct *p;
20999 struct files_struct *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);
21008 read_unlock(&tasklist_lock);
21013 -match_pid(const struct sk_buff *skb, pid_t pid)
21014 +match_pid(const struct sock *sk, pid_t pid)
21016 struct task_struct *p;
21017 struct files_struct *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);
21026 read_unlock(&tasklist_lock);
21027 @@ -75,10 +83,10 @@
21031 -match_sid(const struct sk_buff *skb, pid_t sid)
21032 +match_sid(const struct sock *sk, pid_t sid)
21034 struct task_struct *p;
21035 - struct file *file = skb->sk->socket->file;
21036 + struct file *file = sk->socket->file;
21039 read_lock(&tasklist_lock);
21040 @@ -119,41 +127,71 @@
21043 const struct ipt_owner_info *info = matchinfo;
21045 - if (!skb->sk || !skb->sk->socket || !skb->sk->socket->file)
21047 + struct iphdr *iph = skb->nh.iph;
21048 + struct sock *sk = NULL;
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);
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);
21072 + if (!sk || !sk->socket || !sk->socket->file)
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))
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))
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))
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))
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))
21126 @@ -164,11 +202,19 @@
21127 unsigned int 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");
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");
21145 if (matchsize != IPT_ALIGN(sizeof(struct ipt_owner_info)))
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
21152 +/* Kernel module to match an IP address pool. */
21154 +#include <linux/module.h>
21155 +#include <linux/ip.h>
21156 +#include <linux/skbuff.h>
21158 +#include <linux/netfilter_ipv4/ip_tables.h>
21159 +#include <linux/netfilter_ipv4/ip_pool.h>
21160 +#include <linux/netfilter_ipv4/ipt_pool.h>
21162 +static inline int match_pool(
21167 + if (ip_pool_match(index, ntohl(addr)))
21173 + const struct sk_buff *skb,
21174 + const struct net_device *in,
21175 + const struct net_device *out,
21176 + const void *matchinfo,
21179 + u_int16_t datalen,
21182 + const struct ipt_pool_info *info = matchinfo;
21183 + const struct iphdr *iph = skb->nh.iph;
21185 + if (info->src != IP_POOL_NONE && !match_pool(info->src, iph->saddr,
21186 + info->flags&IPT_POOL_INV_SRC))
21189 + if (info->dst != IP_POOL_NONE && !match_pool(info->dst, iph->daddr,
21190 + info->flags&IPT_POOL_INV_DST))
21196 +static int checkentry(
21197 + const char *tablename,
21198 + const struct ipt_ip *ip,
21200 + unsigned int matchsize,
21201 + unsigned int hook_mask
21203 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_pool_info)))
21208 +static struct ipt_match pool_match
21209 += { { NULL, NULL }, "pool", &match, &checkentry, NULL, THIS_MODULE };
21211 +static int __init init(void)
21213 + return ipt_register_match(&pool_match);
21216 +static void __exit fini(void)
21218 + ipt_unregister_match(&pool_match);
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
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.
21232 + Copyright (C) 2000,2001 astaro AG
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
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
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>
21254 +#define DEBUGP printk
21256 +#define DEBUGP(format, args...)
21259 +MODULE_LICENSE("GPL");
21260 +MODULE_AUTHOR("Dennis Koslowski <koslowski@astaro.com>");
21262 +#define HF_DADDR_CHANGING 0x01
21263 +#define HF_SPORT_CHANGING 0x02
21264 +#define HF_TOS_CHANGING 0x04
21265 +#define HF_TTL_CHANGING 0x08
21268 + * Information we keep per each target 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 */
21278 + * Information we keep per each source address.
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 */
21295 + * State information.
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 */
21305 + * Convert an IP address into a hash table index.
21307 +static inline int hashfunc(struct in_addr addr)
21309 + unsigned int value;
21312 + value = addr.s_addr;
21316 + } while ((value >>= HASH_LOG));
21318 + return hash & (HASH_SIZE - 1);
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,
21328 + u_int16_t datalen,
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;
21337 + struct host *curr, *last, **head;
21338 + int hash, index, count;
21340 + /* Parameters from userspace */
21341 + const struct ipt_psd_info *psdinfo = matchinfo;
21344 + ip_hdr = pskb->nh.iph;
21346 + /* Sanity check */
21347 + if (ntohs(ip_hdr->frag_off) & IP_OFFSET) {
21348 + DEBUGP("PSD: sanity check failed\n");
21352 + /* TCP or UDP ? */
21353 + proto = ip_hdr->protocol;
21355 + if (proto != IPPROTO_TCP && proto != IPPROTO_UDP) {
21356 + DEBUGP("PSD: protocol not supported\n");
21360 + /* Get the source address, source & destination ports, and TCP flags */
21362 + addr.s_addr = ip_hdr->saddr;
21364 + tcp_hdr = (struct tcphdr*)((u_int32_t *)ip_hdr + ip_hdr->ihl);
21366 + /* Yep, it´s dirty */
21367 + src_port = tcp_hdr->source;
21368 + dest_port = tcp_hdr->dest;
21370 + if (proto == IPPROTO_TCP) {
21371 + tcp_flags = *((u_int8_t*)tcp_hdr + 13);
21374 + tcp_flags = 0x00;
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");
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. */
21388 + spin_lock(&state.lock);
21390 + /* Do we know this source address already? */
21393 + if ((curr = *(head = &state.hash[hash = hashfunc(addr)])))
21395 + if (curr->src_addr.s_addr == addr.s_addr) break;
21397 + if (curr->next) last = curr;
21398 + } while ((curr = curr->next));
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)) {
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;
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;
21420 + /* Packet to a new port, and not TCP/ACK: update the timestamp */
21421 + curr->timestamp = now;
21423 + /* Logged this scan already? Then drop the packet. */
21424 + if (curr->weight >= psdinfo->weight_threshold)
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;
21437 + /* Update the total weight */
21438 + curr->weight += (ntohs(dest_port) < 1024) ?
21439 + psdinfo->lo_ports_weight : psdinfo->hi_ports_weight;
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)
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;
21455 + goto out_no_match;
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;
21463 + last->next = last->next->next;
21465 + *head = (*head)->next;
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;
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;
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). */
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)];
21488 + if ((curr = *head))
21490 + if (curr == &state.list[state.index]) break;
21492 + } while ((curr = curr->next));
21494 + /* Then, remove it */
21497 + last->next = last->next->next;
21499 + *head = (*head)->next;
21502 + /* Get our list entry */
21503 + curr = &state.list[state.index++];
21504 + if (state.index >= LIST_SIZE) state.index = 0;
21506 + /* Link it into the hash table */
21507 + head = &state.hash[hash];
21508 + curr->next = *head;
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;
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;
21527 + spin_unlock(&state.lock);
21531 + spin_unlock(&state.lock);
21535 +static int ipt_psd_checkentry(const char *tablename,
21536 + const struct ipt_ip *e,
21538 + unsigned int matchsize,
21539 + unsigned int hook_mask)
21541 +/* const struct ipt_psd_info *psdinfo = targinfo;*/
21543 + /* we accept TCP only */
21544 +/* if (e->ip.proto != IPPROTO_TCP) { */
21545 +/* DEBUGP("PSD: specified protocol may be TCP only\n"); */
21549 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_psd_info))) {
21550 + DEBUGP("PSD: matchsize %u != %u\n",
21552 + IPT_ALIGN(sizeof(struct ipt_psd_info)));
21559 +static struct ipt_match ipt_psd_reg = {
21563 + ipt_psd_checkentry,
21567 +static int __init init(void)
21569 + if (ipt_register_match(&ipt_psd_reg))
21572 + memset(&state, 0, sizeof(state));
21574 + spin_lock_init(&(state.lock));
21576 + printk("netfilter PSD loaded - (c) astaro AG\n");
21580 +static void __exit fini(void)
21582 + ipt_unregister_match(&ipt_psd_reg);
21583 + printk("netfilter PSD unloaded - (c) astaro AG\n");
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
21593 + * netfilter module to enforce network quotas
21595 + * Sam Johnston <samj@samj.net>
21597 +#include <linux/module.h>
21598 +#include <linux/skbuff.h>
21599 +#include <linux/spinlock.h>
21600 +#include <linux/interrupt.h>
21602 +#include <linux/netfilter_ipv4/ip_tables.h>
21603 +#include <linux/netfilter_ipv4/ipt_quota.h>
21605 +MODULE_LICENSE("GPL");
21607 +static spinlock_t quota_lock = SPIN_LOCK_UNLOCKED;
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)
21617 + struct ipt_quota_info *q = (struct ipt_quota_info *) matchinfo;
21619 + spin_lock_bh("a_lock);
21621 + if (q->quota >= datalen) {
21622 + /* we can afford this one */
21623 + q->quota -= datalen;
21624 + spin_unlock_bh("a_lock);
21626 +#ifdef DEBUG_IPT_QUOTA
21627 + printk("IPT Quota OK: %llu datlen %d \n", q->quota, datalen);
21632 + /* so we do not allow even small packets from now on */
21635 +#ifdef DEBUG_IPT_QUOTA
21636 + printk("IPT Quota Failed: %llu datlen %d \n", q->quota, datalen);
21639 + spin_unlock_bh("a_lock);
21644 +checkentry(const char *tablename,
21645 + const struct ipt_ip *ip,
21646 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
21648 + /* TODO: spinlocks? sanity checks? */
21649 + if (matchsize != IPT_ALIGN(sizeof (struct ipt_quota_info)))
21655 +static struct ipt_match quota_match
21656 + = { {NULL, NULL}, "quota", &match, &checkentry, NULL, THIS_MODULE };
21661 + return ipt_register_match("a_match);
21664 +static void __exit
21667 + ipt_unregister_match("a_match);
21670 +module_init(init);
21671 +module_exit(fini);
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
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
21683 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
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>
21695 +MODULE_LICENSE("GPL");
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,
21704 + u_int16_t datalen,
21707 + /* Parameters from userspace */
21708 + const struct ipt_rand_info *info = matchinfo;
21709 + u_int8_t random_number;
21711 + /* get 1 random number from the kernel random number generation routine */
21712 + get_random_bytes((void *)(&random_number), 1);
21714 + /* Do we match ? */
21715 + if (random_number <= info->average)
21722 +ipt_rand_checkentry(const char *tablename,
21723 + const struct ipt_ip *e,
21725 + unsigned int matchsize,
21726 + unsigned int hook_mask)
21728 + /* Parameters from userspace */
21729 + const struct ipt_rand_info *info = matchinfo;
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)));
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);
21748 +static struct ipt_match ipt_rand_reg = {
21752 + ipt_rand_checkentry,
21756 +static int __init init(void)
21758 + if (ipt_register_match(&ipt_rand_reg))
21761 + printk("ipt_random match loaded\n");
21765 +static void __exit fini(void)
21767 + ipt_unregister_match(&ipt_rand_reg);
21768 + printk("ipt_random match unloaded\n");
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
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>
21783 +#include <linux/netfilter_ipv4/ipt_realm.h>
21784 +#include <linux/netfilter_ipv4/ip_tables.h>
21786 +MODULE_AUTHOR("Sampsa Ranta <sampsa@netsonic.fi>");
21787 +MODULE_LICENSE("GPL");
21790 +match(const struct sk_buff *skb,
21791 + const struct net_device *in,
21792 + const struct net_device *out,
21793 + const void *matchinfo,
21796 + u_int16_t datalen,
21799 + const struct ipt_realm_info *info = matchinfo;
21800 + struct dst_entry *dst = skb->dst;
21805 + id = dst->tclassid;
21807 + return (info->id == (id & info->mask)) ^ info->invert;
21810 +static int check(const char *tablename,
21811 + const struct ipt_ip *ip,
21813 + unsigned int matchsize,
21814 + unsigned int 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");
21824 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_realm_info)))
21830 +static struct ipt_match realm_match
21831 += { { NULL, NULL }, "realm", &match, &check, NULL, THIS_MODULE };
21833 +static int __init init(void)
21835 + return ipt_register_match(&realm_match);
21838 +static void __exit fini(void)
21840 + ipt_unregister_match(&realm_match);
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
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. */
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>
21867 +#include <linux/netfilter_ipv4/ip_tables.h>
21868 +#include <linux/netfilter_ipv4/ipt_recent.h>
21871 +#define HASH_LOG 9
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;
21879 +static int debug = 1;
21882 +static char version[] =
21883 +KERN_INFO RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n";
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");
21893 +MODULE_PARM(debug,"i");
21894 +MODULE_PARM_DESC(debug,"debugging level, defaults to 1");
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");
21901 +/* Structure of our list of recently seen addresses. */
21902 +struct recent_ip_list {
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;
21912 +struct time_info_list {
21913 + u_int32_t position;
21917 +/* Structure of our linked list of tables of recent lists. */
21918 +struct recent_ip_tables {
21919 + char name[IPT_RECENT_NAME_LEN];
21922 + struct recent_ip_list *table;
21923 + struct recent_ip_tables *next;
21924 + spinlock_t list_lock;
21926 + struct time_info_list *time_info;
21927 +#ifdef CONFIG_PROC_FS
21928 + struct proc_dir_entry *status_proc;
21929 +#endif /* CONFIG_PROC_FS */
21932 +/* Our current list of addresses we have recently seen.
21933 + * Only added to on a --set, and only updated on --set || --update
21935 +static struct recent_ip_tables *r_tables = NULL;
21937 +/* We protect r_list with this spinlock so two processors are not modifying
21938 + * the list at the same time.
21940 +static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
21942 +#ifdef CONFIG_PROC_FS
21943 +/* Our /proc/net/ipt_recent entry */
21944 +static struct proc_dir_entry *proc_net_ipt_recent = NULL;
21947 +/* Function declaration for later. */
21949 +match(const struct sk_buff *skb,
21950 + const struct net_device *in,
21951 + const struct net_device *out,
21952 + const void *matchinfo,
21955 + u_int16_t datalen,
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)
21962 + unsigned int value = addr;
21963 + do { result ^= value; } while((value >>= HASH_LOG));
21966 + if(debug) printk(KERN_INFO RECENT_NAME ": %d = hash_func(%u,%d)\n",
21967 + result & (table_size - 1),
21972 + return(result & (table_size - 1));
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.
21981 +static int ip_recent_get_info(char *buffer, char **start, off_t offset, int length, int *eof, void *data)
21983 + int len = 0, count, last_len = 0, pkt_count;
21986 + struct recent_ip_tables *curr_table;
21988 + curr_table = (struct recent_ip_tables*) data;
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;
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]);
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; }
22009 + *start = buffer + (offset - begin);
22010 + len -= (offset - begin);
22011 + if(len > length) len = length;
22013 + spin_unlock_bh(&curr_table->list_lock);
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
22028 +static int ip_recent_ctrl(struct file *file, const char *input, unsigned long size, void *data)
22030 + static const u_int32_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
22032 + int base, used = 0;
22035 + uint8_t bytes[4];
22038 + uint8_t *pp = res.bytes;
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;
22048 + curr_table = (struct recent_ip_tables*) data;
22050 + if(size > 20) len = 20; else len = size;
22052 + if(copy_from_user(buffer,input,len)) return -EFAULT;
22054 + if(len < 20) buffer[len] = '\0';
22057 + if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl len: %d, input: `%.20s'\n",len,buffer);
22061 + while(isspace(*cp)) { cp++; used++; if(used >= len-5) return used; }
22063 + /* Check if we are asked to flush the entire table */
22064 + if(!memcmp(cp,"clear",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;
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;
22081 + spin_unlock_bh(&curr_table->list_lock);
22085 + check_set = IPT_RECENT_SET;
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;
22093 + if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl cp: `%c', check_set: %d\n",*cp,check_set);
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.
22104 + if(!isdigit(c)) return used;
22105 + val = 0; base = 10; digit = 0;
22108 + if(c == 'x' || c == 'X') base = 16, c = *++cp;
22109 + else { base = 8; digit = 1; }
22112 + if(isascii(c) && isdigit(c)) {
22113 + if(base == 8 && (c == '8' || c == '0')) return used;
22114 + val = (val * base) + (c - '0');
22117 + } else if(base == 16 && isascii(c) && isxdigit(c)) {
22118 + val = (val << 4) | (c + 10 - (islower(c) ? 'a' : 'A'));
22124 + if(pp > res.bytes + 2 || val > 0xff) return used;
22129 + used = cp - buffer;
22130 + if(c != '\0' && (!isascii(c) || !isspace(c))) return used;
22131 + if(c == '\n') used++;
22132 + if(!digit) return used;
22134 + if(val > max[pp - res.bytes]) return used;
22135 + addr = res.word | htonl(val);
22137 + if(!addr && check_set == IPT_RECENT_SET) return used;
22140 + if(debug) printk(KERN_INFO RECENT_NAME ": ip_recent_ctrl c: %c, addr: %u used: %d\n",c,addr,used);
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';
22154 + skb = kmalloc(sizeof(struct sk_buff),GFP_KERNEL);
22157 + goto out_free_info;
22159 + skb->nh.iph = kmalloc(sizeof(struct iphdr),GFP_KERNEL);
22160 + if (!skb->nh.iph) {
22162 + goto out_free_skb;
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);
22171 + kfree(skb->nh.iph);
22178 + if(debug) printk(KERN_INFO RECENT_NAME ": Leaving ip_recent_ctrl addr: %u used: %d\n",addr,used);
22183 +#endif /* CONFIG_PROC_FS */
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
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
22204 +match(const struct sk_buff *skb,
22205 + const struct net_device *in,
22206 + const struct net_device *out,
22207 + const void *matchinfo,
22210 + u_int16_t datalen,
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;
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;
22226 + if(debug) printk(KERN_INFO RECENT_NAME ": match() called\n");
22229 + /* Default is false ^ info->invert */
22230 + ans = info->invert;
22233 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): name = '%s'\n",info->name);
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. */
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) );
22246 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): table found('%s')\n",info->name);
22249 + spin_unlock_bh(&recent_lock);
22251 + /* Table with this name not found, match impossible */
22252 + if(!curr_table) { return ans; }
22254 + /* Make sure no one is changing the list while we work with it */
22255 + spin_lock_bh(&curr_table->list_lock);
22257 + r_list = curr_table->table;
22258 + if(info->side == IPT_RECENT_DEST) addr = skb->nh.iph->daddr; else addr = skb->nh.iph->saddr;
22262 + if(debug) printk(KERN_INFO RECENT_NAME ": match() address (%u) invalid, leaving.\n",addr);
22264 + spin_unlock_bh(&curr_table->list_lock);
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);
22272 + /* Get jiffies now in case they changed while we were waiting for a lock */
22274 + hash_table = curr_table->hash_table;
22275 + time_info = curr_table->time_info;
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;
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;
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);
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)) {
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,
22308 + r_list[hash_table[orig_hash_result]].addr,
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 */
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);
22323 + r_list[hash_table[orig_hash_result]].hash_entry = hash_result;
22326 + temp = hash_table[orig_hash_result];
22328 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision; hash_table[hash_result] = %d\n",hash_table[hash_result]);
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];
22342 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): Collision handled.\n");
22346 + if(hash_table[hash_result] == -1) {
22348 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): New table entry. (hr: %d,ha: %u)\n",
22349 + hash_result, addr);
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;
22367 + ans = !info->invert;
22370 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): Existing table entry. (hr: %d,ha: %u)\n",
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
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;
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++;
22388 + if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
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;
22395 + if(hits_found >= info->hit_count) ans = !info->invert; else ans = info->invert;
22401 + printk(KERN_INFO RECENT_NAME ": match(): match addr: %u\n",addr);
22403 + printk(KERN_INFO RECENT_NAME ": match(): no match addr: %u\n",addr);
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)) {
22411 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): SET or UPDATE; updating time info.\n");
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;
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;
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) {
22437 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; clearing entry (or: %d, hr: %d).\n",orig_hash_result,hash_result);
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? */
22445 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; found collision chain.\n");
22447 + end_collision_chain = orig_hash_result;
22450 + if(end_collision_chain != -1) {
22452 + if(debug) printk(KERN_INFO RECENT_NAME ": match(): REMOVE; part of collision chain, moving to end.\n");
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];
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;
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;
22489 + spin_unlock_bh(&curr_table->list_lock);
22493 + spin_unlock_bh(&curr_table->list_lock);
22495 + if(debug) printk(KERN_INFO RECENT_NAME ": match() left.\n");
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.
22506 +checkentry(const char *tablename,
22507 + const struct ipt_ip *ip,
22509 + unsigned int matchsize,
22510 + unsigned int hook_mask)
22514 + const struct ipt_recent_info *info = matchinfo;
22515 + struct recent_ip_tables *curr_table, *find_table, *last_table;
22518 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() entered.\n");
22521 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return 0;
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++;
22529 + /* One and only one of these should ever be set */
22530 + if(flag != 1) return 0;
22532 + /* Name must be set to something */
22533 + if(!info->name || !info->name[0]) return 0;
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);
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) );
22544 + /* If a table already exists just increment the count on that table and return */
22547 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), incrementing count.\n",info->name);
22549 + find_table->count++;
22550 + spin_unlock_bh(&recent_lock);
22554 + spin_unlock_bh(&recent_lock);
22556 + /* Table with this name not found */
22557 + /* Allocate memory for new linked list item */
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));
22566 + curr_table = vmalloc(sizeof(struct recent_ip_tables));
22567 + if(curr_table == NULL) return -ENOMEM;
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';
22576 + /* Allocate memory for this table and the list of packets in each entry. */
22578 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for table (%s).\n",
22579 + sizeof(struct recent_ip_list)*ip_list_tot,
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);
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);
22591 + hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
22593 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
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);
22601 + for(c = 0; c < ip_list_tot; c++) {
22602 + curr_table->table[c].last_pkts = hold + c*ip_pkt_list_tot;
22605 + /* Allocate memory for the hash table */
22607 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for hash_table.\n",
22608 + sizeof(int)*ip_list_hash_size);
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");
22615 + vfree(curr_table->table);
22616 + vfree(curr_table);
22620 + for(c = 0; c < ip_list_hash_size; c++) {
22621 + curr_table->hash_table[c] = -1;
22624 + /* Allocate memory for the time info */
22626 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for time_info.\n",
22627 + sizeof(struct time_info_list)*ip_list_tot);
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);
22635 + vfree(curr_table->table);
22636 + vfree(curr_table);
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;
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) );
22649 + /* If a table already exists just increment the count on that table and return */
22651 + find_table->count++;
22652 + spin_unlock_bh(&recent_lock);
22654 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: table found (%s), created by other process.\n",info->name);
22656 + vfree(curr_table->time_info);
22657 + vfree(curr_table->hash_table);
22659 + vfree(curr_table->table);
22660 + vfree(curr_table);
22663 + if(!last_table) r_tables = curr_table; else last_table->next = curr_table;
22665 + spin_unlock_bh(&recent_lock);
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) {
22678 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, no tables.\n");
22680 + spin_unlock_bh(&recent_lock);
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) {
22686 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() create_proc failed, table already destroyed.\n");
22688 + spin_unlock_bh(&recent_lock);
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);
22696 + vfree(curr_table->table);
22697 + vfree(curr_table);
22701 + curr_table->status_proc->owner = THIS_MODULE;
22702 + curr_table->status_proc->data = curr_table;
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 */
22709 + if(debug) printk(KERN_INFO RECENT_NAME ": checkentry() left.\n");
22715 +/* This function is called in the event that a rule matching this module is
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
22722 +destroy(void *matchinfo, unsigned int matchsize)
22724 + const struct ipt_recent_info *info = matchinfo;
22725 + struct recent_ip_tables *curr_table, *last_table;
22728 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() entered.\n");
22731 + if(matchsize != IPT_ALIGN(sizeof(struct ipt_recent_info))) return;
22733 + /* Lock the linked list while we play with it */
22734 + spin_lock_bh(&recent_lock);
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) {
22742 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() No tables found, leaving.\n");
22744 + spin_unlock_bh(&recent_lock);
22747 + while( strncmp(info->name,curr_table->name,IPT_RECENT_NAME_LEN) && (last_table = curr_table) && (curr_table = curr_table->next) );
22749 + /* If a table does not exist then do nothing and return */
22750 + if(!curr_table) {
22752 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table not found, leaving.\n");
22754 + spin_unlock_bh(&recent_lock);
22758 + curr_table->count--;
22760 + /* If count is still non-zero then there are still rules referenceing it so we do nothing */
22761 + if(curr_table->count) {
22763 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, non-zero count, leaving.\n");
22765 + spin_unlock_bh(&recent_lock);
22770 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() table found, zero count, removing.\n");
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;
22776 + spin_unlock_bh(&recent_lock);
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);
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);
22793 + if(debug) printk(KERN_INFO RECENT_NAME ": destroy() left.\n");
22799 +/* This is the structure we pass to ipt_register to register our
22800 + * module with iptables.
22802 +static struct ipt_match recent_match = {
22803 + .name = "recent",
22805 + .checkentry = &checkentry,
22806 + .destroy = &destroy,
22807 + .me = THIS_MODULE
22810 +/* Kernel module initialization. */
22811 +static int __init init(void)
22816 +#ifdef CONFIG_PROC_FS
22817 + proc_net_ipt_recent = proc_mkdir("ipt_recent",proc_net);
22818 + if(!proc_net_ipt_recent) return -ENOMEM;
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;
22826 + if(!ip_list_hash_size) {
22827 + ip_list_hash_size = ip_list_tot*3;
22829 + while(ip_list_hash_size > count) count = count*2;
22830 + ip_list_hash_size = count;
22834 + if(debug) printk(KERN_INFO RECENT_NAME ": ip_list_hash_size: %d\n",ip_list_hash_size);
22837 + return ipt_register_match(&recent_match);
22840 +/* Kernel module destruction. */
22841 +static void __exit fini(void)
22843 + ipt_unregister_match(&recent_match);
22845 + remove_proc_entry("ipt_recent",proc_net);
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
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
22860 + * (C) 2001 by Rusty Russell <rusty@rustcorp.com.au>
22861 + * - upgraded conntrack modules to oldnat api - kernel 2.4.0+
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
22867 + * ipt_rpc.c,v 2.2 2003/01/12 18:30:00
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.
22874 + * Module load syntax:
22875 + * insmod ipt_rpc.o ports=port1,port2,...port<MAX_PORTS>
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.
22882 + * RPCs should not be exposed to the internet - ask the Pentagon;
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.
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."
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
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>
22910 +#define MAX_PORTS 8
22911 +static int ports[MAX_PORTS];
22912 +static int ports_n_c = 0;
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");
22919 +MODULE_AUTHOR("Marcelo Barbosa Lima <marcelo.lima@dcc.unicamp.br>");
22920 +MODULE_DESCRIPTION("RPC connection matching module");
22921 +MODULE_LICENSE("GPL");
22924 +#define DEBUGP(format, args...) printk(KERN_DEBUG "ipt_rpc: " \
22927 +#define DEBUGP(format, args...)
22930 +EXPORT_NO_SYMBOLS;
22932 +/* vars from ip_conntrack_rpc_tcp */
22933 +extern struct list_head request_p_list_tcp;
22934 +extern struct module *ip_conntrack_rpc_tcp;
22936 +/* vars from ip_conntrack_rpc_udp */
22937 +extern struct list_head request_p_list_udp;
22938 +extern struct module *ip_conntrack_rpc_udp;
22940 +DECLARE_RWLOCK_EXTERN(ipct_rpc_tcp_lock);
22941 +DECLARE_RWLOCK_EXTERN(ipct_rpc_udp_lock);
22943 +#define ASSERT_READ_LOCK(x) \
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); \
22951 +#define ASSERT_WRITE_LOCK(x) \
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); \
22959 +#include <linux/netfilter_ipv4/listhelp.h>
22961 +const int IPT_RPC_CHAR_LEN = 11;
22964 +static int k_atoi(char *string)
22966 + unsigned int result = 0;
22967 + int maxoctet = IPT_RPC_CHAR_LEN;
22969 + for ( ; *string != 0 && maxoctet != 0; maxoctet--, string++) {
22972 + if (*string == 0)
22974 + if (*string < 48 || *string > 57) {
22977 + result = result * 10 + ( *string - 48 );
22983 +static int match_rpcs(char *c_procs, int i_procs, int proc)
22987 + unsigned int proc_num;
22989 + DEBUGP("entered match_rpcs [%i] [%i] ..\n", i_procs, proc);
22991 + if (i_procs == -1)
22994 + for (proc_ctr=0; proc_ctr <= i_procs; proc_ctr++) {
22996 + proc_ptr = c_procs;
22997 + proc_ptr += proc_ctr * IPT_RPC_CHAR_LEN;
22998 + proc_num = k_atoi(proc_ptr);
23000 + if (proc_num == proc)
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)
23012 + const struct ipt_rpc_info *rpcinfo = matchinfo;
23013 + struct request_p *req_p;
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.
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)
23035 + DEBUGP("RPC packet contains a \"get\" requestor. [cont]\n");
23039 + /* Jump Credentials and Verfifier */
23040 + data = data + IXDR_GET_INT32(data) + 2;
23041 + data = data + IXDR_GET_INT32(data) + 2;
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));
23049 + /* If the RPC conntrack half entry already exists .. */
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);
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);
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));
23068 + /* .. remove it */
23069 + if (del_timer(&req_p->timeout))
23070 + req_p->timeout.expires = 0;
23072 + LIST_DELETE(&request_p_list, req_p);
23073 + DEBUGP("RPC req_p removed. [done]\n");
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));
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);
23089 + if(rpcinfo->strict == 1)
23094 + DEBUGP("RPC packet contains authorised procedure request [%u]. [match]\n",
23095 + (unsigned int)IXDR_GET_INT32(data));
23096 + return (1 && (!offset));
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)
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;
23114 + DEBUGP("new packet to evaluate ..\n");
23116 + ct = ip_conntrack_get((struct sk_buff *)skb, &ctinfo);
23118 + DEBUGP("no ct available [skip]\n");
23122 + DEBUGP("ct detected. [cont]\n");
23123 + dir = CTINFO2DIR(ctinfo);
23125 + /* we only want the client to server packets for matching */
23126 + if (dir != IP_CT_DIR_ORIGINAL)
23129 + /* This does sanity checking on UDP or TCP packets,
23130 + * like their respective modules.
23133 + switch (ct->tuplehash[0].tuple.dst.protonum) {
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");
23142 + for (port=0,portsok=0; port <= ports_n_c; port++) {
23143 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
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));
23154 + if ((datalen - sizeof(struct udphdr)) != 56) {
23155 + DEBUGP("packet length is not correct for RPC content. [skip]\n");
23156 + if (rpcinfo->strict == 1)
23160 + DEBUGP("packet length is correct. [cont]\n");
23162 + /* Get to the data */
23163 + data = (const u_int32_t *)hdr + 2;
23165 + /* Check the RPC data */
23166 + tval = check_rpc_packet(data, matchinfo, hotdrop,
23168 + request_p_list_udp);
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");
23180 + for (port=0,portsok=0; port <= ports_n_c; port++) {
23181 + if (ntohs(ct->tuplehash[dir].tuple.dst.u.all) == ports[port]) {
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));
23193 + if (datalen == (tcp->doff * 4)) {
23194 + DEBUGP("packet does not contain any data. [match]\n");
23195 + return (1 && (!offset));
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)
23205 + DEBUGP("packet length is correct. [cont]\n");
23207 + /* Get to the data */
23208 + data = (const u_int32_t *)tcp + tcp->doff + 1;
23210 + /* Check the RPC data */
23211 + tval = check_rpc_packet(data, matchinfo, hotdrop,
23213 + request_p_list_tcp);
23219 + DEBUGP("transport protocol=%u, is not supported [skip]\n",
23220 + ct->tuplehash[0].tuple.dst.protonum);
23225 +static int checkentry(const char *tablename, const struct ipt_ip *ip, void *matchinfo,
23226 + unsigned int matchsize, unsigned int 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");
23235 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_rpc_info)))
23242 +static struct ipt_match rpc_match = { { NULL, NULL }, "rpc",
23243 + &match, &checkentry, NULL,
23247 +static int __init init(void)
23251 + DEBUGP("incrementing usage counts\n");
23252 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_udp);
23253 + __MOD_INC_USE_COUNT(ip_conntrack_rpc_tcp);
23255 + /* If no port given, default to standard RPC port */
23256 + if (ports[0] == 0)
23257 + ports[0] = RPC_PORT;
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]);
23265 + return ipt_register_match(&rpc_match);
23269 +static void fini(void)
23271 + DEBUGP("unregistering match\n");
23272 + ipt_unregister_match(&rpc_match);
23274 + DEBUGP("decrementing usage counts\n");
23275 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_tcp);
23276 + __MOD_DEC_USE_COUNT(ip_conntrack_rpc_udp);
23280 +module_init(init);
23281 +module_exit(fini);
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
23287 enum ip_conntrack_info ctinfo;
23288 unsigned int statebit;
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;
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
23301 +/* Kernel module to match a string into a packet.
23303 + * Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
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
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>
23326 +#include <linux/netfilter_ipv4/ip_tables.h>
23327 +#include <linux/netfilter_ipv4/ipt_string.h>
23329 +MODULE_LICENSE("GPL");
23331 +struct string_per_cpu {
23337 +struct string_per_cpu *bm_string_data=NULL;
23339 +/* Boyer Moore Sublinear string search - VERY FAST */
23340 +char *search_sublinear (char *needle, char *haystack, int needle_len, int haystack_len)
23342 + int M1, right_end, sk, sh;
23345 + int *skip, *shift, *len;
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;
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;
23357 + for (i = 1; i < needle_len; i++) {
23358 + for (j = 0; j < needle_len && needle[M1 - j] == needle[M1 - i - j]; j++);
23363 + for (i = 1; i < needle_len; i++) shift[i] = needle_len;
23364 + for (i = M1; i > 0; i--) shift[len[i]] = i;
23367 + for (i = 0; i < needle_len; i++) {
23368 + if (len[i] == M1 - i) ended = i;
23369 + if (ended) shift[i] = ended;
23372 + /* Do the search*/
23373 + while (right_end < haystack_len)
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);
23380 + sk = skip[haystack[right_end - i]];
23382 + right_end = max(right_end - i + sk, right_end + sh);
23388 +/* Linear string search based on memcmp() */
23389 +char *search_linear (char *needle, char *haystack, int needle_len, int haystack_len)
23391 + char *k = haystack + (haystack_len-needle_len);
23392 + char *t = haystack;
23394 + while ( t <= k ) {
23395 + if (memcmp(t, needle, needle_len) == 0)
23405 +match(const struct sk_buff *skb,
23406 + const struct net_device *in,
23407 + const struct net_device *out,
23408 + const void *matchinfo,
23411 + u_int16_t datalen,
23414 + const struct ipt_string_info *info = matchinfo;
23415 + struct iphdr *ip = skb->nh.iph;
23417 + char *needle, *haystack;
23418 + proc_ipt_search search=search_linear;
23420 + if ( !ip ) return 0;
23422 + /* get lenghts, and validate them */
23424 + hlen=ntohs(ip->tot_len)-(ip->ihl*4);
23425 + if ( nlen > hlen ) return 0;
23427 + needle=(char *)&info->string;
23428 + haystack=(char *)ip+(ip->ihl*4);
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;
23437 + if (net_ratelimit())
23438 + printk(KERN_INFO "ipt_string: Packet too big "
23439 + "to attempt sublinear string search "
23440 + "(%d bytes)\n", hlen );
23444 + return ((search(needle, haystack, nlen, hlen)!=NULL) ^ info->invert);
23448 +checkentry(const char *tablename,
23449 + const struct ipt_ip *ip,
23451 + unsigned int matchsize,
23452 + unsigned int hook_mask)
23455 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_string_info)))
23461 +void string_freeup_data(void)
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);
23471 + kfree(bm_string_data);
23475 +static struct ipt_match string_match
23476 += { { NULL, NULL }, "string", &match, &checkentry, NULL, THIS_MODULE };
23478 +static int __init init(void)
23484 + tlen=sizeof(struct string_per_cpu)*smp_num_cpus;
23485 + alen=sizeof(int)*BM_MAX_HLEN;
23487 + /* allocate array of structures */
23488 + if ( !(bm_string_data=kmalloc(tlen,GFP_KERNEL)) ) {
23492 + memset(bm_string_data, 0, tlen);
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)) )
23498 + if ( !(bm_string_data[c].skip=kmalloc(alen, GFP_KERNEL)) )
23500 + if ( !(bm_string_data[c].len=kmalloc(alen, GFP_KERNEL)) )
23504 + return ipt_register_match(&string_match);
23507 + string_freeup_data();
23511 +static void __exit fini(void)
23513 + ipt_unregister_match(&string_match);
23514 + string_freeup_data();
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
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.
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>
23543 +MODULE_AUTHOR("Fabrice MARIE <fabrice@netfilter.org>");
23544 +MODULE_DESCRIPTION("Match arrival timestamp");
23545 +MODULE_LICENSE("GPL");
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]*/
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 */
23564 +localtime(const time_t *timepr, struct tm *r);
23567 +match(const struct sk_buff *skb,
23568 + const struct net_device *in,
23569 + const struct net_device *out,
23570 + const void *matchinfo,
23573 + u_int16_t datalen,
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;
23583 + /* if kerneltime=1, we don't read the skb->timestamp but kernel time instead */
23584 + if (info->kerneltime)
23586 + do_gettimeofday(&kerneltimeval);
23587 + packet_local_time = kerneltimeval.tv_sec;
23590 + packet_local_time = skb->stamp.tv_sec;
23592 + /* Transform the timestamp of the packet, in a human readable form */
23593 + localtime(&packet_local_time, ¤ttime);
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 */
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))
23604 + /* here we match ! */
23609 +checkentry(const char *tablename,
23610 + const struct ipt_ip *ip,
23612 + unsigned int matchsize,
23613 + unsigned int hook_mask)
23615 + struct ipt_time_info *info = matchinfo; /* match info for rule */
23617 + /* First, check that we are in the correct hook */
23618 + /* PRE_ROUTING, LOCAL_IN or FROWARD */
23620 + & ~((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) | (1 << NF_IP_LOCAL_OUT)))
23622 + printk("ipt_time: error, only valid for PRE_ROUTING, LOCAL_IN, FORWARD and OUTPUT)\n");
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;
23631 + /* Check the size */
23632 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_time_info)))
23634 + /* Now check the coherence of the data ... */
23635 + if ((info->time_start > 1439) || /* 23*60+59 = 1439*/
23636 + (info->time_stop > 1439))
23638 + printk(KERN_WARNING "ipt_time: invalid argument\n");
23645 +static struct ipt_match time_match
23646 += { { NULL, NULL }, "time", &match, &checkentry, NULL, THIS_MODULE };
23648 +static int __init init(void)
23650 + printk("ipt_time loading\n");
23651 + return ipt_register_match(&time_match);
23654 +static void __exit fini(void)
23656 + ipt_unregister_match(&time_match);
23657 + printk("ipt_time unloaded\n");
23660 +module_init(init);
23661 +module_exit(fini);
23664 +/* The part below is borowed and modified from dietlibc */
23666 +/* seconds per day */
23667 +#define SPD 24*60*60
23670 +localtime(const time_t *timepr, struct tm *r) {
23673 + extern struct timezone sys_tz;
23674 + const unsigned int __spm[12] =
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),
23688 + register time_t work;
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;
23703 + r->tm_year=i-1900;
23704 + for (i=11; i && __spm[i]>work; --i) ;
23706 + r->tm_mday=work-__spm[i]+1;
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
23712 +/* Kernel module to match u32 packet content. */
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.
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 := & | << | >> | @
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.
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
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
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.
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.
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"
23763 + AND that with FFFF (giving bytes 2-3),
23764 + and test whether that's in the range [0x100:0xFFFF]
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.
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
23814 +#include <linux/module.h>
23815 +#include <linux/skbuff.h>
23817 +#include <linux/netfilter_ipv4/ipt_u32.h>
23818 +#include <linux/netfilter_ipv4/ip_tables.h>
23820 +/* #include <asm-i386/timex.h> for timing */
23822 +MODULE_AUTHOR("Don Cohen <don@isis.cs3-inc.com>");
23823 +MODULE_DESCRIPTION("IP tables u32 matching module");
23824 +MODULE_LICENSE("GPL");
23827 +match(const struct sk_buff *skb,
23828 + const struct net_device *in,
23829 + const struct net_device *out,
23830 + const void *matchinfo,
23833 + u_int16_t datalen,
23836 + const struct ipt_u32 *data = matchinfo;
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(); */
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)
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;
23861 + case IPT_U32_LEFTSH:
23862 + val = val << number;
23864 + case IPT_U32_RIGHTSH:
23865 + val = val >> number;
23868 + base = base + val;
23870 + if (base+pos+3 > end || base+pos < head)
23872 + val = (base[pos]<<24) + (base[pos+1]<<16) +
23873 + (base[pos+2]<<8) + base[pos+3];
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)) {
23884 + if (i >= data->tests[testind].nvalues) {
23885 + /* cycles2 = get_cycles();
23886 + printk("failed %d in %d cycles\n", testind,
23887 + cycles2-cycles1); */
23891 + /* cycles2 = get_cycles();
23892 + printk("succeeded in %d cycles\n", cycles2-cycles1); */
23897 +checkentry(const char *tablename,
23898 + const struct ipt_ip *ip,
23900 + unsigned int matchsize,
23901 + unsigned int hook_mask)
23903 + if (matchsize != IPT_ALIGN(sizeof(struct ipt_u32)))
23908 +static struct ipt_match u32_match
23909 += { { NULL, NULL }, "u32", &match, &checkentry, NULL, THIS_MODULE };
23911 +static int __init init(void)
23913 + return ipt_register_match(&u32_match);
23916 +static void __exit fini(void)
23918 + ipt_unregister_match(&u32_match);
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
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] =
23934 + [TH_SYN|TH_ACK] = 1,
23936 + [TH_RST|TH_ACK] = 1,
23937 + [TH_RST|TH_ACK|TH_PUSH] = 1,
23938 + [TH_FIN|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
23948 /* TCP-specific checks. */
23950 check_tcp(const struct iphdr *iph,
23951 @@ -330,19 +348,7 @@
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);
23972 @@ -521,6 +527,16 @@
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
23981 + if (ntohs(iph->frag_off)>>15) {
23982 + limpk("IP unused bit set\n");
23986 /* Per-protocol checks. */
23987 switch (iph->protocol) {
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
24006 + * 'raw' table, which is the very first hooked in at PRE_ROUTING and LOCAL_OUT .
24008 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
24010 +#include <linux/module.h>
24011 +#include <linux/netfilter_ipv4/ip_tables.h>
24013 +#define RAW_VALID_HOOKS ((1 << NF_IP_PRE_ROUTING) | (1 << NF_IP_LOCAL_OUT))
24015 +/* Standard entry. */
24016 +struct ipt_standard
24018 + struct ipt_entry entry;
24019 + struct ipt_standard_target target;
24022 +struct ipt_error_target
24024 + struct ipt_entry_target target;
24025 + char errorname[IPT_FUNCTION_MAXNAMELEN];
24030 + struct ipt_entry entry;
24031 + struct ipt_error_target target;
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) },
24048 + /* PRE_ROUTING */
24049 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 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 } },
24057 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 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 } }
24066 + { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 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 } },
24078 +static struct ipt_table packet_raw = {
24079 + .list = { NULL, NULL },
24081 + .table = &initial_table.repl,
24082 + .valid_hooks = RAW_VALID_HOOKS,
24083 + .lock = RW_LOCK_UNLOCKED,
24085 + .me = THIS_MODULE
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 *))
24096 + return ipt_do_table(pskb, hook, in, out, &packet_raw, NULL);
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,
24105 + .hooknum = NF_IP_PRE_ROUTING,
24106 + .priority = NF_IP_PRI_FIRST },
24107 + /* LOCAL_OUT hook */
24108 + { .list = { NULL, NULL },
24109 + .hook = ipt_hook,
24111 + .hooknum = NF_IP_LOCAL_OUT,
24112 + .priority = NF_IP_PRI_FIRST }
24115 +static int __init init(void)
24119 + /* Register table */
24120 + ret = ipt_register_table(&packet_raw);
24124 + /* Register hooks */
24125 + ret = nf_register_hook(&ipt_ops[0]);
24127 + goto cleanup_table;
24129 + ret = nf_register_hook(&ipt_ops[1]);
24131 + goto cleanup_hook0;
24136 + nf_unregister_hook(&ipt_ops[0]);
24138 + ipt_unregister_table(&packet_raw);
24143 +static void __exit fini(void)
24147 + for (i = 0; i < sizeof(ipt_ops)/sizeof(struct nf_hook_ops); i++)
24148 + nf_unregister_hook(&ipt_ops[i]);
24150 + ipt_unregister_table(&packet_raw);
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
24160 +/* Netfilter messages via netlink socket. Allows for user space
24161 + * protocol helpers and general trouble making from userspace.
24163 + * (C) 2001 by Jay Schulist <jschlst@samba.org>,
24164 + * (C) 2002 by Harald Welte <laforge@gnumonks.org>
24166 + * Initial netfilter messages via netlink development funded and
24167 + * generally made possible by Network Robots, Inc. (www.networkrobots.com)
24169 + * Further development of this code funded by Astaro AG (http://www.astaro.com)
24171 + * This software may be used and distributed according to the terms
24172 + * of the GNU General Public License, incorporated herein by reference.
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>
24195 +#include <linux/netfilter.h>
24196 +#include <linux/netlink.h>
24197 +#include <linux/nfnetlink.h>
24199 +MODULE_LICENSE("GPL");
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)
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);
24212 +void nfnl_lock(void)
24218 +void nfnl_unlock(void)
24224 +struct nfnetlink_subsystem *nfnetlink_subsys_alloc(int cb_count)
24227 + struct nfnetlink_subsystem *ss;
24229 + size = sizeof(struct nfnetlink_subsystem)
24230 + + (cb_count * sizeof(struct nfnl_callback));
24232 + ss = kmalloc(size, GFP_KERNEL);
24235 + memset(ss, 0, size);
24240 +int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
24242 + MOD_INC_USE_COUNT;
24244 + nf_debug(0, "registering subsystem ID %u\n", n->subsys_id);
24247 + list_add(&n->list, &subsys_list);
24248 + subsys_table[n->subsys_id] = n;
24254 +int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
24256 + nf_debug(0, "unregistering subsystem ID %u\n", n->subsys_id);
24259 + subsys_table[n->subsys_id] = NULL;
24260 + list_del(&n->list);
24263 + MOD_DEC_USE_COUNT;
24268 +struct nfnl_callback *nfnetlink_find_client(u_int16_t nlmsg_type)
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);
24274 + if (subsys_id >= NFNL_SUBSYS_COUNT
24275 + || subsys_table[subsys_id] == NULL)
24278 + ss = subsys_table[subsys_id];
24280 + if (type >= ss->cb_count) {
24281 + nf_debug(0, "msgtype %u >= %u, returning\n", type,
24286 + return &ss->cb[type];
24289 +void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen,
24290 + const void *data)
24292 + struct nfattr *nfa;
24293 + int size = NFA_LENGTH(attrlen);
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);
24301 +int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len)
24303 + memset(tb, 0, sizeof(struct nfattr *)*maxattr);
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);
24316 + * nfnetlink_check_attributes - check and parse nfnetlink attributes
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
24324 +nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
24325 + struct nlmsghdr *nlh, struct nfattr *cda[])
24329 + /* check attribute lengths. */
24330 + min_len = sizeof(struct nfgenmsg);
24331 + if (nlh->nlmsg_len < min_len)
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);
24338 + while (NFA_OK(attr, attrlen)) {
24339 + unsigned flavor = attr->nfa_type;
24341 + if (flavor > subsys->attr_count)
24343 + cda[flavor - 1] = attr;
24345 + attr = NFA_NEXT(attr, attrlen);
24353 +int nfnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo)
24357 + NETLINK_CB(skb).dst_groups = group;
24359 + atomic_inc(&skb->users);
24360 + netlink_broadcast(nfnl, skb, pid, group, GFP_KERNEL);
24362 + err = netlink_unicast(nfnl, skb, pid, MSG_DONTWAIT);
24367 +/* Process one complete nfnetlink message. */
24368 +static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
24369 + struct nlmsghdr *nlh, int *errp)
24371 + struct nfnl_callback *nc;
24372 + int type, err = 0;
24374 + nf_debug(0, "entered; subsys=%u, msgtype=%u\n",
24375 + NFNL_SUBSYS_ID(nlh->nlmsg_type),
24376 + NFNL_MSG_TYPE(nlh->nlmsg_type));
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");
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");
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");
24397 + nc = nfnetlink_find_client(type);
24399 + nf_debug(0, "unable to find client for type %d\n", type);
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);
24410 + err = nc->call(nfnl, skb, nlh, errp);
24419 +/* Process one packet of messages. */
24420 +static inline int nfnetlink_rcv_skb(struct sk_buff *skb)
24423 + struct nlmsghdr *nlh;
24425 + while (skb->len >= NLMSG_SPACE(0)) {
24428 + nlh = (struct nlmsghdr *)skb->data;
24429 + if (nlh->nlmsg_len < sizeof(struct nlmsghdr)
24430 + || skb->len < nlh->nlmsg_len)
24432 + rlen = NLMSG_ALIGN(nlh->nlmsg_len);
24433 + if (rlen > skb->len)
24435 + if (nfnetlink_rcv_msg(skb, nlh, &err)) {
24438 + netlink_ack(skb, nlh, err);
24440 + if (nlh->nlmsg_flags & NLM_F_ACK)
24441 + netlink_ack(skb, nlh, 0);
24442 + skb_pull(skb, rlen);
24448 +static void nfnetlink_rcv(struct sock *sk, int len)
24451 + struct sk_buff *skb;
24453 + if (nfnl_shlock_nowait())
24456 + while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
24457 + if (nfnetlink_rcv_skb(skb)) {
24459 + skb_queue_head(&sk->receive_queue, skb);
24468 + } while(nfnl && nfnl->receive_queue.qlen);
24471 +void __exit nfnetlink_exit(void)
24473 + printk("Netfilter removing netlink socket.\n");
24474 + sock_release(nfnl->socket);
24478 +int __init nfnetlink_init(void)
24481 + printk("Netfilter messages via NETLINK v%s.\n", nfversion);
24483 + for (i = 0; i < NFNL_SUBSYS_COUNT; i++)
24484 + subsys_table[i] = NULL;
24486 + nfnl = netlink_kernel_create(NETLINK_NETFILTER, nfnetlink_rcv);
24488 + printk(KERN_ERR "cannot initialize nfnetlink!\n");
24495 +module_init(nfnetlink_init);
24496 +module_exit(nfnetlink_exit);
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
24508 +/* Connection tracking via netlink socket. Allows for user space
24509 + * protocol helpers and general trouble making from userspace.
24511 + * (C) 2001 by Jay Schulist <jschlst@samba.org>
24512 + * (C) 2002 by Harald Welte <laforge@gnumonks.org>
24514 + * Initial connection tracking via netlink development funded and
24515 + * generally made possible by Network Robots, Inc. (www.networkrobots.com)
24517 + * Further development of this code funded by Astaro AG (http://www.asaro.com)
24519 + * This software may be used and distributed according to the terms
24520 + * of the GNU General Public License, incorporated herein by reference.
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>
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>
24550 +#include <linux/nfnetlink.h>
24551 +#include <linux/nfnetlink_conntrack.h>
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>
24557 +MODULE_LICENSE("GPL");
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)
24565 +/* FIXME: this define is just needed for DUMP_TUPLE */
24566 +#define DEBUGP(format, args...) ct_debug(0, format, ## args)
24568 +static struct nfnetlink_subsystem *ctnl_subsys;
24571 +ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
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)
24580 + struct nlmsghdr *nlh;
24581 + struct nfgenmsg *nfmsg;
24582 + struct cta_proto cp;
24584 + unsigned char *b;
24587 + nlh = NLMSG_PUT(skb, pid, seq, (NFNL_SUBSYS_CTNETLINK<<8)|event,
24588 + sizeof(struct nfgenmsg));
24589 + nfmsg = NLMSG_DATA(nlh);
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);
24598 + NFA_PUT(skb, CTA_STATUS, sizeof(unsigned long), &s);
24600 + NFA_PUT(skb, CTA_IIF, IFNAMSIZ, in->name);
24602 + NFA_PUT(skb, CTA_OIF, IFNAMSIZ, out->name);
24604 + NFA_PUT(skb, CTA_INFO, sizeof(unsigned long), ctinfo);
24606 + cp.num_proto = proto;
24607 + memcpy(&cp.proto, &ct->proto, sizeof (cp.proto));
24608 + NFA_PUT(skb, CTA_PROTOINFO, sizeof(cp), &cp);
24610 + if (ct->helper) {
24611 + struct cta_help ch;
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);
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;
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);
24632 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
24634 + nlh->nlmsg_len = skb->tail - b;
24639 + skb_trim(skb, b - skb->data);
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)
24650 + struct sk_buff *skb;
24653 + skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24657 + err = ctnetlink_fill_info(skb, 0, 0, CTNL_MSG_NEWCONNTRACK, 1, ct,
24658 + &ctinfo, proto, in, out);
24660 + goto nlmsg_failure;
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)
24673 + u16 proto = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
24674 + struct sk_buff *skb;
24676 + skb = ctnetlink_event_build_msg(ct, ctinfo, proto, in, out);
24680 + if (proto == IPPROTO_TCP) {
24681 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
24683 + } else if (proto == IPPROTO_UDP) {
24684 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
24686 + } else if (proto == IPPROTO_ICMP) {
24687 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
24690 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
24698 +static void ctnetlink_destroy(struct ip_conntrack *ct)
24700 + ctnetlink_create(ct, IP_CT_DELETE, NULL, NULL);
24704 +static inline int ctnetlink_kill(const struct ip_conntrack *i, void *data)
24706 + struct ip_conntrack *t = (struct ip_conntrack *)data;
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]);
24720 +ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
24721 + struct nlmsghdr *nlh, int *errp)
24723 + struct ip_conntrack_tuple_hash *h;
24724 + struct ip_conntrack_tuple *tuple;
24725 + struct nfattr *cda[CTA_MAX];
24727 + ct_debug(0, "entered\n");
24729 + if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24732 + if (cda[CTA_ORIG-1])
24733 + tuple = NFA_DATA(cda[CTA_ORIG-1]);
24735 + if (cda[CTA_RPLY-1])
24736 + tuple = NFA_DATA(cda[CTA_RPLY-1]);
24738 + ct_debug(0, "no tuple found in request\n");
24743 + h = ip_conntrack_find_get(tuple, NULL);
24745 + ct_debug(0, "tuple not found in conntrack hash:");
24746 + DUMP_TUPLE(tuple);
24750 + ct_debug(0, "calling selective_cleanup\n");
24751 + ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack);
24756 +static int ctnetlink_done(struct netlink_callback *cb)
24758 + ct_debug(0, "entering\n");
24763 +ctnetlink_dump_build_msg(const struct ip_conntrack_tuple_hash *hash,
24764 + struct sk_buff *skb, u32 pid, u32 seq)
24766 + struct ip_conntrack *ct;
24769 + /* Only count originals */
24770 + if (DIRECTION(hash))
24773 + ct = hash->ctrack;
24775 + goto nlmsg_failure;
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);
24781 + goto nlmsg_failure;
24791 +ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
24795 + int s_idx = cb->args[0];
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++) {
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))
24807 + READ_UNLOCK(&ip_conntrack_lock);
24809 + cb->args[0] = idx;
24814 +ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
24815 + struct nlmsghdr *nlh, int *errp)
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;
24824 + ct_debug(0, "entered\n");
24826 + if (nlh->nlmsg_flags & NLM_F_DUMP) {
24827 + struct nfgenmsg *msg = NLMSG_DATA(nlh);
24830 + if (msg->nfgen_family != AF_INET)
24831 + return -EAFNOSUPPORT;
24833 + ct_debug(0, "starting dump\n");
24834 + if ((*errp = netlink_dump_start(ctnl, skb, nlh,
24835 + ctnetlink_dump_table,
24836 + ctnetlink_done)) != 0)
24838 + rlen = NLMSG_ALIGN(nlh->nlmsg_len);
24839 + if (rlen > skb->len)
24841 + skb_pull(skb, rlen);
24845 + if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24848 + if (cda[CTA_ORIG-1])
24849 + tuple = NFA_DATA(cda[CTA_ORIG-1]);
24851 + if (cda[CTA_RPLY-1])
24852 + tuple = NFA_DATA(cda[CTA_RPLY-1]);
24857 + h = ip_conntrack_find_get(tuple, NULL);
24863 + goto nlmsg_failure;
24865 + skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24868 + NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
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);
24876 + goto nlmsg_failure;
24878 + err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
24889 +/* Finish me: should support NLM_F_CREATE and NLM_F_REPLACE. */
24891 +ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
24892 + struct nlmsghdr *nlh, int *errp)
24894 + return -EOPNOTSUPP;
24901 +ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
24904 + const struct ip_conntrack_expect *exp)
24906 + struct nlmsghdr *nlh;
24907 + struct nfgenmsg *nfmsg;
24908 + unsigned char *b;
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;
24917 + NFA_PUT(skb, CTA_EXP_TUPLE, sizeof(struct ip_conntrack_tuple),
24919 + NFA_PUT(skb, CTA_EXP_MASK, sizeof(struct ip_conntrack_tuple),
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),
24925 + /* FIXME: proto */
24927 +#ifdef CONFIG_IP_NF_NAT_NEEDED
24928 +#endif /* CONFIG_IP_NF_NAT_NEEDED */
24930 + nlh->nlmsg_len = skb->tail - b;
24935 + skb_trim(skb, b - skb->data);
24939 +static inline struct sk_buff *
24940 +ctnetlink_exp_event_build_msg(const struct ip_conntrack_expect *exp)
24942 + struct sk_buff *skb;
24945 + skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
24949 + err = ctnetlink_exp_fill_info(skb, 0, 0, CTNL_MSG_NEWEXPECT, 1, exp);
24951 + goto nlmsg_failure;
24961 +ctnetlink_exp_create(struct ip_conntrack_expect *exp)
24963 + u16 proto = exp->tuple.dst.protonum;
24964 + struct sk_buff *skb;
24966 + skb = ctnetlink_exp_event_build_msg(exp);
24970 + if (proto == IPPROTO_TCP) {
24971 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_TCP, 0);
24973 + } else if (proto == IPPROTO_UDP) {
24974 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_UDP, 0);
24976 + } else if (proto == IPPROTO_ICMP) {
24977 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_ICMP, 0);
24980 + nfnetlink_send(skb, 0, NFGRP_IPV4_CT_OTHER, 0);
24989 +ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
24990 + struct nlmsghdr *nlh, int *errp)
24992 + struct ip_conntrack_expect *exp;
24993 + struct ip_conntrack_tuple *tuple;
24994 + struct nfattr *cda[CTA_MAX];
24996 + if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
24999 + if (cda[CTA_ORIG-1])
25000 + tuple = NFA_DATA(cda[CTA_ORIG-1]);
25002 + if (cda[CTA_RPLY-1])
25003 + tuple = NFA_DATA(cda[CTA_RPLY-1]);
25008 + /* bump usage count to 2 */
25009 + exp = ip_conntrack_expect_find_get(tuple);
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);
25022 +ctnetlink_exp_dump_build_msg(const struct ip_conntrack_expect *exp,
25023 + struct sk_buff *skb, u32 pid, u32 seq)
25027 + proto = exp->tuple.dst.protonum;
25028 + err = ctnetlink_exp_fill_info(skb, pid, seq, CTNL_MSG_NEWEXPECT, 1,
25031 + goto nlmsg_failure;
25041 +ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
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);
25053 + ct_debug(0, "returning\n");
25060 +ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
25061 + struct nlmsghdr *nlh, int *errp)
25063 + struct ip_conntrack_expect *exp;
25064 + struct ip_conntrack_tuple *tuple;
25065 + struct nfattr *cda[CTA_MAX];
25066 + struct sk_buff *skb2 = NULL;
25069 + ct_debug(0, "entered\n");
25071 + if (nlh->nlmsg_flags & NLM_F_DUMP) {
25072 + struct nfgenmsg *msg = NLMSG_DATA(nlh);
25075 + if (msg->nfgen_family != AF_INET)
25076 + return -EAFNOSUPPORT;
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)
25083 + rlen = NLMSG_ALIGN(nlh->nlmsg_len);
25084 + if (rlen > skb->len)
25086 + skb_pull(skb, rlen);
25090 + if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
25093 + if (cda[CTA_ORIG-1])
25094 + tuple = NFA_DATA(cda[CTA_ORIG-1]);
25096 + if (cda[CTA_RPLY-1])
25097 + tuple = NFA_DATA(cda[CTA_RPLY-1]);
25102 + exp = ip_conntrack_expect_find_get(tuple);
25106 + skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
25109 + NETLINK_CB(skb2).dst_pid = NETLINK_CB(skb).pid;
25110 + proto = exp->tuple.dst.protonum;
25112 + err = ctnetlink_exp_fill_info(skb2, NETLINK_CB(skb).pid,
25113 + nlh->nlmsg_seq, CTNL_MSG_NEWEXPECT,
25116 + goto nlmsg_failure;
25118 + err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
25130 +ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
25131 + struct nlmsghdr *nlh, int *errp)
25133 + return -EOPNOTSUPP;
25136 +/* struct conntrack_expect stuff */
25139 +static struct ip_conntrack_notify ctnl_notify = { { NULL, NULL },
25140 + ctnetlink_destroy,
25141 + ctnetlink_create };
25143 +static struct ip_conntrack_notify ctnl_exp_notify;
25146 +static void __exit ctnetlink_exit(void)
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);
25156 +static int __init ctnetlink_init(void)
25160 + ctnl_subsys = nfnetlink_subsys_alloc(CTNL_MSG_COUNT);
25161 + if (!ctnl_subsys) {
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
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");
25188 + goto err_free_subsys;
25193 + if (ip_conntrack_notify_register(&ctnl_notify) < 0) {
25194 + printk("ctnetlink_init: cannot register notifier.\n");
25196 + goto err_unreg_subsys;
25199 + if (ip_conntrack_notify_register(&ctnl_exp_notify) < 0) {
25200 + printk("ctnetlink_init: cannot register exp notifier\n");
25202 + goto err_unreg_notify;
25211 + ip_conntrack_notify_unregister(&ctnl_notify);
25214 + nfnetlink_subsys_unregister(ctnl_subsys);
25216 + kfree(ctnl_subsys);
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 @@
25229 #ifdef CONFIG_NETFILTER
25230 -static int route6_me_harder(struct sk_buff *skb)
25231 +int ip6_route_me_harder(struct sk_buff *skb)
25233 struct ipv6hdr *iph = skb->nh.ipv6h;
25234 struct dst_entry *dst;
25235 @@ -150,7 +150,7 @@
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");
25244 @@ -166,7 +166,7 @@
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){
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 @@
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
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
25272 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25273 + dep_tristate ' Routing header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_RT $CONFIG_IP6_NF_IPTABLES
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
25278 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25279 + dep_tristate ' Fragmentation header match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_FRAG $CONFIG_IP6_NF_IPTABLES
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
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
25291 + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
25292 + dep_tristate ' AH/ESP match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_AHESP $CONFIG_IP6_NF_IPTABLES
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
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
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
25311 + if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
25312 + dep_tristate ' HL target support' CONFIG_IP6_NF_TARGET_HL $CONFIG_IP6_NF_FILTER
25314 + if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
25315 dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_FILTER
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
25325 #dep_tristate ' LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
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
25357 +obj-$(CONFIG_IP6_NF_MATCH_RANDOM) += ip6t_random.o
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
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);
25371 - goto err_out_unlock;
25372 + goto err_out_free_nskb;
25374 + /* netlink_unicast will either free the nskb or attach it to a socket */
25375 status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
25377 goto err_out_unlock;
25378 @@ -318,6 +319,9 @@
25379 write_unlock_bh(&queue_lock);
25382 +err_out_free_nskb:
25386 write_unlock_bh(&queue_lock);
25388 @@ -326,45 +330,6 @@
25393 - * Taken from net/ipv6/ip6_output.c
25395 - * We should use the one there, but is defined static
25396 - * so we put this just here and let the things as
25399 - * If that one is modified, this one should be modified too.
25402 -route6_me_harder(struct sk_buff *skb)
25404 - struct ipv6hdr *iph = skb->nh.ipv6h;
25405 - struct dst_entry *dst;
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;
25416 - dst = ip6_route_output(skb->sk, &fl);
25418 - if (dst->error) {
25419 - if (net_ratelimit())
25420 - printk(KERN_DEBUG "route6_me_harder: No more route.\n");
25424 - /* Drop old route. */
25425 - dst_release(skb->dst);
25432 ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
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);
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>
25449 #include <linux/netfilter_ipv6/ip6_tables.h>
25450 +#include <linux/netfilter_ipv6/ip6_logging.h>
25452 #define IPV6_HDR_LEN (sizeof(struct ipv6hdr))
25453 #define IPV6_OPTHDR_LEN (sizeof(struct ipv6_opt_hdr))
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",
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];
25472 - char padding[SMP_ALIGN((NF_IP6_NUMHOOKS*2+2)*sizeof(unsigned int))];
25474 /* ip6t_entry tables: one per CPU */
25476 + char entries[0] ____cacheline_aligned;
25479 static LIST_HEAD(ip6t_target);
25480 @@ -322,6 +331,39 @@
25481 return (struct ip6t_entry *)(base + offset);
25485 +get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
25486 + char **chainname, u_int16_t *rulenum)
25488 + struct ip6t_entry_target *t;
25495 + t = ip6t_get_target(s);
25496 + if (strcmp(t->u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
25497 + *chainname = t->data;
25504 +/* All zeroes == unconditional rule. */
25506 +unconditional(const struct ip6t_ip6 *ipv6)
25510 + for (i = 0; i < sizeof(*ipv6); i++)
25511 + if (((char *)ipv6)[i])
25514 + return (i == sizeof(*ipv6));
25517 /* Returns one of the generic firewall policies, like NF_ACCEPT. */
25519 ip6t_do_table(struct sk_buff **pskb,
25520 @@ -398,6 +440,27 @@
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;
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);
25541 + nf_log_ip6_packet(pskb, hook, in, out, "TRACE: %s/%s/%u ",
25542 + table->name, chainname, rulenum);
25545 /* Standard target? */
25546 if (!t->u.kernel.target->target) {
25548 @@ -554,19 +617,6 @@
25549 return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
25552 -/* All zeroes == unconditional rule. */
25554 -unconditional(const struct ip6t_ip6 *ipv6)
25558 - for (i = 0; i < sizeof(*ipv6); i++)
25559 - if (((char *)ipv6)[i])
25562 - return (i == sizeof(*ipv6));
25565 /* Figures out from what hook each rule can be called: returns 0 if
25566 there are loops. Puts hook bitmask in comefrom. */
25568 @@ -1450,7 +1500,7 @@
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 }, { } };
25576 newinfo = vmalloc(sizeof(struct ip6t_table_info)
25577 @@ -1767,14 +1817,15 @@
25578 = { { NULL, NULL }, "icmp6", &icmp6_match, &icmp6_checkentry, NULL };
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)
25586 if ((*count)++ >= start_offset) {
25587 unsigned int namelen;
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 */
25595 @@ -1792,7 +1843,7 @@
25596 if (down_interruptible(&ip6t_mutex) != 0)
25599 - LIST_FIND(&ip6t_tables, print_name, struct ip6t_table *,
25600 + LIST_FIND(&ip6t_tables, print_name, char *,
25601 offset, buffer, length, &pos, &count);
25604 @@ -1801,6 +1852,46 @@
25605 *start=(char *)((unsigned long)count-offset);
25609 +static int ip6t_get_targets(char *buffer, char **start, off_t offset, int length)
25612 + unsigned int count = 0;
25614 + if (down_interruptible(&ip6t_mutex) != 0)
25617 + LIST_FIND(&ip6t_target, print_name, char *,
25618 + offset, buffer, length, &pos, &count);
25622 + *start = (char *)((unsigned long)count - offset);
25626 +static int ip6t_get_matches(char *buffer, char **start, off_t offset, int length)
25629 + unsigned int count = 0;
25631 + if (down_interruptible(&ip6t_mutex) != 0)
25634 + LIST_FIND(&ip6t_match, print_name, char *,
25635 + offset, buffer, length, &pos, &count);
25639 + *start = (char *)((unsigned long)count - offset);
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 },
25648 #endif /*CONFIG_PROC_FS*/
25650 static int __init init(void)
25651 @@ -1826,13 +1917,19 @@
25652 #ifdef CONFIG_PROC_FS
25654 struct proc_dir_entry *proc;
25655 - proc = proc_net_create("ip6_tables_names", 0,
25656 - ip6t_get_tables);
25658 - nf_unregister_sockopt(&ip6t_sockopts);
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);
25667 + proc_net_remove(ip6t_proc_entry[i].name);
25668 + nf_unregister_sockopt(&ip6t_sockopts);
25671 + proc->owner = THIS_MODULE;
25673 - proc->owner = THIS_MODULE;
25677 @@ -1844,7 +1941,11 @@
25679 nf_unregister_sockopt(&ip6t_sockopts);
25680 #ifdef CONFIG_PROC_FS
25681 - proc_net_remove("ip6_tables_names");
25684 + for (i = 0; ip6t_proc_entry[i].name; i++)
25685 + proc_net_remove(ip6t_proc_entry[i].name);
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
25695 + * Hop Limit modification target for ip6tables
25696 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
25697 + * Based on HW's TTL module
25699 + * This software is distributed under the terms of GNU GPL
25702 +#include <linux/module.h>
25703 +#include <linux/skbuff.h>
25704 +#include <linux/ip.h>
25706 +#include <linux/netfilter_ipv6/ip6_tables.h>
25707 +#include <linux/netfilter_ipv6/ip6t_HL.h>
25709 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
25710 +MODULE_DESCRIPTION("IP tables Hop Limit modification module");
25711 +MODULE_LICENSE("GPL");
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)
25717 + struct ipv6hdr *ip6h = (*pskb)->nh.ipv6h;
25718 + const struct ip6t_HL_info *info = targinfo;
25719 + u_int16_t diffs[2];
25722 + switch (info->mode) {
25723 + case IP6T_HL_SET:
25724 + new_hl = info->hop_limit;
25726 + case IP6T_HL_INC:
25727 + new_hl = ip6h->hop_limit + info->hop_limit;
25728 + if (new_hl > 255)
25731 + case IP6T_HL_DEC:
25732 + new_hl = ip6h->hop_limit + info->hop_limit;
25737 + new_hl = ip6h->hop_limit;
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);
25747 + return IP6T_CONTINUE;
25750 +static int ip6t_hl_checkentry(const char *tablename,
25751 + const struct ip6t_entry *e,
25753 + unsigned int targinfosize,
25754 + unsigned int hook_mask)
25756 + struct ip6t_HL_info *info = targinfo;
25758 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_HL_info))) {
25759 + printk(KERN_WARNING "HL: targinfosize %u != %Zu\n",
25761 + IP6T_ALIGN(sizeof(struct ip6t_HL_info)));
25765 + if (strcmp(tablename, "mangle")) {
25766 + printk(KERN_WARNING "HL: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
25770 + if (info->mode > IP6T_HL_MAXMODE) {
25771 + printk(KERN_WARNING "HL: invalid or unknown Mode %u\n",
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");
25784 +static struct ip6t_target ip6t_HL = { { NULL, NULL }, "HL",
25785 + ip6t_hl_target, ip6t_hl_checkentry, NULL, THIS_MODULE };
25787 +static int __init init(void)
25789 + return ip6t_register_target(&ip6t_HL);
25792 +static void __exit fini(void)
25794 + ip6t_unregister_target(&ip6t_HL);
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
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>
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,
25817 + struct ip6t_imq_info *mr = (struct ip6t_imq_info*)targinfo;
25819 + (*pskb)->imq_flags = mr->todev | IMQ_F_ENQUEUE;
25820 + (*pskb)->nfcache |= NFC_ALTERED;
25822 + return IP6T_CONTINUE;
25825 +static int imq_checkentry(const char *tablename,
25826 + const struct ip6t_entry *e,
25828 + unsigned int targinfosize,
25829 + unsigned int hook_mask)
25831 + struct ip6t_imq_info *mr;
25833 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_imq_info))) {
25834 + printk(KERN_WARNING "IMQ: invalid targinfosize\n");
25837 + mr = (struct ip6t_imq_info*)targinfo;
25839 + if (strcmp(tablename, "mangle") != 0) {
25840 + printk(KERN_WARNING
25841 + "IMQ: IMQ can only be called from \"mangle\" table, not \"%s\"\n",
25846 + if (mr->todev > IMQ_MAX_DEVS) {
25847 + printk(KERN_WARNING
25848 + "IMQ: invalid device specified, highest is %u\n",
25856 +static struct ip6t_target ip6t_imq_reg = {
25865 +static int __init init(void)
25867 + if (ip6t_register_target(&ip6t_imq_reg))
25873 +static void __exit fini(void)
25875 + ip6t_unregister_target(&ip6t_imq_reg);
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
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>
25890 MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
25891 MODULE_DESCRIPTION("IP6 tables LOG target module");
25893 printk("DST=%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ", NIP6(ipv6h->daddr));
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,
25901 @@ -266,23 +267,21 @@
25905 -static unsigned int
25906 -ip6t_log_target(struct sk_buff **pskb,
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,
25914 + const struct ip6t_log_info *loginfo,
25915 + const char *level_string,
25916 + const char *prefix)
25918 struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h;
25919 - const struct ip6t_log_info *loginfo = targinfo;
25920 - char level_string[4] = "< >";
25922 - level_string[1] = '0' + (loginfo->level % 8);
25923 spin_lock_bh(&log_lock);
25924 printk(level_string);
25925 printk("%sIN=%s OUT=%s ",
25927 + prefix == NULL ? loginfo->prefix : prefix,
25928 in ? in->name : "",
25929 out ? out->name : "");
25931 @@ -329,10 +328,59 @@
25932 dump_packet(loginfo, ipv6h, 1);
25934 spin_unlock_bh(&log_lock);
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,
25945 + const struct ip6t_log_info *loginfo = targinfo;
25946 + char level_string[4] = "< >";
25948 + level_string[1] = '0' + (loginfo->level % 8);
25949 + ip6t_log_packet(pskb, hooknum, in, out, loginfo, level_string, NULL);
25951 return IP6T_CONTINUE;
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)
25961 + struct ip6t_log_info loginfo = {
25963 + .logflags = IP6T_LOG_MASK,
25967 + ip6t_log_packet(pskb, hooknum, in, out, &loginfo, KERN_WARNING, prefix);
25971 +ip6_log_fn(char *pfh, size_t len,
25972 + const char *prefix)
25974 + struct ipv6hdr *ipv6h = (struct ipv6hdr *)pfh;
25975 + struct ip6t_log_info loginfo = {
25977 + .logflags = IP6T_LOG_MASK,
25981 + spin_lock_bh(&log_lock);
25982 + printk(KERN_WARNING "%s", prefix);
25983 + dump_packet(&loginfo, ipv6h, 1);
25985 + spin_unlock_bh(&log_lock);
25988 static int ip6t_log_checkentry(const char *tablename,
25989 const struct ip6t_entry *e,
25991 @@ -364,17 +412,21 @@
25992 static struct ip6t_target ip6t_log_reg
25993 = { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL,
25995 +static struct nf_logging_t ip6_logging_fn
25996 += { ip6_log_packet_fn, ip6_log_fn };
25998 static int __init init(void)
26000 if (ip6t_register_target(&ip6t_log_reg))
26002 + nf_ip6_log_register(&ip6_logging_fn);
26007 static void __exit fini(void)
26009 + nf_ip6_log_unregister(&ip6_logging_fn);
26010 ip6t_unregister_target(&ip6t_log_reg);
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
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>)
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>
26032 +#define DEBUGP printk
26034 +#define DEBUGP(format, args...)
26038 +/* Send RST reply */
26039 +static void send_reset(struct sk_buff *oldskb)
26041 + struct sk_buff *nskb;
26042 + struct tcphdr *otcph, *tcph;
26043 + struct rtable *rt;
26044 + unsigned int otcplen;
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))
26052 + otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl);
26053 + otcplen = oldskb->len - oldskb->nh.iph->ihl*4;
26055 + /* No RST for RST. */
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)
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);
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;
26080 + tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
26082 + nskb->nh.iph->daddr = xchg(&nskb->nh.iph->saddr, nskb->nh.iph->daddr);
26083 + tcph->source = xchg(&tcph->dest, tcph->source);
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);
26092 + tcph->seq = otcph->ack_seq;
26093 + tcph->ack_seq = 0;
26096 + tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin
26097 + + otcplen - (otcph->doff<<2));
26101 + /* Reset flags */
26102 + ((u_int8_t *)tcph)[13] = 0;
26104 + tcph->ack = needs_ack;
26106 + tcph->window = 0;
26107 + tcph->urg_ptr = 0;
26109 + /* Adjust TCP checksum */
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));
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;
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);
26129 + if (ip_route_output(&rt, nskb->nh.iph->daddr, nskb->nh.iph->saddr,
26130 + RT_TOS(nskb->nh.iph->tos) | RTO_CONN,
26134 + dst_release(nskb->dst);
26135 + nskb->dst = &rt->u.dst;
26137 + /* "Never happens" */
26138 + if (nskb->len > nskb->dst->pmtu)
26141 + NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, nskb, NULL, nskb->dst->dev,
26142 + ip_finish_output);
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,
26157 + const struct ip6t_reject_info *reject = targinfo;
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);
26167 + case IP6T_ICMP6_ADM_PROHIBITED:
26168 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADM_PROHIBITED, 0, out);
26170 + case IP6T_ICMP6_NOT_NEIGHBOUR:
26171 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_NOT_NEIGHBOUR, 0, out);
26173 + case IP6T_ICMP6_ADDR_UNREACH:
26174 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0, out);
26176 + case IP6T_ICMP6_PORT_UNREACH:
26177 + icmpv6_send(*pskb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, out);
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;
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
26191 + struct icmp_bxm icmp_param;
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);
26201 + case IPT_TCP_RESET:
26202 + send_reset(*pskb);
26206 + printk(KERN_WARNING "REJECTv6: case %u not handled yet\n", reject->with);
26213 +static inline int find_ping_match(const struct ip6t_entry_match *m)
26215 + const struct ip6t_icmp *icmpinfo = (const struct ip6t_icmp *)m->data;
26217 + if (strcmp(m->u.kernel.match->name, "icmp6") == 0
26218 + && icmpinfo->type == ICMPV6_ECHO_REQUEST
26219 + && !(icmpinfo->invflags & IP6T_ICMP_INV))
26225 +static int check(const char *tablename,
26226 + const struct ip6t_entry *e,
26228 + unsigned int targinfosize,
26229 + unsigned int hook_mask)
26231 + const struct ip6t_reject_info *rejinfo = targinfo;
26233 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_reject_info))) {
26234 + DEBUGP("REJECTv6: targinfosize %u != 0\n", targinfosize);
26238 + /* Only allow these for packet filtering. */
26239 + if (strcmp(tablename, "filter") != 0) {
26240 + DEBUGP("REJECTv6: bad table `%s'.\n", tablename);
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);
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");
26257 + /* Must contain ICMP match. */
26258 + if (IP6T_MATCH_ITERATE(e, find_ping_match) == 0) {
26259 + DEBUGP("REJECTv6: ECHOREPLY illegal for non-ping\n");
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");
26274 +static struct ip6t_target ip6t_reject_reg
26275 += { { NULL, NULL }, "REJECT", reject6_target, check, NULL, THIS_MODULE };
26277 +static int __init init(void)
26279 + if (ip6t_register_target(&ip6t_reject_reg))
26284 +static void __exit fini(void)
26286 + ip6t_unregister_target(&ip6t_reject_reg);
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
26296 + * This implements the ROUTE v6 target, which enables you to setup unusual
26297 + * routes not supported by the standard kernel routing table.
26299 + * Copyright (C) 2003 Cedric de Launois <delaunois@info.ucl.ac.be>
26301 + * v 1.0 2003/08/05
26303 + * This software is distributed under GNU GPL v2, 1991
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>
26318 +#define DEBUGP printk
26320 +#define DEBUGP(format, args...)
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])
26333 +/* Route the packet according to the routing keys specified in
26334 + * route_info. Keys are :
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
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
26350 +route6(struct sk_buff *skb,
26351 + unsigned int ifindex,
26352 + const struct ip6t_route_target_info *route_info)
26354 + struct rt6_info *rt = NULL;
26355 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
26356 + struct in6_addr *gw = (struct in6_addr*)&route_info->gw;
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);
26363 + if (ipv6_addr_any(gw))
26364 + rt = rt6_lookup(&ipv6h->daddr, &ipv6h->saddr, ifindex, 1);
26366 + rt = rt6_lookup(gw, &ipv6h->saddr, ifindex, 1);
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);
26376 + if (ifindex && rt->rt6i_dev->ifindex!=ifindex)
26377 + goto wrong_route;
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);
26384 + /* Drop old route. */
26385 + dst_release(skb->dst);
26386 + skb->dst = &rt->u.dst;
26387 + skb->dev = rt->rt6i_dev;
26391 + dst_release(&rt->u.dst);
26393 + if (!net_ratelimit())
26396 + printk("ip6t_ROUTE: no explicit route found ");
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));
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
26412 +static void ip_direct_send(struct sk_buff *skb)
26414 + struct dst_entry *dst = skb->dst;
26415 + struct hh_cache *hh = dst->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);
26426 + if (net_ratelimit())
26427 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no hdr & no neighbour cache!\n");
26433 +static unsigned int
26434 +route6_oif(const struct ip6t_route_target_info *route_info,
26435 + struct sk_buff *skb)
26437 + unsigned int ifindex = 0;
26438 + struct net_device *dev_out = NULL;
26440 + /* The user set the interface name to use.
26441 + * Getting the current interface index.
26443 + if ((dev_out = dev_get_by_name(route_info->oif))) {
26444 + ifindex = dev_out->ifindex;
26446 + /* Unknown interface name : packet dropped */
26447 + if (net_ratelimit())
26448 + DEBUGP("ip6t_ROUTE: oif interface %s not found\n", route_info->oif);
26450 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
26451 + return IP6T_CONTINUE;
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;
26462 + ip_direct_send(skb);
26463 + return NF_STOLEN;
26469 +static unsigned int
26470 +route6_gw(const struct ip6t_route_target_info *route_info,
26471 + struct sk_buff *skb)
26473 + if (route6(skb, 0, route_info)) {
26474 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
26475 + return IP6T_CONTINUE;
26477 + ip_direct_send(skb);
26478 + return NF_STOLEN;
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,
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;
26496 + if (route_info->flags & IP6T_ROUTE_CONTINUE)
26499 + /* If we are at PREROUTING or INPUT hook
26500 + * the TTL isn't decreased by the IP stack
26502 + if (hooknum == NF_IP6_PRE_ROUTING ||
26503 + hooknum == NF_IP6_LOCAL_IN) {
26505 + struct ipv6hdr *ipv6h = skb->nh.ipv6h;
26507 + if (ipv6h->hop_limit <= 1) {
26508 + /* Force OUTPUT device used as source address */
26509 + skb->dev = skb->dst->dev;
26511 + icmpv6_send(skb, ICMPV6_TIME_EXCEED,
26512 + ICMPV6_EXC_HOPLIMIT, 0, skb->dev);
26517 + ipv6h->hop_limit--;
26522 + if (route_info->oif[0])
26523 + return route6_oif(route_info, *pskb);
26525 + if (!ipv6_addr_any(gw))
26526 + return route6_gw(route_info, *pskb);
26528 + if (net_ratelimit())
26529 + DEBUGP(KERN_DEBUG "ip6t_ROUTE: no parameter !\n");
26531 + return IP6T_CONTINUE;
26536 +ip6t_route_checkentry(const char *tablename,
26537 + const struct ip6t_entry *e,
26539 + unsigned int targinfosize,
26540 + unsigned int hook_mask)
26542 + if (strcmp(tablename, "mangle") != 0) {
26543 + printk("ip6t_ROUTE: can only be called from \"mangle\" table.\n");
26547 + if (targinfosize != IP6T_ALIGN(sizeof(struct ip6t_route_target_info))) {
26548 + printk(KERN_WARNING "ip6t_ROUTE: targinfosize %u != %Zu\n",
26550 + IP6T_ALIGN(sizeof(struct ip6t_route_target_info)));
26558 +static struct ip6t_target ip6t_route_reg = {
26560 + .target = ip6t_route_target,
26561 + .checkentry = ip6t_route_checkentry,
26562 + .me = THIS_MODULE
26566 +static int __init init(void)
26568 + printk(KERN_DEBUG "registering ipv6 ROUTE target\n");
26569 + if (ip6t_register_target(&ip6t_route_reg))
26576 +static void __exit fini(void)
26578 + ip6t_unregister_target(&ip6t_route_reg);
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
26588 +/* This is a module which is used for setting
26589 + * the NFC_TRACE flag in the nfcache field of an skb.
26591 +#include <linux/module.h>
26592 +#include <linux/skbuff.h>
26594 +#include <linux/netfilter_ipv6/ip6_tables.h>
26596 +MODULE_LICENSE("GPL");
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,
26606 + (*pskb)->nfcache |= NFC_TRACE;
26607 + return IP6T_CONTINUE;
26611 +checkentry(const char *tablename,
26612 + const struct ip6t_entry *e,
26614 + unsigned int targinfosize,
26615 + unsigned int hook_mask)
26617 + if (targinfosize != 0) {
26618 + printk(KERN_WARNING "TRACE: targinfosize %u != 0\n",
26623 + if (strcmp(tablename, "raw") != 0) {
26624 + printk(KERN_WARNING "TRACE: can only be called from \"raw\" table, not \"%s\"\n", tablename);
26631 +static struct ip6t_target ip6t_trace_reg = {
26632 + .list = { NULL, NULL },
26634 + .target = target,
26635 + .checkentry = checkentry,
26637 + .me = THIS_MODULE };
26639 +static int __init init(void)
26641 + if (ip6t_register_target(&ip6t_trace_reg))
26647 +static void __exit fini(void)
26649 + ip6t_unregister_target(&ip6t_trace_reg);
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
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>
26666 +#include <linux/netfilter_ipv6/ip6_tables.h>
26667 +#include <linux/netfilter_ipv6/ip6t_ah.h>
26669 +EXPORT_NO_SYMBOLS;
26670 +MODULE_LICENSE("GPL");
26671 +MODULE_DESCRIPTION("IPv6 AH match");
26672 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
26675 +#define DEBUGP printk
26677 +#define DEBUGP(format, args...)
26687 +/* Returns 1 if the spi is matched by the range, 0 otherwise */
26689 +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
26692 + DEBUGP("ah spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
26694 + r=(spi >= min && spi <= max) ^ invert;
26695 + DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
26700 +match(const struct sk_buff *skb,
26701 + const struct net_device *in,
26702 + const struct net_device *out,
26703 + const void *matchinfo,
26705 + const void *protohdr,
26706 + u_int16_t datalen,
26709 + struct ahhdr *ah = NULL;
26710 + const struct ip6t_ah *ahinfo = matchinfo;
26711 + unsigned int temp;
26714 + unsigned int ptr;
26715 + unsigned int hdrlen = 0;
26717 + /*DEBUGP("IPv6 AH entered\n");*/
26718 + /* if (opt->auth == 0) return 0;
26719 + * It does not filled on output */
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;
26729 + while (ip6t_ext_hdr(nexthdr)) {
26730 + struct ipv6_opt_hdr *hdr;
26732 + DEBUGP("ipv6_ah header iteration \n");
26734 + /* Is there enough space for the next ext header? */
26735 + if (len < (int)sizeof(struct ipv6_opt_hdr))
26737 + /* No more exthdr -> evaluate */
26738 + if (nexthdr == NEXTHDR_NONE) {
26741 + /* ESP -> evaluate */
26742 + if (nexthdr == NEXTHDR_ESP) {
26746 + hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
26748 + /* Calculate the header length */
26749 + if (nexthdr == NEXTHDR_FRAGMENT) {
26751 + } else if (nexthdr == NEXTHDR_AUTH)
26752 + hdrlen = (hdr->hdrlen+2)<<2;
26754 + hdrlen = ipv6_optlen(hdr);
26756 + /* AH -> evaluate */
26757 + if (nexthdr == NEXTHDR_AUTH) {
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:
26772 + DEBUGP("ipv6_ah match: unknown nextheader %u\n",nexthdr);
26777 + nexthdr = hdr->nexthdr;
26780 + if ( ptr > skb->len ) {
26781 + DEBUGP("ipv6_ah: new pointer too large! \n");
26786 + /* AH header not found */
26787 + if ( temp != MASK_AH ) return 0;
26789 + if (len < (int)sizeof(struct ahhdr)){
26794 + ah = (struct ahhdr *) (skb->data + ptr);
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));
26800 + DEBUGP("IPv6 AH spi %02X ",
26801 + (spi_match(ahinfo->spis[0], ahinfo->spis[1],
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));
26813 + return (ah != NULL)
26815 + (spi_match(ahinfo->spis[0], ahinfo->spis[1],
26817 + !!(ahinfo->invflags & IP6T_AH_INV_SPI)))
26819 + (!ahinfo->hdrlen ||
26820 + (ahinfo->hdrlen == hdrlen) ^
26821 + !!(ahinfo->invflags & IP6T_AH_INV_LEN))
26823 + !(ahinfo->hdrres && ah->reserved);
26826 +/* Called when user tries to insert an entry of this type. */
26828 +checkentry(const char *tablename,
26829 + const struct ip6t_ip6 *ip,
26831 + unsigned int matchinfosize,
26832 + unsigned int hook_mask)
26834 + const struct ip6t_ah *ahinfo = matchinfo;
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)));
26841 + if (ahinfo->invflags & ~IP6T_AH_INV_MASK) {
26842 + DEBUGP("ip6t_ah: unknown flags %X\n",
26843 + ahinfo->invflags);
26850 +static struct ip6t_match ah_match
26851 += { { NULL, NULL }, "ah", &match, &checkentry, NULL, THIS_MODULE };
26853 +static int __init init(void)
26855 + return ip6t_register_match(&ah_match);
26858 +static void __exit cleanup(void)
26860 + ip6t_unregister_match(&ah_match);
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
26869 +/*-------------------------------------------*\
26870 +| Netfilter Condition Module for IPv6 |
26872 +| Description: This module allows firewall |
26873 +| rules to match using condition variables |
26874 +| stored in /proc files. |
26876 +| Author: Stephane Ouellette 2003-02-10 |
26877 +| <ouellettes@videotron.ca> |
26879 +| This software is distributed under the |
26880 +| terms of the GNU GPL. |
26881 +\*-------------------------------------------*/
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>
26892 +#ifndef CONFIG_PROC_FS
26893 +#error "Proc file system support is required for this module"
26897 +MODULE_AUTHOR("Stephane Ouellette <ouellettes@videotron.ca>");
26898 +MODULE_DESCRIPTION("Allows rules to match against condition variables");
26899 +MODULE_LICENSE("GPL");
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 */
26910 +static rwlock_t list_lock;
26911 +static struct condition_variable *head = NULL;
26912 +static struct proc_dir_entry *proc_net_condition = NULL;
26916 +ipt_condition_read_info(char *buffer, char **start, off_t offset,
26917 + int length, int *eof, void *data)
26919 + struct condition_variable *var =
26920 + (struct condition_variable *) data;
26922 + if (offset == 0) {
26924 + buffer[0] = (var->enabled) ? '1' : '0';
26925 + buffer[1] = '\n';
26935 +ipt_condition_write_info(struct file *file, const char *buffer,
26936 + unsigned long length, void *data)
26938 + struct condition_variable *var =
26939 + (struct condition_variable *) data;
26942 + /* Match only on the first character */
26943 + switch (buffer[0]) {
26945 + var->enabled = 0;
26948 + var->enabled = 1;
26952 + return (int) length;
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)
26961 + const struct condition6_info *info =
26962 + (const struct condition6_info *) matchinfo;
26963 + struct condition_variable *var;
26964 + int condition_status = 0;
26966 + read_lock(&list_lock);
26968 + for (var = head; var; var = var->next) {
26969 + if (strcmp(info->name, var->status_proc->name) == 0) {
26970 + condition_status = var->enabled;
26975 + read_unlock(&list_lock);
26977 + return condition_status ^ info->invert;
26983 +checkentry(const char *tablename, const struct ip6t_ip6 *ip,
26984 + void *matchinfo, unsigned int matchsize, unsigned int hook_mask)
26986 + struct condition6_info *info =
26987 + (struct condition6_info *) matchinfo;
26988 + struct condition_variable *var, *newvar;
26990 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
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);
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);
27005 + read_unlock(&list_lock);
27007 + /* At this point, we need to allocate a new condition variable */
27008 + newvar = kmalloc(sizeof(struct condition_variable), GFP_KERNEL);
27013 + /* Create the condition variable's proc file entry */
27014 + newvar->status_proc = create_proc_entry(info->name, 0644, proc_net_condition);
27016 + if (!newvar->status_proc) {
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.
27023 + read_lock(&list_lock);
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);
27033 + read_unlock(&list_lock);
27037 + atomic_set(&newvar->refcount, 1);
27038 + newvar->enabled = 0;
27039 + newvar->status_proc->owner = THIS_MODULE;
27040 + newvar->status_proc->data = newvar;
27042 + newvar->status_proc->read_proc = ipt_condition_read_info;
27043 + newvar->status_proc->write_proc = ipt_condition_write_info;
27045 + write_lock(&list_lock);
27047 + newvar->next = head;
27050 + write_unlock(&list_lock);
27057 +destroy(void *matchinfo, unsigned int matchsize)
27059 + struct condition6_info *info =
27060 + (struct condition6_info *) matchinfo;
27061 + struct condition_variable *var, *prev = NULL;
27063 + if (matchsize != IP6T_ALIGN(sizeof(struct condition6_info)))
27066 + write_lock(&list_lock);
27068 + for (var = head; var && strcmp(info->name, var->status_proc->name);
27069 + prev = var, var = var->next);
27071 + if (var && atomic_dec_and_test(&var->refcount)) {
27073 + prev->next = var->next;
27075 + head = var->next;
27077 + write_unlock(&list_lock);
27078 + remove_proc_entry(var->status_proc->name, proc_net_condition);
27081 + write_unlock(&list_lock);
27085 +static struct ip6t_match condition_match = {
27086 + .name = "condition",
27088 + .checkentry = &checkentry,
27089 + .destroy = &destroy,
27090 + .me = THIS_MODULE
27099 + rwlock_init(&list_lock);
27100 + proc_net_condition = proc_mkdir("ip6t_condition", proc_net);
27102 + if (proc_net_condition) {
27103 + errorcode = ipt_register_match(&condition_match);
27106 + remove_proc_entry("ip6t_condition", proc_net);
27108 + errorcode = -EACCES;
27110 + return errorcode;
27114 +static void __exit
27117 + ipt_unregister_match(&condition_match);
27118 + remove_proc_entry("ip6t_condition", proc_net);
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
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>
27135 +#include <asm/byteorder.h>
27137 +#include <linux/netfilter_ipv6/ip6_tables.h>
27138 +#include <linux/netfilter_ipv6/ip6t_opts.h>
27140 +#define LOW(n) (n & 0x00FF)
27142 +#define HOPBYHOP 0
27144 +EXPORT_NO_SYMBOLS;
27145 +MODULE_LICENSE("GPL");
27147 +MODULE_DESCRIPTION("IPv6 HbH match");
27149 +MODULE_DESCRIPTION("IPv6 DST match");
27151 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27154 +#define DEBUGP printk
27156 +#define DEBUGP(format, args...)
27160 + * (Type & 0xC0) >> 6
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
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
27176 +match(const struct sk_buff *skb,
27177 + const struct net_device *in,
27178 + const struct net_device *out,
27179 + const void *matchinfo,
27181 + const void *protohdr,
27182 + u_int16_t datalen,
27185 + struct ipv6_opt_hdr *optsh = NULL;
27186 + const struct ip6t_opts *optinfo = matchinfo;
27187 + unsigned int temp;
27188 + unsigned int len;
27190 + unsigned int ptr;
27191 + unsigned int hdrlen = 0;
27192 + unsigned int ret = 0;
27193 + u_int16_t *optdesc = NULL;
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;
27203 + while (ip6t_ext_hdr(nexthdr)) {
27204 + struct ipv6_opt_hdr *hdr;
27206 + DEBUGP("ipv6_opts header iteration \n");
27208 + /* Is there enough space for the next ext header? */
27209 + if (len < (int)sizeof(struct ipv6_opt_hdr))
27211 + /* No more exthdr -> evaluate */
27212 + if (nexthdr == NEXTHDR_NONE) {
27215 + /* ESP -> evaluate */
27216 + if (nexthdr == NEXTHDR_ESP) {
27220 + hdr=(void *)(skb->data)+ptr;
27222 + /* Calculate the header length */
27223 + if (nexthdr == NEXTHDR_FRAGMENT) {
27225 + } else if (nexthdr == NEXTHDR_AUTH)
27226 + hdrlen = (hdr->hdrlen+2)<<2;
27228 + hdrlen = ipv6_optlen(hdr);
27230 + /* OPTS -> evaluate */
27232 + if (nexthdr == NEXTHDR_HOP) {
27233 + temp |= MASK_HOPOPTS;
27235 + if (nexthdr == NEXTHDR_DEST) {
27236 + temp |= MASK_DSTOPTS;
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:
27251 + DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
27256 + nexthdr = hdr->nexthdr;
27259 + if ( ptr > skb->len ) {
27260 + DEBUGP("ipv6_opts: new pointer is too large! \n");
27265 + /* OPTIONS header not found */
27267 + if ( temp != MASK_HOPOPTS ) return 0;
27269 + if ( temp != MASK_DSTOPTS ) return 0;
27272 + if (len < (int)sizeof(struct ipv6_opt_hdr)){
27277 + if (len < hdrlen){
27278 + /* Packet smaller than it's length field */
27282 + optsh=(void *)(skb->data)+ptr;
27284 + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
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))));
27292 + ret = (optsh != NULL)
27294 + (!(optinfo->flags & IP6T_OPTS_LEN) ||
27295 + ((optinfo->hdrlen == hdrlen) ^
27296 + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
27301 + if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
27303 + } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
27304 + DEBUGP("Not strict - not implemented");
27306 + DEBUGP("Strict ");
27307 + DEBUGP("#%d ",optinfo->optsnr);
27308 + for(temp=0; temp<optinfo->optsnr; temp++){
27309 + optdesc = (void *)(skb->data)+ptr;
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] &
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]);
27335 + /* Step to the next */
27336 + if ((unsigned char)*optdesc == 0){
27337 + DEBUGP("PAD0 \n");
27341 + ptr += LOW(ntohs(*optdesc));
27342 + hdrlen -= LOW(ntohs(*optdesc));
27343 + DEBUGP("len%04X \n",
27344 + LOW(ntohs(*optdesc)));
27346 + if (ptr > skb->len || ( !hdrlen &&
27347 + (temp != optinfo->optsnr - 1))) {
27348 + DEBUGP("new pointer is too large! \n");
27352 + if (temp == optinfo->optsnr)
27360 +/* Called when user tries to insert an entry of this type. */
27362 +checkentry(const char *tablename,
27363 + const struct ip6t_ip6 *ip,
27365 + unsigned int matchinfosize,
27366 + unsigned int hook_mask)
27368 + const struct ip6t_opts *optsinfo = matchinfo;
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)));
27375 + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
27376 + DEBUGP("ip6t_opts: unknown flags %X\n",
27377 + optsinfo->invflags);
27384 +static struct ip6t_match opts_match
27386 += { { NULL, NULL }, "hbh", &match, &checkentry, NULL, THIS_MODULE };
27388 += { { NULL, NULL }, "dst", &match, &checkentry, NULL, THIS_MODULE };
27391 +static int __init init(void)
27393 + return ip6t_register_match(&opts_match);
27396 +static void __exit cleanup(void)
27398 + ip6t_unregister_match(&opts_match);
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
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>
27415 +#include <linux/netfilter_ipv6/ip6_tables.h>
27416 +#include <linux/netfilter_ipv6/ip6t_esp.h>
27418 +EXPORT_NO_SYMBOLS;
27419 +MODULE_LICENSE("GPL");
27420 +MODULE_DESCRIPTION("IPv6 ESP match");
27421 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27424 +#define DEBUGP printk
27426 +#define DEBUGP(format, args...)
27433 +/* Returns 1 if the spi is matched by the range, 0 otherwise */
27435 +spi_match(u_int32_t min, u_int32_t max, u_int32_t spi, int invert)
27438 + DEBUGP("esp spi_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
27440 + r=(spi >= min && spi <= max) ^ invert;
27441 + DEBUGP(" result %s\n",r? "PASS\n" : "FAILED\n");
27446 +match(const struct sk_buff *skb,
27447 + const struct net_device *in,
27448 + const struct net_device *out,
27449 + const void *matchinfo,
27451 + const void *protohdr,
27452 + u_int16_t datalen,
27455 + struct esphdr *esp = NULL;
27456 + const struct ip6t_esp *espinfo = matchinfo;
27457 + unsigned int temp;
27460 + unsigned int ptr;
27462 + /* Make sure this isn't an evil packet */
27463 + /*DEBUGP("ipv6_esp entered \n");*/
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;
27473 + while (ip6t_ext_hdr(nexthdr)) {
27474 + struct ipv6_opt_hdr *hdr;
27477 + DEBUGP("ipv6_esp header iteration \n");
27479 + /* Is there enough space for the next ext header? */
27480 + if (len < (int)sizeof(struct ipv6_opt_hdr))
27482 + /* No more exthdr -> evaluate */
27483 + if (nexthdr == NEXTHDR_NONE) {
27486 + /* ESP -> evaluate */
27487 + if (nexthdr == NEXTHDR_ESP) {
27488 + temp |= MASK_ESP;
27492 + hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
27494 + /* Calculate the header length */
27495 + if (nexthdr == NEXTHDR_FRAGMENT) {
27497 + } else if (nexthdr == NEXTHDR_AUTH)
27498 + hdrlen = (hdr->hdrlen+2)<<2;
27500 + hdrlen = ipv6_optlen(hdr);
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:
27511 + DEBUGP("ipv6_esp match: unknown nextheader %u\n",nexthdr);
27516 + nexthdr = hdr->nexthdr;
27519 + if ( ptr > skb->len ) {
27520 + DEBUGP("ipv6_esp: new pointer too large! \n");
27525 + /* ESP header not found */
27526 + if ( temp != MASK_ESP ) return 0;
27528 + if (len < (int)sizeof(struct esphdr)){
27533 + esp = (struct esphdr *) (skb->data + ptr);
27535 + DEBUGP("IPv6 ESP SPI %u %08X\n", ntohl(esp->spi), ntohl(esp->spi));
27537 + return (esp != NULL)
27538 + && spi_match(espinfo->spis[0], espinfo->spis[1],
27540 + !!(espinfo->invflags & IP6T_ESP_INV_SPI));
27543 +/* Called when user tries to insert an entry of this type. */
27545 +checkentry(const char *tablename,
27546 + const struct ip6t_ip6 *ip,
27548 + unsigned int matchinfosize,
27549 + unsigned int hook_mask)
27551 + const struct ip6t_esp *espinfo = matchinfo;
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)));
27558 + if (espinfo->invflags & ~IP6T_ESP_INV_MASK) {
27559 + DEBUGP("ip6t_esp: unknown flags %X\n",
27560 + espinfo->invflags);
27567 +static struct ip6t_match esp_match
27568 += { { NULL, NULL }, "esp", &match, &checkentry, NULL, THIS_MODULE };
27570 +static int __init init(void)
27572 + return ip6t_register_match(&esp_match);
27575 +static void __exit cleanup(void)
27577 + ip6t_unregister_match(&esp_match);
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
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>
27594 +#include <asm/byteorder.h>
27596 +#include <linux/netfilter_ipv6/ip6_tables.h>
27597 +#include <linux/netfilter_ipv6/ip6t_frag.h>
27599 +EXPORT_NO_SYMBOLS;
27600 +MODULE_LICENSE("GPL");
27601 +MODULE_DESCRIPTION("IPv6 FRAG match");
27602 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
27605 +#define DEBUGP printk
27607 +#define DEBUGP(format, args...)
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 */
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 */
27633 +/* Returns 1 if the id is matched by the range, 0 otherwise */
27635 +id_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
27638 + DEBUGP("frag id_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
27640 + r=(id >= min && id <= max) ^ invert;
27641 + DEBUGP(" result %s\n",r? "PASS" : "FAILED");
27646 +match(const struct sk_buff *skb,
27647 + const struct net_device *in,
27648 + const struct net_device *out,
27649 + const void *matchinfo,
27651 + const void *protohdr,
27652 + u_int16_t datalen,
27655 + struct fraghdr *frag = NULL;
27656 + const struct ip6t_frag *fraginfo = matchinfo;
27657 + unsigned int temp;
27660 + unsigned int ptr;
27661 + unsigned int hdrlen = 0;
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;
27671 + while (ip6t_ext_hdr(nexthdr)) {
27672 + struct ipv6_opt_hdr *hdr;
27674 + DEBUGP("ipv6_frag header iteration \n");
27676 + /* Is there enough space for the next ext header? */
27677 + if (len < (int)sizeof(struct ipv6_opt_hdr))
27679 + /* No more exthdr -> evaluate */
27680 + if (nexthdr == NEXTHDR_NONE) {
27683 + /* ESP -> evaluate */
27684 + if (nexthdr == NEXTHDR_ESP) {
27688 + hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
27690 + /* Calculate the header length */
27691 + if (nexthdr == NEXTHDR_FRAGMENT) {
27693 + } else if (nexthdr == NEXTHDR_AUTH)
27694 + hdrlen = (hdr->hdrlen+2)<<2;
27696 + hdrlen = ipv6_optlen(hdr);
27698 + /* FRAG -> evaluate */
27699 + if (nexthdr == NEXTHDR_FRAGMENT) {
27700 + temp |= MASK_FRAGMENT;
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:
27714 + DEBUGP("ipv6_frag match: unknown nextheader %u\n",nexthdr);
27719 + nexthdr = hdr->nexthdr;
27722 + if ( ptr > skb->len ) {
27723 + DEBUGP("ipv6_frag: new pointer too large! \n");
27728 + /* FRAG header not found */
27729 + if ( temp != MASK_FRAGMENT ) return 0;
27731 + if (len < (int)sizeof(struct fraghdr)){
27736 + frag = (struct fraghdr *) (skb->data + ptr);
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));
27745 + DEBUGP("IPv6 FRAG id %02X ",
27746 + (id_match(fraginfo->ids[0], fraginfo->ids[1],
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)));
27767 + return (frag != NULL)
27769 + (id_match(fraginfo->ids[0], fraginfo->ids[1],
27771 + !!(fraginfo->invflags & IP6T_FRAG_INV_IDS)))
27773 + (!fraginfo->hdrlen ||
27774 + (fraginfo->hdrlen == hdrlen) ^
27775 + !!(fraginfo->invflags & IP6T_FRAG_INV_LEN))
27777 + !((fraginfo->flags & IP6T_FRAG_RES) && (frag->info & IP6F_RESERVED_MASK))
27779 + !((fraginfo->flags & IP6T_FRAG_FST) && (frag->info & IP6F_OFF_MASK))
27781 + !((fraginfo->flags & IP6T_FRAG_MF) && !((frag->info & IP6F_MORE_FRAG)))
27783 + !((fraginfo->flags & IP6T_FRAG_NMF) && (frag->info & IP6F_MORE_FRAG));
27786 +/* Called when user tries to insert an entry of this type. */
27788 +checkentry(const char *tablename,
27789 + const struct ip6t_ip6 *ip,
27791 + unsigned int matchinfosize,
27792 + unsigned int hook_mask)
27794 + const struct ip6t_frag *fraginfo = matchinfo;
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)));
27801 + if (fraginfo->invflags & ~IP6T_FRAG_INV_MASK) {
27802 + DEBUGP("ip6t_frag: unknown flags %X\n",
27803 + fraginfo->invflags);
27810 +static struct ip6t_match frag_match
27811 += { { NULL, NULL }, "frag", &match, &checkentry, NULL, THIS_MODULE };
27813 +static int __init init(void)
27815 + return ip6t_register_match(&frag_match);
27818 +static void __exit cleanup(void)
27820 + ip6t_unregister_match(&frag_match);
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
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 .
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
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>
27858 + Packet Acceptance Rate - LOW and Packet Acceptance Rate - HIGH
27859 + Expressed in percentage
27862 +#define PAR_LOW 1/100
27863 +#define PAR_HIGH 1
27865 +static spinlock_t fuzzy_lock = SPIN_LOCK_UNLOCKED;
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");
27871 +static u_int8_t mf_high(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
27873 + if (tx >= maxi) return 100;
27875 + if (tx <= mini) return 0;
27877 + return ((100 * (tx-mini)) / (maxi-mini));
27880 +static u_int8_t mf_low(u_int32_t tx,u_int32_t mini,u_int32_t maxi)
27882 + if (tx <= mini) return 100;
27884 + if (tx >= maxi) return 0;
27886 + return ((100 * (maxi - tx)) / (maxi - mini));
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,
27897 + u_int16_t datalen,
27900 + /* From userspace */
27902 + struct ip6t_fuzzy_info *info = (struct ip6t_fuzzy_info *) matchinfo;
27904 + u_int8_t random_number;
27905 + unsigned long amount;
27906 + u_int8_t howhigh, howlow;
27909 + spin_lock_bh(&fuzzy_lock); /* Rise the lock */
27911 + info->bytes_total += pskb->len;
27912 + info->packets_total++;
27914 + info->present_time = jiffies;
27916 + if (info->present_time >= info->previous_time)
27917 + amount = info->present_time - info->previous_time;
27919 + /* There was a transition : I choose to re-sample
27920 + and keep the old acceptance rate...
27924 + info->previous_time = info->present_time;
27925 + info->bytes_total = info->packets_total = 0;
27928 + if ( amount > HZ/10) {/* More than 100 ms elapsed ... */
27930 + info->mean_rate = (u_int32_t) ((HZ * info->packets_total) \
27933 + info->previous_time = info->present_time;
27934 + info->bytes_total = info->packets_total = 0;
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);
27939 + info->acceptance_rate = (u_int8_t) \
27940 + (howhigh * PAR_LOW + PAR_HIGH * howlow);
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,
27952 + spin_unlock_bh(&fuzzy_lock); /* Release the lock */
27955 + if (info->acceptance_rate < 100)
27957 + get_random_bytes((void *)(&random_number), 1);
27959 + /* If within the acceptance , it can pass => don't match */
27960 + if (random_number <= (255 * info->acceptance_rate) / 100)
27963 + return 1; /* It can't pass (It matches) */
27966 + return 0; /* acceptance_rate == 100 % => Everything passes ... */
27971 +ip6t_fuzzy_checkentry(const char *tablename,
27972 + const struct ip6t_ip6 *ip,
27974 + unsigned int matchsize,
27975 + unsigned int hook_mask)
27978 + const struct ip6t_fuzzy_info *info = matchinfo;
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)));
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");
27995 +static struct ip6t_match ip6t_fuzzy_reg = {
27998 + ip6t_fuzzy_match,
27999 + ip6t_fuzzy_checkentry,
28003 +static int __init init(void)
28005 + if (ip6t_register_match(&ip6t_fuzzy_reg))
28011 +static void __exit fini(void)
28013 + ip6t_unregister_match(&ip6t_fuzzy_reg);
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
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>
28030 +#include <asm/byteorder.h>
28032 +#include <linux/netfilter_ipv6/ip6_tables.h>
28033 +#include <linux/netfilter_ipv6/ip6t_opts.h>
28035 +#define LOW(n) (n & 0x00FF)
28037 +#define HOPBYHOP 1
28039 +EXPORT_NO_SYMBOLS;
28040 +MODULE_LICENSE("GPL");
28042 +MODULE_DESCRIPTION("IPv6 HbH match");
28044 +MODULE_DESCRIPTION("IPv6 DST match");
28046 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28049 +#define DEBUGP printk
28051 +#define DEBUGP(format, args...)
28055 + * (Type & 0xC0) >> 6
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
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
28071 +match(const struct sk_buff *skb,
28072 + const struct net_device *in,
28073 + const struct net_device *out,
28074 + const void *matchinfo,
28076 + const void *protohdr,
28077 + u_int16_t datalen,
28080 + struct ipv6_opt_hdr *optsh = NULL;
28081 + const struct ip6t_opts *optinfo = matchinfo;
28082 + unsigned int temp;
28083 + unsigned int len;
28085 + unsigned int ptr;
28086 + unsigned int hdrlen = 0;
28087 + unsigned int ret = 0;
28088 + u_int16_t *optdesc = NULL;
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;
28098 + while (ip6t_ext_hdr(nexthdr)) {
28099 + struct ipv6_opt_hdr *hdr;
28101 + DEBUGP("ipv6_opts header iteration \n");
28103 + /* Is there enough space for the next ext header? */
28104 + if (len < (int)sizeof(struct ipv6_opt_hdr))
28106 + /* No more exthdr -> evaluate */
28107 + if (nexthdr == NEXTHDR_NONE) {
28110 + /* ESP -> evaluate */
28111 + if (nexthdr == NEXTHDR_ESP) {
28115 + hdr=(void *)(skb->data)+ptr;
28117 + /* Calculate the header length */
28118 + if (nexthdr == NEXTHDR_FRAGMENT) {
28120 + } else if (nexthdr == NEXTHDR_AUTH)
28121 + hdrlen = (hdr->hdrlen+2)<<2;
28123 + hdrlen = ipv6_optlen(hdr);
28125 + /* OPTS -> evaluate */
28127 + if (nexthdr == NEXTHDR_HOP) {
28128 + temp |= MASK_HOPOPTS;
28130 + if (nexthdr == NEXTHDR_DEST) {
28131 + temp |= MASK_DSTOPTS;
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:
28146 + DEBUGP("ipv6_opts match: unknown nextheader %u\n",nexthdr);
28151 + nexthdr = hdr->nexthdr;
28154 + if ( ptr > skb->len ) {
28155 + DEBUGP("ipv6_opts: new pointer is too large! \n");
28160 + /* OPTIONS header not found */
28162 + if ( temp != MASK_HOPOPTS ) return 0;
28164 + if ( temp != MASK_DSTOPTS ) return 0;
28167 + if (len < (int)sizeof(struct ipv6_opt_hdr)){
28172 + if (len < hdrlen){
28173 + /* Packet smaller than it's length field */
28177 + optsh=(void *)(skb->data)+ptr;
28179 + DEBUGP("IPv6 OPTS LEN %u %u ", hdrlen, optsh->hdrlen);
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))));
28187 + ret = (optsh != NULL)
28189 + (!(optinfo->flags & IP6T_OPTS_LEN) ||
28190 + ((optinfo->hdrlen == hdrlen) ^
28191 + !!(optinfo->invflags & IP6T_OPTS_INV_LEN)));
28196 + if ( !(optinfo->flags & IP6T_OPTS_OPTS) ){
28198 + } else if (optinfo->flags & IP6T_OPTS_NSTRICT) {
28199 + DEBUGP("Not strict - not implemented");
28201 + DEBUGP("Strict ");
28202 + DEBUGP("#%d ",optinfo->optsnr);
28203 + for(temp=0; temp<optinfo->optsnr; temp++){
28204 + optdesc = (void *)(skb->data)+ptr;
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] &
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]);
28230 + /* Step to the next */
28231 + if ((unsigned char)*optdesc == 0){
28232 + DEBUGP("PAD0 \n");
28236 + ptr += LOW(ntohs(*optdesc));
28237 + hdrlen -= LOW(ntohs(*optdesc));
28238 + DEBUGP("len%04X \n",
28239 + LOW(ntohs(*optdesc)));
28241 + if (ptr > skb->len || ( !hdrlen &&
28242 + (temp != optinfo->optsnr - 1))) {
28243 + DEBUGP("new pointer is too large! \n");
28247 + if (temp == optinfo->optsnr)
28255 +/* Called when user tries to insert an entry of this type. */
28257 +checkentry(const char *tablename,
28258 + const struct ip6t_ip6 *ip,
28260 + unsigned int matchinfosize,
28261 + unsigned int hook_mask)
28263 + const struct ip6t_opts *optsinfo = matchinfo;
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)));
28270 + if (optsinfo->invflags & ~IP6T_OPTS_INV_MASK) {
28271 + DEBUGP("ip6t_opts: unknown flags %X\n",
28272 + optsinfo->invflags);
28279 +static struct ip6t_match opts_match
28281 += { { NULL, NULL }, "hbh", &match, &checkentry, NULL, THIS_MODULE };
28283 += { { NULL, NULL }, "dst", &match, &checkentry, NULL, THIS_MODULE };
28286 +static int __init init(void)
28288 + return ip6t_register_match(&opts_match);
28291 +static void __exit cleanup(void)
28293 + ip6t_unregister_match(&opts_match);
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
28303 + * Hop Limit matching module
28304 + * Maciej Soltysiak <solt@dns.toxicfilms.tv>
28305 + * Based on HW's ttl module
28307 + * This software is distributed under the terms GNU GPL
28310 +#include <linux/module.h>
28311 +#include <linux/skbuff.h>
28313 +#include <linux/netfilter_ipv6/ip6t_hl.h>
28314 +#include <linux/netfilter_ipv6/ip6_tables.h>
28316 +MODULE_AUTHOR("Maciej Soltysiak <solt@dns.toxicfilms.tv>");
28317 +MODULE_DESCRIPTION("IP tables Hop Limit matching module");
28318 +MODULE_LICENSE("GPL");
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,
28325 + const struct ip6t_hl_info *info = matchinfo;
28326 + const struct ipv6hdr *ip6h = skb->nh.ipv6h;
28328 + switch (info->mode) {
28330 + return (ip6h->hop_limit == info->hop_limit);
28333 + return (!(ip6h->hop_limit == info->hop_limit));
28336 + return (ip6h->hop_limit < info->hop_limit);
28339 + return (ip6h->hop_limit > info->hop_limit);
28342 + printk(KERN_WARNING "ip6t_hl: unknown mode %d\n",
28350 +static int checkentry(const char *tablename, const struct ip6t_ip6 *ip,
28351 + void *matchinfo, unsigned int matchsize,
28352 + unsigned int hook_mask)
28354 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_hl_info)))
28360 +static struct ip6t_match hl_match = { { NULL, NULL }, "hl", &match,
28361 + &checkentry, NULL, THIS_MODULE };
28363 +static int __init init(void)
28365 + return ip6t_register_match(&hl_match);
28368 +static void __exit fini(void)
28370 + ip6t_unregister_match(&hl_match);
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
28380 +/* ipv6header match - matches IPv6 packets based
28381 +on whether they contain certain headers */
28383 +/* Original idea: Brad Chapman
28384 + * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
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>
28393 +#include <linux/netfilter_ipv6/ip6_tables.h>
28394 +#include <linux/netfilter_ipv6/ip6t_ipv6header.h>
28396 +EXPORT_NO_SYMBOLS;
28397 +MODULE_LICENSE("GPL");
28398 +MODULE_DESCRIPTION("IPv6 headers match");
28399 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28402 +ipv6header_match(const struct sk_buff *skb,
28403 + const struct net_device *in,
28404 + const struct net_device *out,
28405 + const void *matchinfo,
28407 + const void *protohdr,
28408 + u_int16_t datalen,
28411 + const struct ip6t_ipv6header_info *info = matchinfo;
28412 + unsigned int temp;
28415 + unsigned int ptr;
28417 + /* Make sure this isn't an evil packet */
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;
28427 + while (ip6t_ext_hdr(nexthdr)) {
28428 + struct ipv6_opt_hdr *hdr;
28431 + /* Is there enough space for the next ext header? */
28432 + if (len < (int)sizeof(struct ipv6_opt_hdr))
28434 + /* No more exthdr -> evaluate */
28435 + if (nexthdr == NEXTHDR_NONE) {
28436 + temp |= MASK_NONE;
28439 + /* ESP -> evaluate */
28440 + if (nexthdr == NEXTHDR_ESP) {
28441 + temp |= MASK_ESP;
28445 + hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
28447 + /* Calculate the header length */
28448 + if (nexthdr == NEXTHDR_FRAGMENT) {
28450 + } else if (nexthdr == NEXTHDR_AUTH)
28451 + hdrlen = (hdr->hdrlen+2)<<2;
28453 + hdrlen = ipv6_optlen(hdr);
28455 + /* set the flag */
28456 + switch (nexthdr){
28457 + case NEXTHDR_HOP:
28458 + temp |= MASK_HOPOPTS;
28460 + case NEXTHDR_ROUTING:
28461 + temp |= MASK_ROUTING;
28463 + case NEXTHDR_FRAGMENT:
28464 + temp |= MASK_FRAGMENT;
28466 + case NEXTHDR_AUTH:
28469 + case NEXTHDR_DEST:
28470 + temp |= MASK_DSTOPTS;
28477 + nexthdr = hdr->nexthdr;
28480 + if ( ptr > skb->len ) {
28485 + if ( (nexthdr != NEXTHDR_NONE ) && (nexthdr != NEXTHDR_ESP) )
28486 + temp |= MASK_PROTO;
28488 + if (info->modeflag)
28489 + return (!( (temp & info->matchflags)
28490 + ^ info->matchflags) ^ info->invflags);
28492 + return (!( temp ^ info->matchflags) ^ info->invflags);
28496 +ipv6header_checkentry(const char *tablename,
28497 + const struct ip6t_ip6 *ip,
28499 + unsigned int matchsize,
28500 + unsigned int hook_mask)
28502 + /* Check for obvious errors */
28503 + /* This match is valid in all hooks! */
28504 + if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_ipv6header_info))) {
28511 +static struct ip6t_match
28512 +ip6t_ipv6header_match = {
28515 + &ipv6header_match,
28516 + &ipv6header_checkentry,
28520 +static int __init ipv6header_init(void)
28522 + return ip6t_register_match(&ip6t_ipv6header_match);
28525 +static void __exit ipv6header_exit(void)
28527 + ip6t_unregister_match(&ip6t_ipv6header_match);
28530 +module_init(ipv6header_init);
28531 +module_exit(ipv6header_exit);
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
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
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
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>
28560 +MODULE_LICENSE("GPL");
28563 + * State information.
28567 + u_int16_t number;
28570 +static struct state states[IP6T_NTH_NUM_COUNTERS];
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,
28579 + u_int16_t datalen,
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))
28587 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
28591 + spin_lock(&states[counter].lock);
28593 + /* Are we matching every nth packet?*/
28594 + if (info->packet == 0xFF)
28596 + /* We're matching every nth packet and only every nth packet*/
28597 + /* Do we match or invert match? */
28598 + if (info->not == 0)
28600 + if (states[counter].number == 0)
28602 + ++states[counter].number;
28605 + if (states[counter].number >= info->every)
28606 + states[counter].number = 0; /* reset the counter */
28608 + ++states[counter].number;
28613 + if (states[counter].number == 0)
28615 + ++states[counter].number;
28618 + if (states[counter].number >= info->every)
28619 + states[counter].number = 0;
28621 + ++states[counter].number;
28627 + /* We're using the --packet, so there must be a rule for every value */
28628 + if (states[counter].number == info->packet)
28630 + /* only increment the counter when a match happens */
28631 + if (states[counter].number >= info->every)
28632 + states[counter].number = 0; /* reset the counter */
28634 + ++states[counter].number;
28642 + /* don't match */
28643 + spin_unlock(&states[counter].lock);
28647 + spin_unlock(&states[counter].lock);
28652 +ip6t_nth_checkentry(const char *tablename,
28653 + const struct ip6t_ip6 *e,
28655 + unsigned int matchsize,
28656 + unsigned int hook_mask)
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))
28663 + printk(KERN_WARNING "nth: invalid counter %u. counter between 0 and %u\n", counter, IP6T_NTH_NUM_COUNTERS-1);
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)));
28673 + states[counter].number = info->startat;
28678 +static struct ip6t_match ip6t_nth_reg = {
28682 + ip6t_nth_checkentry,
28686 +static int __init init(void)
28688 + unsigned counter;
28689 + memset(&states, 0, sizeof(states));
28690 + if (ip6t_register_match(&ip6t_nth_reg))
28693 + for(counter = 0; counter < IP6T_NTH_NUM_COUNTERS; counter++)
28695 + spin_lock_init(&(states[counter].lock));
28698 + printk("ip6t_nth match loaded\n");
28702 +static void __exit fini(void)
28704 + ip6t_unregister_match(&ip6t_nth_reg);
28705 + printk("ip6t_nth match unloaded\n");
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
28714 MODULE_LICENSE("GPL");
28717 +match_comm(const struct sk_buff *skb, const char *comm)
28719 + struct task_struct *p;
28720 + struct files_struct *files;
28723 + read_lock(&tasklist_lock);
28724 + for_each_task(p) {
28725 + if(strncmp(p->comm, comm, sizeof(p->comm)))
28729 + files = p->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);
28736 + read_unlock(&tasklist_lock);
28740 + read_unlock(&files->file_lock);
28744 + read_unlock(&tasklist_lock);
28749 match_pid(const struct sk_buff *skb, pid_t pid)
28751 struct task_struct *p;
28752 @@ -119,6 +151,12 @@
28756 + if(info->match & IP6T_OWNER_COMM) {
28757 + if (!match_comm(skb, info->comm) ^
28758 + !!(info->invert & IP6T_OWNER_COMM))
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
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
28775 + 2001-10-14 Fabrice MARIE <fabrice@netfilter.org> : initial implementation.
28776 + 2003-04-30 Maciej Soltysiak <solt@dns.toxicfilms.tv> : IPv6 Port
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>
28788 +MODULE_LICENSE("GPL");
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,
28797 + u_int16_t datalen,
28800 + /* Parameters from userspace */
28801 + const struct ip6t_rand_info *info = matchinfo;
28802 + u_int8_t random_number;
28804 + /* get 1 random number from the kernel random number generation routine */
28805 + get_random_bytes((void *)(&random_number), 1);
28807 + /* Do we match ? */
28808 + if (random_number <= info->average)
28815 +ip6t_rand_checkentry(const char *tablename,
28816 + const struct ip6t_ip6 *e,
28818 + unsigned int matchsize,
28819 + unsigned int hook_mask)
28821 + /* Parameters from userspace */
28822 + const struct ip6t_rand_info *info = matchinfo;
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)));
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);
28841 +static struct ip6t_match ip6t_rand_reg = {
28845 + ip6t_rand_checkentry,
28849 +static int __init init(void)
28851 + if (ip6t_register_match(&ip6t_rand_reg))
28854 + printk("ip6t_random match loaded\n");
28858 +static void __exit fini(void)
28860 + ip6t_unregister_match(&ip6t_rand_reg);
28861 + printk("ip6t_random match unloaded\n");
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
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>
28878 +#include <asm/byteorder.h>
28880 +#include <linux/netfilter_ipv6/ip6_tables.h>
28881 +#include <linux/netfilter_ipv6/ip6t_rt.h>
28883 +EXPORT_NO_SYMBOLS;
28884 +MODULE_LICENSE("GPL");
28885 +MODULE_DESCRIPTION("IPv6 RT match");
28886 +MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
28889 +#define DEBUGP printk
28891 +#define DEBUGP(format, args...)
28894 +/* Returns 1 if the id is matched by the range, 0 otherwise */
28896 +segsleft_match(u_int32_t min, u_int32_t max, u_int32_t id, int invert)
28899 + DEBUGP("rt segsleft_match:%c 0x%x <= 0x%x <= 0x%x",invert? '!':' ',
28901 + r=(id >= min && id <= max) ^ invert;
28902 + DEBUGP(" result %s\n",r? "PASS" : "FAILED");
28907 +match(const struct sk_buff *skb,
28908 + const struct net_device *in,
28909 + const struct net_device *out,
28910 + const void *matchinfo,
28912 + const void *protohdr,
28913 + u_int16_t datalen,
28916 + struct ipv6_rt_hdr *route = NULL;
28917 + const struct ip6t_rt *rtinfo = matchinfo;
28918 + unsigned int temp;
28919 + unsigned int len;
28921 + unsigned int ptr;
28922 + unsigned int hdrlen = 0;
28923 + unsigned int ret = 0;
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;
28933 + while (ip6t_ext_hdr(nexthdr)) {
28934 + struct ipv6_opt_hdr *hdr;
28936 + DEBUGP("ipv6_rt header iteration \n");
28938 + /* Is there enough space for the next ext header? */
28939 + if (len < (int)sizeof(struct ipv6_opt_hdr))
28941 + /* No more exthdr -> evaluate */
28942 + if (nexthdr == NEXTHDR_NONE) {
28945 + /* ESP -> evaluate */
28946 + if (nexthdr == NEXTHDR_ESP) {
28950 + hdr=(struct ipv6_opt_hdr *)skb->data+ptr;
28952 + /* Calculate the header length */
28953 + if (nexthdr == NEXTHDR_FRAGMENT) {
28955 + } else if (nexthdr == NEXTHDR_AUTH)
28956 + hdrlen = (hdr->hdrlen+2)<<2;
28958 + hdrlen = ipv6_optlen(hdr);
28960 + /* ROUTING -> evaluate */
28961 + if (nexthdr == NEXTHDR_ROUTING) {
28962 + temp |= MASK_ROUTING;
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:
28976 + DEBUGP("ipv6_rt match: unknown nextheader %u\n",nexthdr);
28981 + nexthdr = hdr->nexthdr;
28984 + if ( ptr > skb->len ) {
28985 + DEBUGP("ipv6_rt: new pointer is too large! \n");
28990 + /* ROUTING header not found */
28991 + if ( temp != MASK_ROUTING ) return 0;
28993 + if (len < (int)sizeof(struct ipv6_rt_hdr)){
28998 + if (len < hdrlen){
28999 + /* Pcket smaller than its length field */
29003 + route = (struct ipv6_rt_hdr *) (skb->data + ptr);
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));
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)));
29027 + ret = (route != NULL)
29029 + (segsleft_match(rtinfo->segsleft[0], rtinfo->segsleft[1],
29030 + ntohl(route->segments_left),
29031 + !!(rtinfo->invflags & IP6T_RT_INV_SGS)))
29033 + (!(rtinfo->flags & IP6T_RT_LEN) ||
29034 + ((rtinfo->hdrlen == hdrlen) ^
29035 + !!(rtinfo->invflags & IP6T_RT_INV_LEN)))
29037 + (!(rtinfo->flags & IP6T_RT_TYP) ||
29038 + ((rtinfo->rt_type == route->type) ^
29039 + !!(rtinfo->invflags & IP6T_RT_INV_TYP)))
29041 + !((rtinfo->flags & IP6T_RT_RES) && (((struct rt0_hdr *)route)->bitmap));
29043 + DEBUGP("#%d ",rtinfo->addrnr);
29044 + temp = len = ptr = 0;
29045 + if ( !(rtinfo->flags & IP6T_RT_FST) ){
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");
29053 + DEBUGP("#%d ",rtinfo->addrnr);
29055 + for(temp=0; temp<(unsigned int)((hdrlen-8)/16); temp++){
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]));
29064 + if ( len == 16 ) break;
29067 + DEBUGP("ptr=%d temp=%d;\n",ptr,temp);
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);
29075 + if (ptr==rtinfo->addrnr) break;
29077 + DEBUGP("ptr=%d len=%d #%d\n",ptr,len, rtinfo->addrnr);
29078 + if ( (len == 16) && (ptr == rtinfo->addrnr))
29083 + DEBUGP("Strict ");
29084 + if ( rtinfo->addrnr > (unsigned int)((hdrlen-8)/16) ){
29085 + DEBUGP("There isn't enough space\n");
29088 + DEBUGP("#%d ",rtinfo->addrnr);
29089 + for(temp=0; temp<rtinfo->addrnr; temp++){
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]));
29098 + if ( len == 16 ) break;
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);
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)))
29118 +/* Called when user tries to insert an entry of this type. */
29120 +checkentry(const char *tablename,
29121 + const struct ip6t_ip6 *ip,
29123 + unsigned int matchinfosize,
29124 + unsigned int hook_mask)
29126 + const struct ip6t_rt *rtinfo = matchinfo;
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)));
29133 + if (rtinfo->invflags & ~IP6T_RT_INV_MASK) {
29134 + DEBUGP("ip6t_rt: unknown flags %X\n",
29135 + rtinfo->invflags);
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-*'");
29149 +static struct ip6t_match rt_match
29150 += { { NULL, NULL }, "rt", &match, &checkentry, NULL, THIS_MODULE };
29152 +static int __init init(void)
29154 + return ip6t_register_match(&rt_match);
29157 +static void __exit cleanup(void)
29159 + ip6t_unregister_match(&rt_match);
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;
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);
29174 ret = ip6t_do_table(pskb, hook, in, out, &packet_mangler, NULL);
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
29181 + * IPv6 raw table, a port of the IPv4 raw table to IPv6
29183 + * Copyright (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
29185 +#include <linux/module.h>
29186 +#include <linux/netfilter_ipv6/ip6_tables.h>
29188 +#define RAW_VALID_HOOKS ((1 << NF_IP6_PRE_ROUTING) | (1 << NF_IP6_LOCAL_OUT))
29191 +#define DEBUGP(x, args...) printk(KERN_DEBUG x, ## args)
29193 +#define DEBUGP(x, args...)
29196 +/* Standard entry. */
29197 +struct ip6t_standard
29199 + struct ip6t_entry entry;
29200 + struct ip6t_standard_target target;
29203 +struct ip6t_error_target
29205 + struct ip6t_entry_target target;
29206 + char errorname[IP6T_FUNCTION_MAXNAMELEN];
29211 + struct ip6t_entry entry;
29212 + struct ip6t_error_target target;
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) },
29229 + /* PRE_ROUTING */
29230 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 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 } },
29238 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 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 } },
29247 + { { { { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, { { { 0 } } }, "", "", { 0 }, { 0 }, 0, 0, 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 } },
29259 +static struct ip6t_table packet_raw = {
29260 + .list = { NULL, NULL },
29262 + .table = &initial_table.repl,
29263 + .valid_hooks = RAW_VALID_HOOKS,
29264 + .lock = RW_LOCK_UNLOCKED,
29266 + .me = THIS_MODULE
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 *))
29277 + return ip6t_do_table(pskb, hook, in, out, &packet_raw, NULL);
29280 +static struct nf_hook_ops ip6t_ops[] = {
29281 + /* PRE_ROUTING */
29282 + { .list = { NULL, NULL },
29283 + .hook = ip6t_hook,
29285 + .hooknum = NF_IP6_PRE_ROUTING,
29286 + .priority = NF_IP6_PRI_FIRST },
29288 + { .list = { NULL, NULL },
29289 + .hook = ip6t_hook,
29291 + .hooknum = NF_IP6_LOCAL_OUT,
29292 + .priority = NF_IP6_PRI_FIRST }
29295 +static int __init init(void)
29299 + /* Register table */
29300 + ret = ip6t_register_table(&packet_raw);
29304 + /* Register hooks */
29305 + ret = nf_register_hook(&ip6t_ops[0]);
29307 + goto cleanup_table;
29309 + ret = nf_register_hook(&ip6t_ops[1]);
29311 + goto cleanup_hook0;
29316 + nf_unregister_hook(&ip6t_ops[0]);
29318 + ip6t_unregister_table(&packet_raw);
29323 +static void __exit fini(void)
29327 + for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
29328 + nf_unregister_hook(&ip6t_ops[i]);
29330 + ip6t_unregister_table(&packet_raw);
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);
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 @@
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);
29366 #include <linux/netfilter_ipv4.h>
29367 EXPORT_SYMBOL(ip_route_me_harder);
29368 @@ -593,13 +601,6 @@
29370 EXPORT_SYMBOL(softnet_data);
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);
29376 -extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
29377 -EXPORT_SYMBOL(udp_v4_lookup);
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 */
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);
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);
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);
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 */
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);
29408 +#endif /* CONFIG_IP_NF_MATCH_OWNER */
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
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
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
29455 +./base/nth6.patch.ipv6
29459 +./base/quota.patch
29460 +./base/random.patch
29461 +./base/random6.patch.ipv6
29462 +./base/realm.patch
29465 +./extra/CLASSIFY.patch
29466 +./extra/CONNMARK.patch
29468 +./extra/IMQ.patch.ipv6
29469 +./extra/IPMARK.patch
29470 +./extra/ROUTE.patch
29471 +./extra/ROUTE.patch.ipv6
29472 +./extra/TCPLAG.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
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