3 # tinc tincd VPN setup script
5 # chkconfig: 2345 46 54
8 # authors: Lubomir Bulej <pallas@kadan.cz>
9 # Mads Kiilerich <mads@kiilerich.com>
11 # description: This script parses tinc configuration files for networks given \
12 # in /etc/tinc/nets.boot and for each of the networks it sets up \
13 # the interface and static routes and starts the tinc daemon.
17 # Source function library.
18 . /etc/rc.d/init.d/functions
20 # Source networking configuration.
21 . /etc/sysconfig/network
23 # Check that networking is up.
24 [ ${NETWORKING} = "no" ] && exit 0
26 #############################################################################
27 # configuration & sanity checks
34 NETSFILE=$TCONF/nets.boot
37 if [ ! -x $TINCD ]; then
38 echo "**tinc: $TINCD does not exist or is not executable!" >&2
42 # Check if ip-route is installed
43 if [ ! -f /sbin/ip ]; then
44 echo "**tinc: ip-route utilities not installed!" >&2
49 if ! ip addr &> /dev/null; then
50 echo "**tinc: kernel not configured for use with ip-route!" >&2
54 # Check the configuration directory
55 if [ ! -d $TCONF ]; then
56 echo "**tinc: configuration directory ($TCONF) not found!" >&2
61 if [ ! -f $NETSFILE ]; then
62 echo "**tinc: file with list of VPNs to start ($NETSFILE) not found!" >&2
66 # Load names of networks to be started
67 NETS="$(sed -e 's/#.*//; s/[[:space:]]//g; /^$/ d' $NETSFILE)"
70 ##############################################################################
71 # prefix_to_mask Converts prefix length to netmask
72 # eg. 17 -> 255.255.128.0
77 for _dot in "." "." "." " "; do
78 if [ ${_len} -ge 8 ]; then
84 _MSK="${_MSK}$((255 & (255 << (8 - _fld))))${_dot}"
92 ##############################################################################
93 # mask_to_prefix Converts netmask to prefix length
94 # eg. 255.255.192.0 -> 18
99 for _tmp in 1 2 3 4; do
103 while [ ${_fld} -ne 0 ]; do
104 _fld=$(((_fld << 1) & 255))
113 ##############################################################################
114 # vpn_load () Loads VPN configuration
119 CFG="$TCONF/$1/tinc.conf"
120 [ -f $CFG ] || { MSG="$CFG does not exist!"; return 1; }
123 DEV="$(grep -i -e '^[[:space:]]*TapDevice' $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
124 VPN="$(grep -i -e '^[[:space:]]*(MyOwnVPNIP|MyVirtualIP)' -E $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
125 IFM="$(grep -i -e '^[[:space:]]*VPNMask' $CFG | sed 's/[[:space:]]//g; s/^.*=//g')"
127 # TapDevice syntax validation
129 { MSG="TapDevice required!"; return 1; }
130 [ $(echo $DEV | wc -l) -gt 1 ] && \
131 { MSG="multiple TapDevice entries not allowed!"; return 1; }
132 echo $DEV | grep -q -x -E '/dev/tap[[:digit:]]+' ||
133 { MSG="TapDevice should be in form /dev/tapX!"; return 1; }
135 # MyOwnVPNIP/MyVirtualIP syntax validation
137 { MSG="MyOwnVPNIP/MyVirtualIP required!"; return 1; }
138 [ $(echo $VPN | wc -l) -gt 1 ] && \
139 { MSG="multiple MyOwnVPNIP/MyVirtualIP entries not allowed!"; return 1; }
140 echo $VPN | grep -q -x -E \
141 '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}/[[:digit:]]{1,2}' || \
142 { MSG="badly formed MyOwnVPNIP/MyVirtualIP address $VPN!"; return 1; }
144 # VPNMask syntax validation
145 [ $(echo $IFM | wc -l) -gt 1 ] && \
146 { MSG="multiple VPNMask entries not allowed!"; return 1; }
149 # device & IP address extraction
154 # netmask is calculated from MyVirtualIP netmask prefix length, except when
155 # VPNMask is specified, in which case it is used instead of default prefix
157 # VPNMask not specified
158 if [ -z "$IFM" ]; then
160 MSK=$(prefix_to_mask $LEN)
162 # VPNMask is prefix length, convert it to netmask for MSK
163 elif echo $IFM | grep -q -x -E '[[:digit:]]{1,2}'; then
165 MSK=$(prefix_to_mask $IFM)
167 # VPNMask is netmask, convert it to prefix length for VPN
168 elif echo $IFM | grep -q -x -E '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}'; then
169 VPN="$ADR/$(mask_to_prefix $IFM)"
173 MSG="badly formed interface netmask (VPNMask=$IFM)!"
178 # Network & broadcast addresses
179 BRD=$(ipcalc --broadcast $ADR $MSK | cut -d"=" -f2)
180 NET=$(ipcalc --network $ADR $MSK | cut -d"=" -f2)
183 MAC=$(printf "fe:fd:%0.2x:%0.2x:%0.2x:%0.2x" $(echo $ADR | { IFS=. ; read a b c d; echo $a $b $c $d; }))
187 # echo "VPN $VPN TAP $TAP NUM $NUM MAC $MAC IFM $IFM" >&2
188 # echo "ADR $ADR MSK $MSK NET $NET BRD $BRD" >&2
194 ##############################################################################
195 # vpn_start () starts specified VPN
197 # $1 ... VPN to start
201 vpn_load $1 || return 1
204 if [ ! -c $DEV ]; then
205 [ -e $DEV ] && rm -f $DEV
206 mknod --mode=0600 $DEV c 36 $((16 + NUM))
210 ERR="$(insmod ethertap -o "ethertap$NUM" unit="$NUM" 2>&1 1> /dev/null)" ||
211 { MSG="could not insmod ethertap as unit $NUM!"; return 2; }
213 # configure the interface
214 ERR="$(ip link set $TAP address $MAC 2>&1)" ||
215 { MSG="could not set address for device $TAP!"; return 3; }
217 ERR="$(ip link set $TAP up 2>&1)" ||
218 { MSG="could not bring up device $TAP!"; return 3; }
220 ERR="$(ip addr add $VPN brd $BRD dev $TAP 2>&1)" ||
221 { MSG="could not set IP address for device $TAP!"; return 3; }
224 $TINCD --net="$1" $DEBUG || \
225 { MSG="could not start daemon for network $1"; return 3; }
227 # setup custom static routes
228 /etc/sysconfig/network-scripts/ifup-routes $TAP
234 ##############################################################################
235 # vpn_stop () Stops specified VPN
241 vpn_load $1 || return 1
243 # kill the tincd daemon
244 PID="$TPIDS/tinc.$1.pid"
246 $TINCD --net="$1" --kill &> /dev/null
249 if [ $RET -eq 0 ]; then
251 while [ $dly -le 5 ]; do
253 sleep 1; dly=$((dly + 1))
257 # remove stale PID file
258 [ -f $PID ] && rm -f $PID
261 # bring the interface down
262 ip addr flush dev $TAP &> /dev/null
263 ip link set $TAP down &> /dev/null
265 # remove ethertap module
266 rmmod "ethertap$NUM" &> /dev/null
272 # Check if there is anything to start
273 if [ ! -z "$1" -a "$1" != "status" -a -z "$NETS" ]; then
274 echo "**tinc: no networks found in $NETSFILE!" >&2
279 # See how we were called.
283 echo -n "Bringing up TINC network $vpn: "
285 success "startup of network $vpn" || \
286 failure "startup of network $vpn"
289 if [ ! -z "$MSG" ]; then
290 [ ! -z "$ERR" ] && echo "$ERR" >&2
291 echo "**tinc: $MSG" >&2
295 touch /var/lock/subsys/tinc
300 echo -n "Shutting down TINC network $vpn: "
302 success "shutdown of network $vpn" || \
303 failure "shutdown of network $vpn"
306 if [ ! -z "$MSG" ]; then
307 [ ! -z "$ERR" ] && echo "$ERR" >&2
308 echo "**tinc: $MSG" >&2
312 rm -f /var/lock/subsys/tinc
316 echo -n "Configured VPNs: "
318 PID="$TPIDS/tinc.$vpn.pid"
320 [ -f $PID ] && PID="$(cat $PID)" || PID="-dead-"
321 ps ax | grep "^[[:space:]]*$PID" && STS="OK" || STS="DEAD"
333 echo "Usage: tinc {start|stop|status|restart}"