summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/br_fw_ia/br_fw_ia.html634
1 files changed, 634 insertions, 0 deletions
diff --git a/docs/br_fw_ia/br_fw_ia.html b/docs/br_fw_ia/br_fw_ia.html
new file mode 100644
index 0000000..25cf769
--- /dev/null
+++ b/docs/br_fw_ia/br_fw_ia.html
@@ -0,0 +1,634 @@
+<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01//EN'
+'http://www.w3.org/TR/html4/strict.dtd'>
+<HTML>
+ <HEAD>
+ <TITLE>
+ ebtables/iptables interaction on a Linux-based bridge
+ </TITLE>
+ <META HTTP-EQUIV="Content-Type" CONTENT=
+ "text/html; charset=iso-8859-1">
+ <LINK REL="STYLESHEET" TYPE="text/css" HREF="ebtables.css">
+ </HEAD>
+ <BODY>
+ <DIV CLASS="bar">
+ <DIV CLASS="shadow">
+ <H1 ALIGN="center">
+ ebtables/iptables interaction on a Linux-based bridge
+ </H1>
+ </DIV>
+ </DIV>
+ <H3>
+ <A NAME="top">Table of Contents</A>
+ </H3>
+ <OL>
+ <LI>
+ <A HREF="#section1">Introduction</A>
+ </LI>
+ <LI>
+ <A HREF="#section2">How frames traverse the
+ <EM>ebtables</EM> chains</A>
+ </LI>
+ <LI>
+ <A HREF="#section3">A machine used as a bridge and a
+ router (not a brouter)</A>
+ </LI>
+ <LI>
+ <A HREF="#section4">DNAT'ing bridged packets</A>
+ </LI>
+ <LI>
+ <A HREF="#section5">Chain traversal for bridged IP packets</A>
+ </LI>
+ <LI>
+ <A HREF="#section6">Using a bridge port in <EM>iptables</EM> rules</A>
+ </LI>
+ <LI>
+ <A HREF="#section7">Two possible ways for frames/packets
+ to pass through the <EM>iptables</EM> PREROUTING, FORWARD and
+ POSTROUTING chains</A>
+ </LI>
+ <LI>
+ <A HREF="#section8">IP DNAT in the <EM>iptables</EM> PREROUTING
+ chain on frames/packets entering on a bridge port</A>
+ </LI>
+ <LI>
+ <A HREF="#section9">Using the MAC module extension for
+ <EM>iptables</EM></A>
+ </LI>
+ </OL>
+ <A NAME="section1"></A>
+ <P CLASS="section">
+ 1. Introduction
+ </P>
+ <P>
+ This document describes how <EM>iptables</EM> and
+ <EM>ebtables</EM> filtering tables interact on a Linux-based bridge.<BR>
+ Getting a bridging firewall consists of patching the kernel source
+ code with two patches. The first patch is called "br-nf" and makes
+ bridged IP frames/packets go through the <EM>iptables</EM> chains.
+ The second patch adds <EM>ebtables</EM> support in the kernel.
+ <EM>Ebtables</EM> filters on the Ethernet layer, while <EM>iptables</EM>
+ only filters IP packets.<BR>
+ It is possible to use <EM>ebtables</EM> without compiling the br-nf
+ code into the kernel. The only reason why the <EM>ebtables</EM> patch
+ has to be applied after the br-nf patch is because some files are
+ changed by both patches.
+ </P>
+ <A NAME="section2"></A>
+ <P CLASS="section">
+ 2. How frames traverse the <EM>ebtables</EM> chains
+ </P>
+ <DIV CLASS="note">
+ This section only considers <EM>ebtables</EM>, not
+ <EM>iptables</EM>.
+ </DIV>
+ <P>
+ First thing to keep in mind is that we are talking about
+ the Ethernet layer here, so the OSI layer 2 (Data link
+ layer), or layer 1 (Link layer, Network Access layer) by the TCP/IP Network
+ Model. All samples below will be explained according to the TCP/IP
+ Network Model.
+ </P>
+ <P>
+ A packet destined for the local computer according to the
+ bridge (which works on the Ethernet layer) isn't
+ necessarily destined for the local computer according to
+ the IP layer. That's how routing works (MAC destination is
+ the router, IP destination is the actual box you want to
+ communicate with).
+ </P>
+ <P>
+ <IMG SRC="bridge2a.png">
+ </P>
+ <P>
+ <I><B>Figure 2a.</B> General frame traversal scheme</I><BR>
+ </P>
+ <P>
+ </P>
+ <P>
+ There are five hooks defined in the Linux bridging code.
+ The sixth hook (BROUTING) is added by the <EM>ebtables</EM> patch.
+ The hooks are places in the network
+ code where software can hook itself in to process the
+ packets/frames passing that hook.
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge2b.png">
+ <P>
+ <I><B>Figure 2b.</B> Ethernet Bridging hooks</I><BR>
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge2c.png">
+ <P>
+ <I><B>Figure 2c.</B> Bridging tables (ebtables) traversal
+ process</I><BR>
+ </P>
+ <P>
+ <EM>Ebtables</EM> has three built in tables:
+ <B>filter</B>, <B>nat</B> and <B>broute</B>, as shown in Figure 2c.
+ </P>
+ <UL>
+ <LI>
+ The <FONT COLOR="#00ffff"><B>broute</B></FONT> table has
+ the BROUTING chain.
+ </LI>
+ <LI>
+ The <FONT COLOR="#00ffff"><B>filter</B></FONT> table has
+ the FORWARD, INPUT and OUTPUT chains.
+ </LI>
+ <LI>
+ The <FONT COLOR="#00ffff"><B>nat</B></FONT> table has the
+ PREROUTING, OUTPUT and POSTROUTING chains.
+ </LI>
+ </UL>
+ <BR>
+ <DIV CLASS="note">
+ The filter OUTPUT and nat OUTPUT chains are separated and have
+ a different usage.
+ </DIV>
+ <P>
+ Figures 2b and 2c give a clear view where the
+ <EM>ebtables</EM> chains are hooked into the bridge code.
+ </P>
+ <P>
+ When a NIC enslaved to a bridge receives a frame, the frame
+ will first go through the BROUTING chain. In this special
+ chain you can choose whether to route or bridge frames,
+ enabling you to make a brouter. The definitions found on
+ the Internet for what a brouter actually is differ a bit.
+ The next definition describes the brouting ability using the
+ BROUTING chain quite well:
+ </P>
+ <DIV CLASS="note">
+ A brouter is a device which
+ bridges some frames/packets (i.e. forwards based on Link layer
+ information) and routes other frames/packets (i.e. forwards based
+ on Network layer information). The bridge/route decision is
+ based on configuration information.
+ </DIV>
+ <P>
+ A brouter can be used, for example,
+ to act as a normal router for IP traffic between 2
+ networks, while bridging specific traffic (NetBEUI, ARP,
+ whatever) between those networks. The IP routing
+ table does not use the bridge logical device and the box has
+ IP addresses assigned to the physical network devices that
+ also happen to be bridge ports (bridge enslaved NICs).<BR>
+ The default decision in the BROUTING chain is bridging.
+ </P>
+ <P>
+ Next the frame passes through the PREROUTING chain.
+ In this chain you can alter the destination MAC address
+ of frames (DNAT).
+ If the frame passes this chain, the bridging code will decide where the
+ frame should be sent. The bridge does this by looking at
+ the destination MAC address, it doesn't care about the
+ Network layer addresses (e.g. IP address).
+ </P>
+ <DIV CLASS="note">
+ Incoming frames on non-forwarding ports of a bridge will
+ not be seen by <EM>ebtables</EM>, not even by the BROUTING
+ chain.
+ </DIV>
+ <P>
+ If the bridge decides the frame is destined for the local
+ computer, the frame will go through the INPUT chain.
+ In this chain you can filter frames destined for the bridge box.
+ After traversal of the INPUT chain, the frame will be passed up
+ to the Network layer code (e.g. to the IP code).
+ So, a routed IP packet will go through
+ the <EM>ebtables</EM> INPUT chain, not through the
+ <EM>ebtables</EM> FORWARD chain. This is logical.
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge2d.png">
+ <P>
+ <I><B>Figure 2d.</B> Incoming frames' chain traversal</I><BR>
+ </P>
+ <P>
+ Otherwise the frame should possibly be sent onto another side
+ of the bridge. If it should, the frame will go through the
+ FORWARD chain and the POSTROUTING chain. The bridged frames can be
+ filtered in the FORWARD chain. In the POSTROUTING chain you can alter the MAC
+ source address (SNAT).
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge2e.png">
+ <P>
+ <I><B>Figure 2e.</B> Forwarded frames' chain traversal</I><BR>
+ </P>
+ <P>
+ Locally originated frames will, after the bridging decision, traverse
+ the nat OUTPUT, the filter OUTPUT and the nat POSTROUTING chains.
+ The nat OUTPUT chain allows to alter the destination
+ MAC address and the filter OUTPUT chain allows to
+ filter frames originating from the bridge box. Note that
+ the nat OUTPUT chain is traversed after the bridging
+ decision, so this is actually too late. We should change this. The nat
+ POSTROUTING chain is the same one as described above.
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge2f.png">
+ <P>
+ <I><B>Figure 2f.</B> Outgoing frames' chain traversal</I><BR>
+ </P>
+ <DIV CLASS="note">
+ It's also possible for routed frames to go
+ through these three chains when the destination
+ device is a logical bridge device.
+ </DIV>
+ <BR>
+ <BR>
+ <A NAME="section3"></A>
+ <P CLASS="section">
+ 3. A machine used as a bridge and a router (not a brouter)
+ </P>
+ <P>
+ Here is the IP code hooks scheme:
+ </P>
+ <IMG SRC="bridge3a.png">
+ <P>
+ <I><B>Figure 3a.</B> IP code hooks</I><BR>
+ </P>
+ <P>
+ Here is the iptables packet traversal scheme.
+ </P>
+ <BR>
+ <BR>
+ <IMG SRC="bridge3b.png">
+ <P>
+ <I><B>Figure 3b.</B> Routing tables (iptables) traversal
+ process</I><BR>
+ </P>
+ <P>
+ Note that the iptables nat OUTPUT chain is situated after the
+ routing decision. As commented in the previous section,
+ this is too late for DNAT. This is solved by rerouting the
+ IP packet if it has been DNAT'ed, before continuing.
+ </P>
+ <P>
+ Figures 3a and 3b give a clear view where the
+ <EM>iptables</EM> chains are hooked into the IP code. When the br-nf
+ patch is compiled into the kernel, the iptables chains are
+ also hooked in the hooks of the bridging code. However,
+ this does not mean that they are no longer hooked into their
+ standard IP code hooks. For IP packets that get into
+ contact with the bridging code, the br-nf patch will
+ decide in which place in the network code the <EM>iptables</EM>
+ chains are traversed. Obviously, it is guaranteed that no chain is
+ traversed twice by the same packet. All packets that do not come into
+ contact with the bridge code traverse the <EM>iptables</EM> chains
+ in the standard way as seen in Figure 3b.<BR>
+ The following sections try, among other things,
+ to explain what the br-nf patch does and why it does it.
+ </P>
+ <P>
+ It's possible to see a single IP packet/frame traverse the
+ nat PREROUTING, filter INPUT, nat OUTPUT, filter OUTPUT and
+ nat POSTROUTING <EM>ebtables</EM> chains.<BR>
+ This can happen when the bridge is also used as a router.
+ The Ethernet frame(s) containing that IP packet will have
+ the bridge's destination MAC address, while the destination
+ IP address is not of the bridge. Including the
+ <EM>iptables</EM> chains and assuming the br-nf code is
+ compiled into the kernel, this is how the IP packet runs
+ through the bridge/router (actually there is more going on,
+ see <A HREF="#section6">section 6</A>):
+ </P>
+ <P>
+ <IMG SRC="bridge3c.png">
+ </P>
+ <P>
+ <I><B>Figure 3c.</B> Bridge/router routes packet to a
+ bridge interface (simplistic view)</I><BR>
+ </P>
+ <P>
+ This assumes that the routing decision sends the packet to
+ a bridge interface. If the routing decision sends the
+ packet to a physical network card, this is what happens:
+ </P>
+ <P>
+ <IMG SRC="bridge3d.png">
+ </P>
+ <P>
+ <I><B>Figure 3d.</B> Bridge/router routes packet to a
+ physical interface (simplistic view)</I><BR>
+ </P>
+ <P>
+ What is obviously "asymmetric" here is that the
+ <EM>iptables</EM> PREROUTING chain is traversed before the
+ <EM>ebtables</EM> INPUT chain, however this cannot be
+ helped without sacrificing other functionality. See the
+ next section.
+ </P>
+ <A NAME="section4"></A>
+ <P CLASS="section">
+ 4. DNAT'ing bridged packets
+ </P>
+ <P>
+ Take an IP packet received by the bridge. Let's assume we
+ want to do some IP DNAT on it.
+ Changing the destination address of the packet (IP address
+ and MAC address) has to happen before the bridge code
+ decides what to do with the frame/packet.
+ The decision of the bridge code can be one of these:
+ <ul>
+ <li>bridge it, if the destination MAC address is on
+ another side of the bridge;</li>
+ <li>flood it over all the forwarding bridge ports, if the
+ position of the box with the destination MAC is unknown
+ to the bridge;</li>
+ <li>pass it to the higher protocol code (the IP code),
+ if the destination MAC address is that of the bridge or of
+ one of its ports;</li>
+ <li>ignore it, if the destination MAC address is located
+ on the same side of the bridge.</li>
+ </ul>
+ </P>
+ <P>
+ So, this IP DNAT has to happen very early in the bridge
+ code. Namely before the bridge code actually does anything.
+ This is at the same place as where the <EM>ebtables</EM> nat
+ PREROUTING chain will be traversed (for the same reason).
+ This should explain the asymmetry encountered in Figures 3c
+ and 3d.
+ </P>
+ <A NAME="section5"></A>
+ <P CLASS="section">
+ 5. Chain traversal for bridged IP packets
+ </P>
+ <P>
+ A bridged packet never enters any network code above layer
+ 1 (Link layer). So, a bridged IP packet/frame will never enter the
+ IP code.
+ Therefore all <EM>iptables</EM> chains will be traversed
+ while the IP packet is in the bridge code. The chain
+ traversal will look like this:
+ </P>
+ <P>
+ <IMG SRC="bridge5.png">
+ </P>
+ <P>
+ <I><B>Figure 5.</B> Chain traversal for bridged IP
+ packets</I><BR>
+ </P>
+ <A NAME="section6"></A>
+ <P CLASS="section">
+ 6. Using a bridge port in <EM>iptables</EM> rules
+ </P>
+ <P>
+ The wish to be able to use physical devices belonging to a
+ bridge (bridge ports) in <EM>iptables</EM> rules is valid.
+ Knowing the input bridge ports is necessary to prevent
+ spoofing attacks. Say br0 has ports eth0 and eth1. If
+ <EM>iptables</EM> rules can only use br0 there's no way of
+ knowing when a box on the eth0 side changes its source IP
+ address to that of a box on the eth1 side, except by
+ looking at the MAC source address (and then still...). With
+ the br-nf patch you can use eth0 and eth1 in your
+ <EM>iptables</EM> rules and therefore catch these attempts.
+ </P>
+ <P CLASS="case">
+ 6.1. <EM>iptables</EM> wants to use the bridge destination
+ ports:
+ </P>
+ <P>
+ To make this possible the <EM>iptables</EM> chains have to
+ be traversed after the bridge code decided where the frame
+ needs to be sent (eth0, eth1, both or none). This has some
+ impact on the scheme presented in <A HREF=
+ "#section3">section 3</A> (so, we are looking at routed
+ traffic here). It actually looks like this (in the case of
+ Figure 3c):
+ </P>
+ <P>
+ <IMG SRC="bridge6a.png">
+ </P>
+ <P>
+ <I><B>Figure 6a.</B> Chain traversal when routing and br-nf
+ is compiled into the kernel</I><BR>
+ </P>
+ <DIV CLASS="note">
+ All chains are now traversed while in the bridge code.<BR>
+ This is the work of the br-nf patch. Obviously this does not
+ mean that the routed IP packets never enter the IP code. They
+ just don't pass any <EM>iptables</EM> chains while in the IP code.
+ </DIV>
+ <P>
+ If one does not compile the br-nf code into the kernel, the
+ chains will be traversed as shown below. However, then one
+ can only use br0, not eth0/eth1 to filter.
+ </P>
+ <P>
+ <IMG SRC="bridge6b.png">
+ </P>
+ <P>
+ <I><B>Figure 6b.</B> Chain traversal when routing and br-nf
+ code is not compiled into the kernel</I><BR>
+ </P>
+ <P>
+ Notice that the <EM>iptables</EM> PREROUTING chain is now in
+ the natural position in the chain list and too far to be able
+ to change the bridging decision. More precise: the <EM>iptables</EM>
+ PREROUTING chain is now traversed when the packet is already
+ in the IP code.
+ </P>
+ <P CLASS="case">
+ 6.2. IP DNAT for locally generated packets (so in the
+ <EM>iptables</EM> nat OUTPUT chain):
+ </P>
+ <P>
+ The 'normal' way locally generated packets would go through
+ the chains looks like this:
+ </P>
+ <P>
+ <IMG SRC="bridge6c.png">
+ </P>
+ <P>
+ <I><B>Figure 6c.</B> The 'normal' way for locally generated
+ packets</I><BR>
+ </P>
+ <P>
+ From <A HREF="#section6">section 6.1</A> we know that this
+ actually looks like this (due to the br-nf code):
+ </P>
+ <P>
+ <IMG SRC="bridge6d.png">
+ </P>
+ <P>
+ <I><B>Figure 6d.</B> The 'actual' way for locally generated
+ packets</I><BR>
+ </P>
+ <P>
+ Note that the <EM>iptables</EM> nat OUTPUT chain is traversed while the
+ packet is in the IP code, while the <EM>iptables</EM> filter OUTPUT chain
+ is traversed when the packet has entered the bridge code.
+ This makes it possible to do DNAT to another device in the
+ nat OUTPUT chain and lets us use the bridge ports in the
+ filter OUTPUT chain.
+ </P>
+ <P>
+ Note that in Figures 6a and 6d the <EM>iptables</EM>
+ POSTROUTING chain is traversed before the <EM>ebtables</EM>
+ POSTROUTING chain, while it's the way around for Figure 5.
+ The rule is as follows:
+ </P>
+ <DIV CLASS="note">
+ for bridged traffic the <EM>ebtables</EM> POSTROUTING chain
+ is traversed before the <EM>iptables</EM> POSTROUTING chain,
+ for all other traffic it's the way around.
+ </DIV>
+ <A NAME="section7"></A>
+ <P CLASS="section">
+ 7. Two possible ways for frames/packets to pass through the
+ <EM>iptables</EM> PREROUTING, FORWARD and POSTROUTING
+ chains
+ </P>
+ <P>
+ With the br-nf patch there are 2 ways a frame/packet can
+ pass through the 3 given <EM>iptables</EM> chains. The
+ first way is when the frame is bridged, so the
+ <EM>iptables</EM> chains are called by the bridge code. The
+ second way is when the packet is routed. So special care
+ has to be taken to distinguish between those two,
+ especially in the <EM>iptables</EM> FORWARD chain. Here's
+ an example of strange things to look out for:
+ </P>
+ <P>
+ Consider the following situation
+ </P>
+ <P>
+ <IMG SRC="bridge7a.png">
+ </P>
+ <P>
+ <I><B>Figure 7a.</B> Very basic setup.</I><BR>
+ </P>
+ <P>
+ The default gateway for 172.16.1.2 and
+ 172.16.1.4 is 172.16.1.1. 172.16.1.1 is the bridge
+ interface br0 with ports eth1 and eth2.
+ </P>
+ <P CLASS="case">
+ More details:
+ </P>
+ <P>
+ The idea is that traffic between 172.16.1.4 and 172.16.2 is
+ bridged, while the rest is routed, using masquerading.
+ </P>
+ <P>
+ <IMG SRC="bridge7b.png">
+ </P>
+ <P>
+ <I><B>Figure 7b.</B> Traffic flow for the example setup.</I><BR>
+ </P>
+ <P>
+ Here's a possible scheme to use at bootup for the bridge/router:
+ </P>
+<PRE>
+iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -d 172.16.1.0/24 -j ACCEPT
+iptables -t nat -A POSTROUTING -s 172.16.1.0/24 -j MASQUERADE
+
+brctl addbr br0
+brctl stp br0 off
+brctl addif br0 eth1
+brctl addif br0 eth2
+
+ifconfig eth1 0 0.0.0.0
+ifconfig eth2 0 0.0.0.0
+ifconfig br0 172.16.1.1 netmask 255.255.255.0 up
+
+echo '1' &gt; /proc/sys/net/ipv4/ip_forward
+</PRE>
+ <P>
+ The catch is in the first line. Because the
+ <EM>iptables</EM> code gets executed for both bridged
+ packets and routed packets we need to make a distinction
+ between the two. We don't really want the bridged frames/packets
+ to be masqueraded. If we omit the first line then
+ everything will work too, but things will happen
+ differently. Let's say 172.16.1.2 pings 172.16.1.4. The
+ bridge receives the ping request and will transmit it
+ through its eth1 port after first masquerading the IP
+ address. So the packet's source IP address will now be
+ 172.16.1.1 and 172.16.1.4 will respond to the bridge.
+ Masquerading will change the IP destination of this
+ response from 172.16.1.1 to 172.16.1.4. Everything works
+ fine. But it's better not to have this behaviour. Thus, we
+ use the first line to avoid this. Note that
+ if we would want to filter the connections to and from the
+ internet, we would certainly need the first line so we don't
+ filter the local connections as well.
+ </P>
+ <A NAME="section8"></A>
+ <P CLASS="section">
+ 8. IP DNAT in the <EM>iptables</EM> PREROUTING chain on
+ frames/packets entering on a bridge port
+ </P>
+ <P>
+ Through some groovy play it is assured that (see
+ /net/bridge/br_netfilter.c) DNAT'ed packets that after
+ DNAT'ing have the same output device as the input device
+ they came on (the logical bridge device which we like to
+ call br0) will go through the <EM>ebtables</EM> FORWARD
+ chain, not through the <EM>ebtables</EM> INPUT/OUTPUT chains. All
+ other DNAT'ed packets will be purely routed, so won't go
+ through the <EM>ebtables</EM> FORWARD chain, will go through
+ the <EM>ebtables</EM> INPUT chain and might go through the
+ <EM>ebtables</EM> OUTPUT chain.<BR>
+ </P>
+ <A NAME="section9"></A>
+ <P CLASS="section">
+ 9. Using the MAC module extension for <EM>iptables</EM>
+ </P>
+ <P>
+ The side effect explained here occurs when the br-nf code
+ is compiled in the kernel, the IP packet is routed and the
+ out device for that packet is a logical bridge device. The
+ side effect is encountered when filtering on the MAC source
+ in the <EM>iptables</EM> FORWARD chains. As should be clear
+ from earlier sections, the traversal of the
+ <EM>iptables</EM> FORWARD chains is postponed until the
+ packet is in the bridge code. This is done so we can
+ filter on the bridge port out device. This has a side
+ effect on the MAC source address, because the IP code will
+ have changed the MAC source address to the MAC address of
+ the bridge device. It is therefore impossible, in the
+ <EM>iptables</EM> FORWARD chains, to filter on the MAC
+ source address of the computer sending the packet in
+ question to the bridge/router. If you really need to filter
+ on this MAC source address, you should do it in the nat
+ PREROUTING chain. Agreed, very ugly, but making it possible
+ to filter on the real MAC source address in the FORWARD
+ chains would involve a very dirty hack and is probably not
+ worth it. This of course makes the anti-spoofing remark of
+ <A HREF="#section5">section 6</A> funny. If I'm [BDS]
+ pressured enough I could hack something up to make this
+ unpleasant side effect go away.
+ </P>
+ <HR>
+<PRE>
+Released under the GNU Free Documentation License.
+Copyright (c) 2002 Bart De Schuymer &lt;bart.de.schuymer@pandora.be&gt;,
+ Nick Fedchik &lt;nick@fedchik.org.ua&gt;.
+</PRE>
+ <BR>
+ <BR>
+ <BR>
+ <SMALL>Permission is granted to copy, distribute and/or
+ modify this document under the terms of the GNU Free
+ Documentation License, Version 1.1 or any later version
+ published by the Free Software Foundation, with no Invariant Sections,
+ with no Front-Cover Texts, and with no Back-Cover Texts. For a copy of the
+ license, see <A HREF=
+ "http://www.gnu.org/licenses/fdl.txt">"GNU Free Documentation License"</A>.</SMALL> <BR>
+ <BR>
+ <P>
+ Last updated July 9, 2002.
+ </P>
+ </BODY>
+</HTML>
+