chiark / gitweb /
server/: Post-merge fixup.
[tripe] / contrib / tripe-ipif.in
1 #! /bin/sh
2 ###
3 ### TRIPE_SLIPIF dynamic allocation script for use with `userv-ipif'
4 ###
5 ### (c) 2012 Mark Wooding
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This file is part of Trivial IP Encryption (TrIPE).
11 ###
12 ### TrIPE is free software: you can redistribute it and/or modify it under
13 ### the terms of the GNU General Public License as published by the Free
14 ### Software Foundation; either version 3 of the License, or (at your
15 ### option) any later version.
16 ###
17 ### TrIPE is distributed in the hope that it will be useful, but WITHOUT
18 ### ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 ### FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 ### for more details.
21 ###
22 ### You should have received a copy of the GNU General Public License
23 ### along with TrIPE.  If not, see <https://www.gnu.org/licenses/>.
24
25 ###--------------------------------------------------------------------------
26 ### Instructions.
27 ###
28 ### This script is an adaptor for attaching tripe's `slip' tunnel driver to
29 ### `userv-ipif'.  The latter is a service for GNU Userv which allows
30 ### otherwise unprivileged users to implement network devices, subject to
31 ### administrative limitations on which addresses can be configured and which
32 ### prefixes routed through them.  The software is available as part of the
33 ### `userv-utils' package.
34 ###
35 ### To use this script, you'll need to set up a configuration file
36 ### `$TRIPEDIR/ipif.tab'.  This file may contain comments (begining `#') and
37 ### blank lines, both of which are ignored, and entries of the form
38 ###
39 ### PEER        REMOTE-EXT      LOCAL-INT       REMOTE-INT      ROUTE,...
40 ###
41 ### The PEER names a peer, as given to tripe's ADD command.  REMOTE-EXT is
42 ### the external IP address of the peer, i.e., the one which tripe will send
43 ### its packets to.  LOCAL-INT and REMOTE-INT are the local and remote
44 ### addresses to be associated with the point-to-point interface.  Finally,
45 ### the ROUTEs are a comma-separated list of PREFIX/LEN pairs declaring
46 ### which prefixes should be routed over this interface.  The *-INT and
47 ### ROUTEs fields are passed on to the `userv-ipif' service.  The REMOTE-EXT
48 ### field is used (a) by the accompanying `ipif-peers' script to set up the
49 ### peer association, and (b) to determine the correct MTU to set; it
50 ### should have the form ADDRESS[:PORT], where the PORT defaults to 4070 if
51 ### it's not given explicitly, and an IPv6 ADDRESS is enclosed in square
52 ### brackets (because of the stupid syntax decision to use colons in IPv6
53 ### address literals).
54 ###
55 ### Having done all of that, and having configured userv-ipif correctly,
56 ### you should set TRIPE_SLIPIF=.../tripe-ipif and everything should just
57 ### work.  If you drop the script `ipif-peers' into the $TRIPEDIR/peers
58 ### directory, then the init script will run it and all of the configured
59 ### peers with known remote addresses will be added on startup.
60
61 set -e
62 quis=${0##*/}
63 : ${TRIPEDIR=@configdir@}
64 : ${logfile=@logfile@}
65 : ${TRIPE_IPIF_LOG=${logfile%/*}/tripe-ipif.log}
66
67 ## Parse the command line.
68 case $# in 1) ;; *) echo >&2 "Usage: $quis PEER"; exit 1 ;; esac
69 case ${TRIPEDIR+t} in
70   t) ;;
71   *) echo >&2 "$quis: \`TRIPEDIR' unset"; exit 1 ;;
72 esac
73 peer=$1
74
75 ## Arrange for errors to go somewhere.
76 exec 2>>"$TRIPE_IPIF_LOG"
77 now=$(date +"%Y-%m-%d %H:%M:%S")
78 echo >&2 "$now $quis[$$] running for peer \`$peer'"
79
80 ## Find the record in the peer table.
81 foundp=nil
82 while read name remote_ext local_int remote_int routes; do
83   case $name in "$peer") foundp=t; break ;; esac
84 done <$TRIPEDIR/ipif.tab
85 case $foundp in
86   nil) echo >&2 "$quis[$$]: unknown peer \`$peer'"; exit 1 ;;
87 esac
88
89 ## Announce the interface name.  We actually have no way to determine this,
90 ## so lie and hope that nobody cares.
91 echo "userv-$peer"
92
93 ## Now we can interrogate the server without deadlocking it.
94 algs=$(tripectl algs) overhead=nil
95 while read line; do
96   for i in $line; do
97     case $i in bulk-overhead=*) overhead=${i#*=} ;; esac
98   done
99 done <<EOF
100 $algs
101 EOF
102 case $overhead in
103   nil) echo >&2 "$quis[$$]: failed to discover overhead"; exit 1 ;;
104 esac
105
106 ## Determine the remote address if none is specified; strip off a port number
107 ## if there is one.
108 case "$remote_ext" in
109   -)
110     addr=$(tripectl addr $peer)
111     set -- $addr
112     case $1 in
113       INET | INET6) remote_af=$1 remote_ext=$2 ;;
114       *) echo >&2 "$quis: unexpected address family \`$1'"; exit 1 ;;
115     esac
116     ;;
117   \[*\]:*)
118     remote_af=INET6
119     remote_ext=${remote_ext#\[}
120     remote_ext=${remote_ext%\]:*}
121     ;;
122   *:*)
123     remote_af=INET
124     remote_ext=${remote_ext%:*}
125     ;;
126 esac
127
128 ## Determine the MTU based on the path.
129 pmtu=$(pathmtu $remote_ext)
130 case $remote_af in
131   INET) iphdrsz=20 ;;
132   INET6) iphdrsz=40 ;;
133 esac
134 mtu=$(( $pmtu - $iphdrsz - 8 - $overhead - 1 ))
135
136 ## Obtain the tunnel and run it.
137 now=$(date +"%Y-%m-%d %H:%M:%S")
138 info="invoking \`userv ipif' for \`$peer'; mtu = $mtu"
139 info="$info; $local_int -> $remote_int${routes+ $routes}"
140 echo >&2 "$now $quis[$$] $info"
141 exec userv root ipif $local_int,$remote_int,$mtu,slip $routes
142
143 ###----- That's all, folks --------------------------------------------------