This file, INSTALL, is a -*- text -*- file tutorial on how to
 * install userv ipif and udptunnel,
 * configure them to create a VPN tunnel between two hosts or
   networks, or
 * use udptunnel-reconf to create a multi-site VPN.
 

See README for details of other available documentation.


BUILD AND INSTALLATION INSTRUCTIONS
-----------------------------------

1. Install userv, 1.0.1 or later.  This is in Debian GNU/Linux.

2. Make sure your Linux kernel has SLIP and TUN compiled in.

3. udptunnel works best if your ssh can do ssh-protocol-level
   keepalives.  Currently these are only supported by using a special
   patch, which can be found (for various OpenSSH versions) at
   ftp.chiark.greenend.org.uk:/users/ian/openssh+protocolkeepalives.
   Pre-compiled Debian packages are available there too.

4. Obtain a fresh copy of userv-utils, if you haven't already.
   cd to ipif, and run `make' and (as root) `make install'.

 After you have done this the software will still not do anything, and
 by default userv ipif will not allow anyone (except root) to create
 network interfaces.

 The software will probably only work on Linux - in particular, userv
 ipif's service program (service.c) uses Linux-specific ways of
 setting up SLIP interfaces.  It might be possible in principle to
 create alternatives for other platforms.



UDPTUNNEL SETUP TUTORIAL
------------------------


1. BACKGROUND INFORMATION

 Firstly, note that userv ipif and udptunnel are extremely flexible,
 as they aim to be `Lego brick' networking components.  Many much more
 interesting configurations can be constructed than there is room to
 document here.  If you want to do something strange, consult the
 README to locate the appropriate reference documentation.

1.1. About udptunnel

 udptunnel is point-to-point; you need a separate `invocation' for
 each pair of machines (or networks) you wish to connect.

 It is `one-shot': it will set up a tunnel and keep it going as long
 as it can, and then exit; if you want a permanent tunnel you must
 arrange to reinvoke udptunnel.

 It is asymmetric, in that one of the endpoints starts the tunnel, and
 the other sits and waits to be contacted.  We'll call the active
 endpoint `alice' and the passive endpoint `bob'.  Usually alice
 invokes udptunnel on bob via OpenSSH (`ssh').

 udptunnel does not need root privilege to run.  However, you do need
 to configure userv ipif to know that the user who will be running
 udptunnel is permitted to use the IP addresses and network ranges
 which will be used.  So, though most of the configuration can be done
 as the normal users who will run udptunnel on each end, a small
 amount (editing /etc/userv/ipif-networks) needs to be done as root on
 each end - and the information configured as root needs to match up

 This tutorial will explain how to do these things.

1.2. About point-to-point tunnelling in general

 A tunnel is an _additional_ (in the case of udptunnel, encrypted)
 network link between a pair of machines.  Packets are encapsulated at
 one end, sent over the real network between them, and decoded again
 at the other end.  As with any network connection, it is possible to
 arrange for networks behind the endpoint machines to be able to
 communicate via the tunnel.

 Each endpoint machine will have at least two network interfaces:
 Firstly, the real `physical' interface through which the encapsulated
 packets will be really sent and received.  Secondly, the `virtual'
 interface created by the tunnelling software, which represents its
 end of the (encrypted) tunnel link.  The physical and virtual
 interfaces MUST have different addresses.

 Each endpoint machine may also have additional network interfaces;
 for example, it may be the router for a network which sits behind it,
 which an interface on that network, or it may be the endpoint for
 more than one tunnel.  It is OK for several tunnels terminating at
 the same machine to use the same virtual address (provided that the
 tunnels are not `layered' on top of each other but are `in
 parallel'), and it is also OK to use as the virtual tunnel address a
 router's address on a private network which will be sent via the
 tunnel.

1.3. Diagram

     ____        ______________               ______________        ____
  __(    )__    |ALICE         |             |           BOB|    __(    )__
,'  `   '   `.  |        _     |  Tunnel     |     _        |  ,'  `   '   `.
|   alice    |  |       |\\ ,- - - - - - - - - -. //|       |  |    bob     |
`._private _.'  |       | ||   |             |   || |       |  `._private _.'
|  networks  |==+--------'||   |  Public     |   ||`--------+==|  networks  |
|            |  |      alice   |  Network    |   bob        |  |            |
`.~       ~.'   |     virtual  +=============+  virtual     |  `.~       ~.'
  (__,'`.__)    |______________|alice     bob|______________|    (__,'`.__)
                              physical  physical
                                                             _
 Key:  HOSTNAME                 +===+ Actual Network        |\\ Tunnel
       Descriptive Text         ----- Data Flow             | ||Endpoint
       host or network number   - - - Encrypted Data Flow     ||


2. INFORMATION COLLECTION AND PRELIMINARY SETUP

 You will need to collect and/or decide upon various information, and
 make sure that your two endpoint systems can talk to each other over
 the public network.

2.1. Find out, or choose, private network numbers

 You need to make sure you know what all of the addresses in the above
 diagram are going to be.

 Usually you must choose the private and virtual addresses yourself:
 hosts on the private networks usually won't communicate with the
 global Internet other than through proxies or masquerading firewalls.

 You MUST choose from the reserved ranges in RFC1918, which are:
    172.16.0.0/12   192.168.0.0/16   10.0.0.0/8
 If you do not do so you'll end up reusing someone else's addresses,
 which can cause lots of hard-to-diagnose and embarrasing problems.

 You should CHOOSE RANDOMLY !  This makes sure that when you decide to
 connect your VPN to someone else's VPN, your network allocation
 numbers are unlikely to clash.  If you both choose 192.168.0.0/24
 you'll have to renumber (and will look like fools).

 To help with choosing random network numbers from RFC1918 space, the
 author maintains a web page at <http://www.ucam.org/cam-grin/>, which
 can pick network numbers for you.

 Additionally, there is a database there - people in Cambridge (in
 England) are encouraged to register their network address usage
 there.  Please do not register in the database unless you're likely
 to want to connect your VPN to others already listed.

2.2. Find out, or choose, public network numbers

 These are usually specified by your ISP, either statically or
 dynamically assigned.  If the active end (`alice physical') is
 dynamically assigned you can use the `Wait' option (see below) to
 avoid specifying it, but otherwise you will need to have some kind of
 script to find it each time you invoke udptunnel, or use a hostname
 which automatically tracks the source host using dynamic DNS.

 In some situations you may find yourself using a `public network'
 which is not actually the public Internet - for example, you may want
 to run one tunnel `through' another, or your `public network' is
 actually a `private', but not sufficiently secure, radio LAN.  In
 this case you'll have to choose the addresses to use from
 RFC1918-space, as above.

2.3. Decide which user account(s) on alice and bob you will use

 These user accounts will see the plaintext for all network packets
 going over the tunnel and if compromised will be able steal or forge
 tunnel traffic.  So, they should be reasonably secure.

 Let us assume that the account on alice is called Tbob, and the
 account on bob is called Talice.  (NB that your system may not
 correctly handle usernames containing uppercase.)

 Each account should be in a group of its own, which will be used for
 the userv ipif access control.

 Arrange that Tbob@alice can ssh to Talice@bob without needing a
 passphrase or other user interaction.

 (Obviously, if you need to create accounts, edit groups, or change
 the sshd configuratioon, you may need to be root.)

2.4. Decide whether to use `udptunnel-reconf'

 There are two ways to set up a tunnel with udptunnel.  Either you can
 simply give udptunnel the right command, by putting it in an
 appropriate script and arranging it to be called, or you can have a
 program `udptunnel-reconf' read some configuration files and do it
 for you.

 udptunnel-reconf is not as well documented, but its behaviour is
 somewhat more `cooked'.  It is especially useful if you need to
 maintain many tunnels as part of an organised, multi-site, VPN.

 Using udptunnel directly is somewhat more flexible, and may be easier
 if you only want one tunnel.


3. SETUP INSTRUCTIONS - USING UDPTUNNEL-RECONF

 Edit or create the following files, as root:
   /etc/userv/vpn/sites
   /etc/userv/vpn/tunnels
   /etc/userv/vpn/global

 Run udptunnel-reconf, as root.  This will create:
   /var/lib/userv/vpn/passive-sites
   /var/lib/userv/vpn/active-sites
   /var/lib/userv/vpn/command.<site>

 It will also spit out to stdout two things: firstly, a list of
 suggested commands to put in your inittab, and secondly a suggested
 line to put in your /etc/userv/ipif-networks.

 Test that your setup is working, by running (one of) the
 /var/lib/userv/vpn/command.<site> file(s) by hand - see section 5.
 If it works, you can put the relevant things in your inittab and say
 `init q'.

 To find out what all the configuration settings do, look at
 /usr/local/share/userv/udptunnel-vpn-defaults, which contains the
 default settings and shows where all the hooks are.  Consult section
 4 of this file to understand what the options to udptunnel do.


4. SETUP INSTRUCTIONS - INVOKING UDPTUNNEL DIRECTLY

 All of these steps can be done using the appropriate normal user
 accounts, unless otherwise indicated.

4.1. Configure the private network numbers in /etc/userv/ipif-networks

 (This step needs to be done as root.)

 On alice, in /etc/userv/ipif-networks, put
  <Tbob-gid>,=<alice-virt-addr>/32,     <Tbob-group>,   <comment>
  <Tbob-gid>,<bob-virt-addr>/32,        <Tbob-group>,   <comment>
 and for each of bob's private networks
  <Tbob-gid>,<network>/<prefix-len>,    <Tbob-group>,   <comment>
 You can leave out the <bob-virt-addr>/32 line if bob's virtual
 address is in one of bob's private networks.

 On bob, do the corresponding.  In /etc/userv/ipif-networks, put
  <Talice-gid>,=<bob-virt-addr>/32,     <Talice-group>, <comment>
  <Talice-gid>,<alice-virt-addr>/32,    <Talice-group>, <comment>
 and for each of alice's private networks
  <Talice-gid>,<network>/<prefix-len>,  <Talice-group>, <comment>
 Again, you can leave out <alice-virt-addr> if one of the virtual
 networks covers it.

 All the specifications in /etc/userv/ipif-networks must be numerical
 addresses - hostnames are not allowed.  Also, the /32 indicating a
 specific host cannot be omitted.

 Note the use of `=' for each host's own virtual address, which
 indicates to userv ipif that it's OK for that gid to create a local
 interface with that address, but the address may not be assigned to a
 remote host or route.

4.2. Construct the udptunnel invocation (on alice)

 udptunnel has a long and complicated command line, rather than a
 configuration file.  The best way to deal with this is to create a
 shell script which runs udptunnel with the right options.  This
 script will live on alice in ~Tbob, and be run by Tbob.  Let us call
 it `udptunnel-invoke-bob'.

 For the most basic setup, it should look something like this:

  #!/bin/sh
  set -e
  set -x

  udptunnel                                                      \
          -e nonce -e timestamp/10/30                            \
          -e pkcs5/8 -e blowfish-cbcmac/128 -e blowfish-cbc/128  \
          <alice-physical-hostname>,Any                          \
          <bob-physical-hostname>,Command                        \
          <alice-virtual>,<bob-virtual>,1000,cslip               \
          30,130,1800                                            \
          <bob-private-nets> <alice-private-nets>                \
          ssh     -o 'BatchMode yes'                             \
                  -v <Talice>@<bob-physical-hostname>            \
                  udptunnel

 You have to fill in the right values for things in angle brackets.
 (See also section 6. for a moderately complex example, below.)

4.4.1. Syntax of <alice-private-nets> and <bob-private-nets>

 These arguments to udptunnel are the network address ranges at each
 end which are to be connected via the tunnel.  Let us consider just
 <alice-private-nets>; <bob-private-nets> is just the same, but for
 bob's end.

 <alice-private-nets> is a comma-separated list of networks specified
 as <network>/<prefix-len>.  The network address must be numerical,
 and the prefix length must always be specified.

 If there are no private networks `behind' alice, ie the tunnel is
 just to connect alice to bob and things at bob's end, then specify
 `-' for <alice-private-nets>.

4.4.2. IP masquerading (NAT) at alice's end

 If alice is behind a masquerading (NAT) firewall, you can still get
 it to work.  You need to add an option `-m' before the other
 arguments.  This will make udptunnel on alice tell udptunnel on bob
 to wait for alice's first encapsulated packet before deciding what
 alice's physcial address and port number are, as seen by bob.  That
 way alice doesn't need to know what port number the NAT proxy will
 use.

4.4.3. Using fixed UDP port numbers (eg to make firewally happy)

 If alice is behind a firewall which will not allow incoming UDP to
 arbitrary ports, even when sent in reply to packets of alice's, you
 have to arrange for alice to use a fixed port number.  Change
          <alice-physical-hostname>,Any                         \
 to
          <alice-physical-hostname>,<alice-physical-port>       \

 udptunnel will need to be able to bind to the relevant port, so you
 must either (i) choose a port number over 1024, which risks other
 processes on alice accidentally using that port, (ii) run udptunnel
 as root on alice, or (iii) use authbind (authbind is a utility,
 included in Debian, which can allow non-root programs to bind to low
 ports in a controlled way).

 If bob is behind such a firewall too, you can replace
          <bob-physical-hostname>,Command                       \
 with
          <bob-physical-hostname>,<bob-physical-port>           \

4.4.4. Clock skew and excessive delay

 The default configuration given above, which includes this
          -e nonce -e timestamp/10/30                            \
 will not work if there is more than 10s of clock skew between alice
 and bob's system clocks, or if the lag in either direction is more
 than 30s.  It is best if your systems run with synchronised clocks
 (you can run NTP over the tunnel if necessary) and don't have such
 bad lag, of course.

 However, you can increase these parameters if you really want.  To
 increase the tolerance to clock skew to some amount, make sure that
 both numbers are at least the amount of clock skew you're willing to
 tolerate.  To increase the tolerance to delay it's only necessary to
 increase the second number.

 Warning: if you increase these numbers too much there is a risk that
 packets delayed or repeated by an attacker will be treated as genuine
 and cause communication or security problems.  I would not recommend
 using a value more than 120 (2 minutes).

 If you really can't get reasonable clock synch at all, you can use
 sequence number replay detection instead of clock-based replay
 detection.  Replace
          -e nonce -e timestamp/10/30                            \
 with
          -e sequence                                            \

4.4.5. Other things to tweak (it's usually safe to ignore this part)

 Do not mess with the `-e' parameters and arguments except as
 explained above, unless you are a cryptographer.

 30,130,1800 are timeouts which control the `dead tunnel detection'.
 The first is the keepalive interval: when one end hasn't sent
 anything for that many seconds, it will send an empty keepalive
 packet.  The second is the dead tunnel timeout: when one end hasn't
 received anything for that many seconds, it assumes the tunnel is
 dead and dies (the other end will then usually die shortly if it
 hasn't already).  The third is the status reporting interval - at
 intervals of that many seconds each end will report (to udptunnel's
 stdout) that the tunnel is still open and give some statistics; these
 diagnostics also prevent the controlling ssh connection's entry in
 masquerading and firewall tables from timing out.

 1000 (in ...,...,1000,cslip) is the MTU - the maximum size of packet
 which will be sent through the tunnel.  It is best if this number is
 a certain amount smaller than the path MTU over the physical network,
 so that encapsulated packets do not get fragmented.  (Each packet
 will be increased in size by 24 bytes + the size of a UDP and IP
 header + the effects of SLIP duplication of certain bytes.)

4.5. Testing your script

 After you've written your script, you should run it to see if it
 works.  See section 5 for details.

4.6. Configure the tunnel to run automatically

 Now that the tunnel works if you invoke it by hand, it is time to
 arrange to run it automatically.

 If you want the tunnel to run over a dialup link only when the dialup
 link is up, then I'm afraid you'll have to arrange to start and kill
 it yourself, probably.  I haven't set up such a configuration.  More
 information about this for this document, if you manage to do it,
 would be good.

 So, I shall assume that you want the tunnel to be up all of the time
 (or at least, as much as possible).  The best way to do this is to
 run it from `init', by setting it up in inittab.

 For example, you could put something like this in your inittab:
  t0:23:respawn:su Tbob -c ./udptunnel-invoke-bob 2>&1 | logger -p local2.info -t tunnel-bob
 (Note that if you have more than one tunnel the `id' field, at the
 start of the inittab line, must be different for each one.)

 This would use `su' to become bob and run the actual tunnelling
 software, and arrange for the diagnostic output to be sent to syslog
 with facility `local2' and priority `info', tagged with `tunnel-bob'.
 With an appropriate line in /etc/syslog.conf, such as
  local2.*                              /var/log/local2-all.log
 (remember that you have to use tabs in syslog.conf) this will
 produce, in /var/log/local2-all.log, all the diagnostics, including
 reassuring messages like this:
  Sep 18 00:27:48 alice tunnel-bob: udptunnel-forwarder: alice: tunnel still open: received 5262 packets, 5262 bytes
  Sep 18 00:28:44 alice tunnel-bob: udptunnel-forwarder: bob: tunnel still open: received 5280 packets, 5280 bytes


5. TESTING YOUR UDPTUNNEL INVOCATION SCRIPT

5.1. Invocation

 Log into alice as Tbob, and run ./udptunnel-invoke-bob.
 A great deal of diagnostic output will ensue.

 If all is well you will see two messages looking something like this
  udptunnel-forwarder: bob: tunnel open with peer 127.0.0.3:76543
  udptunnel-forwarder: alice: tunnel open
 and the session will just sit there.  This means it thinks it's
 working; go on to section 5.2.

 If it didn't say that, here are some debugging tips:

 * If it just sits there for a minute or two and then udptunnel times
 out, the physical packets aren't getting back and forth.  Use
 tcpdump, check your firewall and routing (as below), and consult the
 sections above about NAT and firewalls.

 * If it bombed out, look for an error message in the diagnostics.
 There will be lots of `subprocess somethingorother exited with
 nonzero exit status 47', `no details received from remote' and the
 like, but these are probably not the ones you want to look at,
 because they're usually just consequences of some other failure.

  Permission denied.
  udptunnel - alice: fatal error: remote command failed (code ...)
    Tbob had trouble ssh'ing to Talice@bob.  Check that the ssh
    configuration is set up, and test it separately.

  userv-ipif service: access denied for ...., ....
  udptunnel - alice: subprocess local command failed with code 2048
    The arguments to udptunnel don't correspond to
    /etc/userv/ipif-networks on alice.  Either the arguments to
    udptunnel or the ipif-networks file is wrong.  (Or, if the message
    about `local command failed' mentions bob, look on bob.)

  udptunnel - alice: subprocess forwarder failed with code 14
    The tunnel timed out - no packets were successfully received for
    130 seconds.  See 2.4.5 above for details of the timeout
    parameters.  (NB, applies to `code 14' only.)

  usage errors from udptunnel or ssh, or sh: ...: unknown command
    Perhaps you dropped a \ from the udptunnel-invoke-bob script ?

  udptunnel not found, udptunnel-forwarder not found
    Check that the PATH includes /usr/local/bin.  Noninteractive `ssh'
    invocations (ie, ones with a command specified) often have a
    different PATH.

 * Other messages:

  udptunnel-forwarder: alice: bad packet: blowfish-cbcmac: verify failed
    This can be caused by actual packet corruption on the physical
    network (or even by an actual hostile attack), but when using
    fixed port numbers these messages are common after the tunnel has
    died and been restarted: they correspond to packets from the
    previous invocation (which is usung different keys) being rejected
    because their checksums don't match.  In this case they should go
    away in a minute or two.

5.2. Testing, once the tunnel claims to be working

 In another session on alice, you should be able to ping bob's virtual
 interface.  If this works, test pinging between hosts on the private
 networks behind alice and bob.  If all is well, go onto step 4.

 If not, here are some troubleshooting hints:

 * Use numerical addresses when testing.  This eliminates DNS problems
 from your test strategy.

 * Use `ifconfig' and `route -n' on alice and bob to check that the
 interfaces and routes all look right.  The tunnel will show up as a
 `sl<n>' for some <n>.

 * Use `tcpdump -n -i <interface>' to watch the traffic go across some
 interface, to try to figure out where the traffic is going.  Look
 both for the private traffic before it goes into the tunnel, and the
 physical traffic, to try to find out where it disappears.  The
 diagnostics will tell you which physical ports it's using, something
 like this:
   udptunnel - alice: debug: using remote Wait,Wait local 131.111.232.108,1422
   udptunnel - bob: debug: using remote 131.111.232.108,1422 local 195.224.38.6,2413

 * alice and bob can see each other but the private networks can't ?
 Make sure alice and bob both have IP forwarding enabled.

 * Check your firewalls, if you have them.  It's most helpful if your
 firewall configuration arranges to log rejected packets - without
 that, they can be a complete pain to debug.


6. DNS, firewall, mail, etc.

 When you have IP level connectivity between your two networks, you
 must also arrange for:

 * An appropriate firewall on each tunnel endpoint (to stop attacks
 from one network to another) and also at all the borders of each
 network (to stop traffic that is going to, or looks like it came
 from, the private networks).

 * DNS configuration so that hosts on both sides of the tunnel can see
 each other's names, addresses and other information.

 * Mail, news and other application protocols may need to be
 configured to use the private tunnel connectivity, rather than
 treating the other private network's names as being `elsewhere' and
 using unencrypted connectivity via the global Internet.

 How to do these things is beyond the scope of this document.


7. Example

 This example is the tunnel between chiark and Relativity.  I'll quote
 it and explain the details, below.  See also the comment at the top of
 udptunnel.

 authbind udptunnel                                               \
          -m                                                      \
          -e nonce -e timestamp/10/30 -e pkcs5/8                  \
          -e blowfish-cbcmac/128 -e blowfish-cbc/128              \
          davenant-external,410                                   \
          chiark-public,Command                                   \
          172.31.80.6,172.31.80.9,1000,cslip                      \
          30,120,1800                                             \
          - 172.18.45.0/24                                        \
          ssh     -o 'ForwardAgent no' -o 'ForwardX11 no'         \
                  -o 'BatchMode yes'                              \
                  -i ~ian/.ssh/identity -l ian                    \
                  -v chiark.greenend.org.uk                       \
                  udptunnel

 Because at Relativity the tunnel endpoint has to not be our firewall,
 because the firewall is a 386SX/16 and so not powerful enough,
 Relativity practically has to be the active partner in any tunnels it
 is involved in.  This also necessitates the use of the `-m' option and
 various other things.

 Exposition of the example udptunnel invocation:

 > authbind udptunnel                                              \

 `authbind' is used because at Relativity the tunnel endpoint address
 has to be on a fixed port because our tunnel endpoint is not on the
 firewall system (if it's not on a fixed port we can't write a good
 firewall rule to let it through).

 The port we are using is port 410, a low port to prevent other
 processes `stealing' it, so root privilege or authbind is needed.

 >         -m                                                      \

 -m tells this invocation of udptunnel that its endpoint address and
 port (for encapsulated packets) are going to be NATted before the far
 end sees them.  The effect is that instead of supplying this
 information to the far end, the far end is told to `wait and see'.

 This should not usually be used in other circumstances.  (For full
 details see the comment at the top of udptunnel.)

 >         -e nonce -e timestamp/10/30 -e pkcs5/8                  \
 >         -e blowfish-cbcmac/128 -e blowfish-cbc/128              \

 This is the crypto configuration.

 >         davenant-external,410                                   \

 This is the local physical address and port.  davenant is the tunnel
 endpoint, and davenant-external is its public address (we run two
 networks on the wire at Relativity, an internal one and a public
 one).

 >         chiark-public,Command                                   \

 This is the physical remote address and port.  `Command' means find
 out the remote physical address or port by having udptunnel at the
 far end print its address and port when they have been allocated.

 Another possibility here is to use a fixed remote port number.

 The DNS at GR is configured so that just `chiark' means chiark via
 the tunnel, so we have to use chiark-public which means its public
 IP address.

 >         172.31.80.6,172.31.80.9,1000,cslip                      \

 172.31.80.6 is davenant's virtual address.
 172.31.80.9 is chiark's virtual address for the Relativity tunnel.

 >         30,130,1800                                             \

 These are the timing parameters.

 >         - 172.18.45.0/24                                        \

 No remote virtual networks are reachable via chiark.  172.18.45.0/24
 is the Relativity house ethernet, which is to be reachable via the
 tunnel from chiark.

 >         ssh     -o 'ForwardAgent no' -o 'ForwardX11 no'         \
 >                 -o 'BatchMode yes'                              \
 >                 -i ~ian/.ssh/identity -l ian                    \
 >                 -v chiark.greenend.org.uk                       \
 >                 udptunnel

 This is the ssh invocation to run udptunnel at the far end.

 At Relativity we put the udptunnel invocation in a file and run it
 out of inittab, like this:

 t0:235:respawn:/usr/local/sbin/really -u ian /usr/local/sbin/udptunnel-invoke 2>&1 | logger -p local2.info -t tunnel-chiark


8. Copyright notice

 This file is part of ipif, part of userv-utils

 userv-utils are
 Copyright 1996-2013 Ian Jackson <ijackson@chiark.greenend.org.uk>
 Copyright 1998 David Damerell <damerell@chiark.greenend.org.uk>
 Copyright 1999,2003
    Chancellor Masters and Scholars of the University of Cambridge
 Copyright 2010 Tony Finch <fanf@dotat.at>

 All the utilities here are free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 3 of the License, or (at your
 option) any later version.

 This program is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with userv-utils; if not, see http://www.gnu.org/licenses/.
