chiark / gitweb /
contrib/: New directory for random occasionally-useful stuff.
[tripe] / contrib / tripe-ipif
diff --git a/contrib/tripe-ipif b/contrib/tripe-ipif
new file mode 100755 (executable)
index 0000000..689957c
--- /dev/null
@@ -0,0 +1,132 @@
+#! /bin/sh
+###
+### TRIPE_SLIPIF dynamic allocation script for use with `userv-ipif'
+###
+### (c) 2012 Mark Wooding
+###
+
+###----- Licensing notice ---------------------------------------------------
+###
+### This file is part of Trivial IP Encryption (TrIPE).
+###
+### TrIPE is 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 2 of the License, or
+### (at your option) any later version.
+###
+### TrIPE 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 TrIPE; if not, write to the Free Software Foundation,
+### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+###--------------------------------------------------------------------------
+### Instructions.
+###
+### This script is an adaptor for attaching tripe's `slip' tunnel driver to
+### `userv-ipif'.  The latter is a service for GNU Userv which allows
+### otherwise unprivileged users to implement network devices, subject to
+### administrative limitations on which addresses can be configured and which
+### prefixes routed through them.  The software is available as part of the
+### `userv-utils' package.
+###
+### To use this script, you'll need to set up a configuration file
+### `$TRIPEDIR/ipif.tab'.  This file may contain comments (begining `#') and
+### blank lines, both of which are ignored, and entries of the form
+###
+### PEER       REMOTE-EXT      LOCAL-INT       REMOTE-INT      ROUTE,...
+###
+### The PEER names a peer, as given to tripe's ADD command.  REMOTE-EXT is
+### the external IP address of the peer, i.e., the one which tripe will send
+### its packets to.  LOCAL-INT and REMOTE-INT are the local and remote
+### addresses to be associated with the point-to-point interface.  Finally,
+### the ROUTEs are a comma-separated list of PREFIX/LEN pairs declaring
+### which prefixes should be routed over this interface.  The *-INT and
+### ROUTEs fields are passed on to the `userv-ipif' service.  The REMOTE-EXT
+### field is used (a) by the accompanying `ipif-peers' script to set up the
+### peer association, and (b) to determine the correct MTU to set; it
+### should have the form ADDRESS[:PORT], where the PORT defaults to 4070 if
+### it's not given explicitly.
+###
+### Having done all of that, and having configured userv-ipif correctly,
+### you should set TRIPE_SLIPIF=.../tripe-ipif and everything should just
+### work.  If you drop the script `ipif-peers' into the $TRIPEDIR/peers
+### directory, then the init script will run it and all of the configured
+### peers with known remote addresses will be added on startup.
+
+set -e
+quis=${0##*/}
+
+## Parse the command line.
+case $# in 1) ;; *) echo >&2 "Usage: $quis PEER"; exit 1 ;; esac
+case ${TRIPEDIR+t} in
+  t) ;;
+  *) echo >&2 "$quis: \`TRIPEDIR' unset"; exit 1 ;;
+esac
+peer=$1
+
+## Arrange for errors to go somewhere.
+case "${TRIPE_IPIF_LOG+t}" in t) exec 2>>"$TRIPE_IPIF_LOG" ;; esac
+now=$(date +"%Y-%m-%d %H:%M:%S")
+echo >&2 "$now $quis[$$] running for peer \`$peer'"
+
+## Find the record in the peer table.
+foundp=nil
+while read name remote_ext local_int remote_int routes; do
+  case $name in "$peer") foundp=t; break ;; esac
+done <$TRIPEDIR/ipif.tab
+case $foundp in
+  nil) echo >&2 "$quis[$$]: unknown peer \`$peer'"; exit 1 ;;
+esac
+
+## Announce the interface name.  We actually have no way to determine this,
+## so lie and hope that nobody cares.
+echo "userv-$peer"
+
+## Now we can interrogate the server without deadlocking it.
+algs=$(tripectl algs) tagsz=nil blksz=nil
+while read line; do
+  for i in $line; do
+    case $i in
+      cipher-blksz=*) blksz=${i#*=} ;;
+      mac-tagsz=*) tagsz=${i#*=} ;;
+    esac
+  done
+done <<EOF
+$algs
+EOF
+case ,$tagsz,$blksz, in
+  *,nil,*) echo >&2 "$quis[$$]: failed to discover cipher suite"; exit 1 ;;
+esac
+
+## Determine the remote address if none is specified; strip off a port number
+## if there is one.
+case "$remote_ext" in
+  -)
+    addr=$(tripectl addr $peer)
+    set -- $addr
+    case $1 in
+      INET) remote_ext=$2 ;;
+      *) echo >&2 "$quis: unexpected address family \`$1'"; exit 1 ;;
+    esac
+    ;;
+  *:*)
+    remote_ext=${remote_ext%:*}
+    ;;
+esac
+
+## Determine the MTU based on the path.
+pmtu=$(pathmtu $remote_ext)
+mtu=$(( $pmtu - 33 - $tagsz - $blksz ))
+
+## Obtain the tunnel and run it.
+now=$(date +"%Y-%m-%d %H:%M:%S")
+info="invoking \`userv ipif' for \`$peer'; mtu = $mtu"
+info="$info; $local_int -> $remote_int${routes+ $routes}"
+echo >&2 "$now $quis[$$] $info"
+exec userv root ipif $local_int,$remote_int,$mtu,slip $routes
+
+###----- That's all, folks --------------------------------------------------