<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
  "/usr/share/sgml/docbook/xml-dtd-4.1.2/docbookx.dtd" [
  <!ENTITY bibliography SYSTEM "iproute2tunnel-bib.xml">
  <!ENTITY ngnetscript SYSTEM "iproute2tunnel-script.xml">
]>
<article lang="en">
  <articleinfo>
    <title>Configuring tunnels with iproute2</title>
    <author>
      <firstname>Simone</firstname>
      <surname>Piunno</surname>
      <affiliation>
        <orgname>Deep Space 6</orgname>
        <address><email>simone@deepspace6.net</email></address>
      </affiliation>
    </author>
  </articleinfo>
  <sect1>
    <title>iproute2</title>
    <para>
      <command>iproute2</command> is a package for advanced network
      management under linux.  In practice, it is composed of a
      bunch of small utilities to dinamically configure the kernel
      by means of <interface>rtnetlink sockets</interface> - a modern and
      powerful interface for the configuration of the networking stack 
      implemented by <author><firstname>Alexey</firstname>
        <surname>Kuznetsov</surname></author> starting from the 
      2.2 kernel series.
    </para>
    <para>
      The most interesting feature of <command>iproute2</command> is 
      that it replaces with a single integrated and organic command all the
      functionalities we were used to find in <command>ifconfig</command>,
      <command>arp</command>, <command>route</command> and
      <command>iptunnel</command> (and it even adds some more!).
    </para>
    <para>
      Nowadays <command>iproute2</command> is installed by default on most
      major distributions, even if their initialization scripts are still built
      on commands from the old <command>net-tools</command> package (e.g.
      <command>ifconfig</command> or <command>iptunnel</command> - the latter
      is actually deprecated).  If your distribution doesn't include this
      important package, you can always download it from 
      <xref linkend="ftpsite"/> and compile it yourself.
    </para>
    <para>
      As the time of this writing, the worst defect of
      <command>iproute2</command> is a relative lack of documentation,
      partially compensated by the fact that the syntax of the
      <command>ip</command> command is very easy and similar to the english
      language.  We believe that people used to <command>ifconfig</command> and
      <command>route</command> shouldn't encounter any problem using
      <command>ip</command> and that they will feel at home in a macommander of
      hours.  In this document we will suppose that the reader has already a
      good knowledge of basic networking concepts and has used
      <command>ifconfig</command> and <command>route</command> in the past.
    </para>
  </sect1>
  <sect1>
    <title>Introduction to tunnels</title>
    <para>
      Let's imagine two Internet nodes wanting to exchange data traffic over a
      protocol different from IPv4 or directed to a private LAN using
      non-globally-valid IP addresses.  This problem is typically solved using a
      virtual point-to-point connection between the two nodes and we call this
      configuration a <emphasis>tunnel</emphasis>.
    </para>
    <para>
      You can think to every packet traveling over the network like it was an
      envelope with a few bits inside and the sender's and receiver's addresses
      written on.  Tunnels simply hide this envelope inside an additional
      one, with different sender and receiver, effectively diverting the packet's
      trip.  When the packet arrives to the external receiver (the one written on the
      external envelope), the external envelope is removed and thrown away, so that
      the packet can continue its travel to the real destinantion.
    </para>
    <para>
      The two nodes putting and removing the additional envelope are called
      <emphasis>endpoints</emphasis> and need to have a known IPv4 address.
      This is why tunnels generally don't work when traversing a network
      address translation (NAT).  Moreover, if the tunnel is built throuh a
      firewall, the latter must be configured ad hoc to permit this kind of
      traffic.
    </para>
    <para>
      A typical tunnel usage is connecting two IPv6 nodes through an IPv4-only
      network.  The two nodes can build an IPv6-in-IPv4 tunnel pretending to
      have a real direct point-to-point IPv6 connection, and this way they can
      link together two IPv6 islands (6bone works this way, a web of tunnels).
      Tunnels for IPv6-over-IPv4 transport come in two different flawors:
      automatic <xref linkend="RFC2373"/> and manually
      configured.  In this document we will talk only of the latter type.
    </para>
  </sect1>
  <sect1>
    <title>Creating tunnels</title>
    <para>
      Creating tunnels with <command>iproute2</command> is very easy.  First of
      all you need a name for your tunnel.  If you choose to name it
      <interface>foo</interface> then you can create the tunnel with the
      command:
    </para>
    <programlisting>ip tunnel add foo mode sit remote 192.168.1.42</programlisting>
    <para>
      This way, you created a sit (IPv6-in-IPv4) tunnel with a remote endpoint 
      at the IP address 192.168.1.42.  Notice that we have not specified which 
      IP address to use for the local side of the tunnel, which interface, and so on.  
      The result can be viewed with the command <command>ip tunnel show</command>:
    </para>
    <programlisting><![CDATA[
# ip tunnel show 
sit0: ipv6/ip  remote any  local any  ttl 64  nopmtudisc
foo: ipv6/ip  remote 192.168.1.42  local any  ttl inherit
    ]]></programlisting>
    <para>
      Our tunnel is the one in the 2nd row.  Now we can also ask a list 
      of all available interfaces, regardless if they are real network 
      adapters or software simulations:
    </para>
    <programlisting><![CDATA[
# ip link show
1: lo: <loopback,up> mtu 16436 qdisc noqueue 
  link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <broadcast,multicast,up> mtu 1500 qdisc pfifo_fast qlen 100
  link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
4: sit0@none: <noarp> mtu 1480 qdisc noop 
  link/sit 0.0.0.0 brd 0.0.0.0
6: foo@none: <pointopoint,noarp> mtu 1480 qdisc noop 
  link/sit 0.0.0.0 peer 192.168.1.42
    ]]></programlisting>
    <para>
      The fact that should get your attention is that while
      <interface>lo</interface> and <interface>eth0</interface> are marked as
      being <option>up</option>, our tunnel is not.  To double check, the good
      old <command>ifconfig</command> says only:
    </para>
    <programlisting><![CDATA[
# ifconfig
eth0    Link encap:Ethernet  HWaddr 00:48:54:1b:25:30  
        inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
        inet6 addr: fe80::248:54ff:fe1b:2530/10 Scope:Link
        UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
        RX packets:0 errors:0 dropped:0 overruns:0 frame:0
        TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:100 
        RX bytes:0 (0.0 b)  TX bytes:528 (528.0 b)
        Interrupt:9 Base address:0x5000 

lo      Link Encap:Local Loopback  
        inet addr:127.0.0.1  Mask:255.0.0.0
        inet6 addr: ::1/128 scope:host
        UP LOOPBACK RUNNING  MTU:16436  Metric:1
        RX packets:35402 errors:0 dropped:0 overruns:0 frame:0
        TX packets:35402 errors:0 dropped:0 overruns:0 carrier:0
        collisions:0 txqueuelen:0 
        RX bytes:3433996 (3.2 mb)  TX bytes:3433996 (3.2 mb)          
    ]]></programlisting>

    <para>
      So we must remember that the <command>ip link</command> command shows all
      available interfaces, regardless of them being activated or not.  To
      activate <interface>foo</interface>, we use the command:
    </para>
    <programlisting>ip link set foo up</programlisting>
    <para>
      and to deactivate it:
    </para>
    <programlisting>ip link set foo down</programlisting>
    <para>
      To completely discard our tunnel we use:
    </para>
    <programlisting>ip tunnel del foo</programlisting>
  </sect1>
  <sect1>
    <title>Special tunnels</title>
    <para>
      In the previous paragraph, we've seen how to build an IPv6-in-IPv4 tunnel, 
      now we'll examine a few different situations.
    </para>
    <sect2>
      <title>GRE tunnels</title>
      <para>
        If you don't need IPv6 but for example you want to carry normal 
        IPv4 traffic through a non-cooperating transit network, then you'd
        better use <parameter>mode gre</parameter> instead of 
        <parameter>mode sit</parameter>.
        For example:
      </para>
      <programlisting><![CDATA[
# ip tunnel add foo4 mode gre remote 192.168.1.42
# ip tunnel show
gre0: gre/ip  remote any  local any  ttl inherit  nopmtudisc
foo4: gre/ip  remote 192.168.1.42  local any  ttl inherit
# ip link show
1: lo: <loopback,up> mtu 16436 qdisc noqueue 
  link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <broadcast,multicast,up> mtu 1500 qdisc pfifo_fast qlen 100
  link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
7: gre0@none: <noarp> mtu 1476 qdisc noop 
  link/gre 0.0.0.0 brd 0.0.0.0
9: foo4@none: <pointopoint,noarp> mtu 1476 qdisc noop 
  link/gre 0.0.0.0 peer 192.168.1.42
      ]]></programlisting>
      <para>
        GRE <xref linkend="GRE"/> is a particular tunnelling protocol
        supported by Cisco routers which is capable to carry different
        protocols over IPv4.  
        There's another kind of tunnels implemented by linux: 
        <option>ipip</option>.  The latter is also useful for IPv4-in-IPv4 
        encapsulation, but it's implemented only by linux and does only 
        unicast IP over IP (so you can't transport for example IPX or 
        broadcasts).  In general, GRE is better.
      </para>
    </sect2>
    <sect2>
      <title>Explicit local endpoint</title>
      <para>
        Even if the kernel is smart enough to choose for you, it could 
        be a good idea to explicitly force the local IP address and interface 
        we're going to use for tunneling.  To do that, we can use the  
        <parameter>local</parameter> and <parameter>dev</parameter> parameters:
      </para>
      <programlisting><![CDATA[
# ip tunnel add foo mode sit local 192.168.0.1 remote 192.168.1.42 dev eth0
# ip tunnel show
sit0: ipv6/ip  remote any  local any  ttl 64  nopmtudisc
foo: ipv6/ip  remote 192.168.1.42  local 192.168.0.1  dev eth0  ttl inherit 
# ip link show
1: lo: <loopback,up> mtu 16436 qdisc noqueue 
 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <broadcast,multicast,up> mtu 1500 qdisc pfifo_fast qlen 100
 link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
4: sit0@none: <noarp> mtu 1480 qdisc noop 
 link/sit 0.0.0.0 brd 0.0.0.0
11: foo@eth0: <pointopoint,noarp> mtu 1480 qdisc noop 
 link/sit 192.168.0.1 peer 192.168.1.42
      ]]></programlisting>
      <para>
        Please notice that now the interface is labeled as
        <interface>foo@eth0</interface>, to remind us where the tunnel has been
        explicitly connected.
      </para>
    </sect2>
    <sect2>
      <title>Time-to-live</title>
      <para>
        When using tunnels, creating accidental loops in the network it's easy.
        To limit the problem, it's fundamental to generate packets with a low
        TTL value. Initial TTL can be specified by the
        <parameter>ttl</parameter> parameter in <command>ip tunnel
          add</command>. The default value is inherited from the network
        interface the tunnel is associated to. <xref linkend="IANA"/> 
        suggests using 64 for TTL.
      </para>
    </sect2>
  </sect1>
  <sect1>
    <title>Assigning an IP address to the interface</title>
    <para>
      Like any other network interface, tunnels can have one or
      more addresses assigned to them.
    </para> 
    <sect2>
      <title>Main address</title>
      <para>
        Assigning the main address is straightforward:
      </para>
      <programlisting><![CDATA[
ip addr add 3ffe:9001:210:3::42/64 dev foo  
ip addr add 192.168.0.2/24 dev foo4
ip addr add 10.20.30.40/8 dev eth0
      ]]></programlisting>
      <para>
        The number immediately following the slash is to suggest to the 
        kernel the network prefix we prefer, useful to automatically compute 
        broadcast address and netmask on IPv4 LANs (this is called CIDR 
        notation). However, tunnels are point-to-point interfaces and this 
        number is then ignored.
      </para>
      <para>
        Note: to be able to assign an IP address to an interface, first 
        you need to activate the interface using:
      </para>
      <programlisting>ip link set interfacename up</programlisting>
      <para>
        To remove an address from an interface, you can obviously use 
        <command>del</command> instead of <command>add</command>:
      </para>
      <programlisting><![CDATA[
ip addr del 3ffe:9001:210:3::42/64 dev foo
ip addr del 192.168.0.2/24 dev foo4
      ]]></programlisting>
	    <para>
        We can even ask for a list of all the IP addresses in use on our server:
      </para>
      <programlisting><![CDATA[
# ip addr show
1: lo: <LOOPBACK,UP> mtu 16436 qdisc noqueue 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
    inet6 ::1/128 scope host 
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
    link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::248:54ff:fe1b:2530/10 scope link 
4: sit0@NONE: <NOARP> mtu 1480 qdisc noop 
    link/sit 0.0.0.0 brd 0.0.0.0
5: foo@NONE: <POINTOPOINT,NOARP> mtu 1480 qdisc noop 
    link/sit 0.0.0.0 peer 192.168.1.42
    inet6 3ffe:9001:210:3::42/64 scope global 
    inet6 fe80::c0a8:1/10 scope link 
      ]]></programlisting>
    </sect2>
    <sect2>
      <title>Aliasing</title>
      <para>
        When using multiple addresses on a single interface, people used to
        <command>ifconfig</command> will be surprised noting that multiple
        <command>ip addr add</command> commands do not generate fictitious
        interfaces like <interface>eth0:1</interface>,
        <interface>eth0:2</interface> and so on.  This is a legacy naming
        scheme coming from the 2.0 kernel version and nowadays no more
        mandated.  For example:
      </para>
      <programlisting><![CDATA[
# ip addr add 192.168.0.11/24 dev eth0
# ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
    link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
    inet 192.168.0.11/24 scope global secondary eth0
    inet6 fe80::248:54ff:fe1b:2530/10 scope link 
# ifconfig     
eth0      Link encap:Ethernet  HWaddr 00:48:54:1B:25:30  
          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::248:54ff:fe1b:2530/10 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:0 (0.0 b)  TX bytes:528 (528.0 b)
          Interrupt:9 Base address:0x5000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:34732 errors:0 dropped:0 overruns:0 frame:0
          TX packets:34732 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:3386912 (3.2 Mb)  TX bytes:3386912 (3.2 Mb)

foo       Link encap:IPv6-in-IPv4  
          inet6 addr: 3ffe:9001:210:3::42/64 Scope:Global
          inet6 addr: fe80::c0a8:1/10 Scope:Link
          UP POINTOPOINT RUNNING NOARP  MTU:1480  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
      ]]></programlisting>
	    <para>
        Our addictional IP address is reported by <command>ip addr show</command> 
	      and works, but <command>ifconfig</command> doesn't even know of its existence!  
        To solve the problem we can use the <parameter>label</parameter> parameter:
      </para>
      <programlisting><![CDATA[
# ip addr add 192.168.0.11/24 label eth0:1 dev eth0
# ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast qlen 100
    link/ether 00:48:54:1b:25:30 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.1/24 brd 192.168.0.255 scope global eth0
    inet 192.168.0.11/24 scope global secondary eth0:1
    inet6 fe80::248:54ff:fe1b:2530/10 scope link 
# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:48:54:1B:25:30  
          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::248:54ff:fe1b:2530/10 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:100 
          RX bytes:0 (0.0 b)  TX bytes:528 (528.0 b)
          Interrupt:9 Base address:0x5000 

eth0:1    Link encap:Ethernet  HWaddr 00:48:54:1B:25:30  
          inet addr:192.168.0.11  Bcast:0.0.0.0  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:9 Base address:0x5000 
      ]]></programlisting>
      <para>
        Notice that we can choose any arbitrary string as the label.  
	      We're not forced to use the 2.0 naming scheme; we must comply 
	      to it only if we care having backward compatibility with 
        <command>ifconfig</command>.
      </para>
    </sect2>
    <sect2>
      <title>Which IP for the tunnel</title>
	    <para>
        Choosing a global/public IP address (respectively an IPv6
	      address for SIT/IPv6-in-IPv4 tunnels and an IPv4 address for
	      GRE/IPv4-in-IPv4 tunnels) for the local endpoint of the 
	      tunnel is probably the best thing we can do when our computer 
	      is a single host and not a router providing IPv6 connectivity 
	      to a whole LAN.
      </para>
      <para>
        Instead, if we're configuring a router, we'd better use  
	      a link-local address for SIT/IPv6-in-IPv4 tunnels (in IPv6 
	      link-local addresses are assigned automatically by means of
	      stateless address autoconfiguration or manually configured) 
	      and a private address for GRE/IPv4-in-IPv4 tunnels (IPv4 has 
	      no link-local addresses). The valid address will then be 
	      only on eth0 (or the interface on the LAN side).  
	      Notice that in this configuration you need to activate 
        forwarding among interfaces, using these commands:
      </para>
      <programlisting><![CDATA[
sysctl -w net.ipv4.conf.all.forwarding=1  # for GRE (IPv4-in-IPv4)
sysctl -w net.ipv6.conf.all.forwarding=1  # for SIT (IPv6-in-IPv4)
      ]]></programlisting>
	    <para>
        For IPv4 you can even decide to enable forwarding only between a 
        couple of interfaces, in this case you could use these commands:
      </para>
      <programlisting><![CDATA[
sysctl -w net.ipv4.conf.eth0.forwarding=1
sysctl -w net.ipv4.conf.pippo.forwarding=1
      ]]></programlisting>
      <warning>
        <para>
          meaning of this switch is different for IPv6 and doesn't work as
          expected, see kernel documentation for more information.
        </para>
      </warning>
    </sect2>
  </sect1>

  <sect1>
    <title>Routing</title>
    <para>
      Now that our tunnel is configured, we have to specify which traffic 
      will be directed through it.  For IPv6 the most common choice is the 
      following:
    </para>
    <programlisting>ip route add 2000::/3 dev foo</programlisting>
    <para>
      This way all IPv6 traffic going to addresses starting with 3 bits 
      equal to 001 (that is, all global unicast IPv6 address space) will be 
      directed to the <interface>foo</interface> interface.  This is only one
      8th of the available IPv6 address space, but you are guaranteed that
      every possible remote host will be in this range.
    </para>
    <para>
      We can see the IPv4 routing table this way:
    </para>
    <programlisting><![CDATA[
# ip route
192.168.0.0/24 dev eth0  scope link 
127.0.0.0/8 dev lo  scope link 
    ]]></programlisting>
    <para>
      and the IPv6 routing table this way:
    </para>
    <programlisting><![CDATA[
# ip -6 route
2000::/3 dev foo  proto kernel  metric 256  mtu 1480 advmss 1420
fe80::/10 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440
fe80::/10 dev foo  proto kernel  metric 256  mtu 1480 advmss 1420
ff00::/8 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440
ff00::/8 dev foo  proto kernel  metric 256  mtu 1480 advmss 1420
default dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440
unreachable default dev lo  metric -1  error -101
    ]]></programlisting>
    <para>
      If you need to specify a gateway (this is not for tunnels) then 
      you can add the <parameter>via</parameter> parameter, for example:
    </para>
    <programlisting>ip route add 192.168.1.0/24 via 192.168.0.254 dev eth0</programlisting>
    <para>
      To remove a route you can obviously use <command>ip route del</command> 
      but be careful: if you write <command>ip route del default</command> you're 
      removing the default IPv4 route, not the IPv6 one!  To remove the IPv6 
      default destination you need to use <command>ip -6 route del default</command>.
    </para>
  </sect1>
  <sect1>
    <title>Practical applications</title>
    <sect2>
      <title>A complete example</title>
      <para>
        This is a typical IPv6 tunnel for 6bone:
      </para>
      <programlisting><![CDATA[
ip tunnel add $TUNNEL mode sit local any remote $V4_REMOTEADDR ttl 64
ip link   set $TUNNEL up
ip addr   add $V6_LOCALADDR dev $TUNNEL
ip route  add 2000::/3      dev $TUNNEL
      ]]></programlisting>
      <para>
        where <parameter>$TUNNEL</parameter> is an arbitrary name assigned to
        the tunnel, <parameter>$V4_REMOTEADDR</parameter> is the IPv4 address
        of the remote end of the tunnel and
        <parameter>$V6_LOCALADDR</parameter> is the IPv6 local address
        assigned to our host. We've used the <option>any</option> value for
        the <parameter>local</parameter> endpoint address because this way we
        can handle a dynamic IPv4 address (e.g. assigned by a dialup
        connection to the ISP).  Obviously we need to inform our tunnel
        broker when our address changes but this is out of the scope of this
        writing, also because there's no general standard procedure.
      </para>
      <para>
        To shut down the tunnel:
      </para>
      <programlisting>ip tunnel del $TUNNEL</programlisting>
      <para>
        also automatically removes the routing entry and the address.
      </para>
    </sect2>
    <sect2>
      <title>Comfort</title>
      <para>
        Now, after we made sure everything works, we can use previous commands
        in a script called <filename>ip-up.local</filename> and saved in 
        <filename>/etc/ppp/</filename>.  This way, those commands will be
        automatically executed <emphasis>everytime we connect PPP</emphasis>.
        If we wanted to also automatically delete the tunnel upon PPP
        disconnection, we can create another script in the same directory,
        and call it <filename>ip-down.local</filename>.
      </para>
      <para>
        As an example, if our tunnel broker is <xref linkend="NGNET"/>, we
        could use this script as <filename>ip-up.local</filename>:
      </para>
      &ngnetscript;
      <para>
        <filename>ip-down.local</filename> could be:
      </para>
      <programlisting><![CDATA[
#!/bin/bash
/sbin/ip tunnel del ngnet
      ]]></programlisting>
    </sect2>
  </sect1>
  <sect1>
    <title>Thanks</title>
    <para>
      Thank to Giacomo Piva for pppd and NGNET integration idea.
    </para>
  </sect1>
  <bibliography>
    <title>References</title>
    <para>
      Here are some useful links:
    </para>
    &bibliography;
  </bibliography>
</article>
<!--
vim: et ts=2 sw=2
-->
