chiark / gitweb /
svc/tripe-ifup.in: Don't set remote IPv6 address until interface is up.
[tripe] / svc / tripe-ifup.in
1 #! /bin/sh
2 ###
3 ### TrIPE interface initialization script
4 ###   suitable for Linux; other operating systems probably want something
5 ###   similar
6
7 ###----- Licensing notica ---------------------------------------------------
8 ###
9 ### Redistribution, modification and use of this file is permitted without
10 ### limitation.
11 ###
12 ### This file is distributed in the hope that it will be useful,
13 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 set -e
17
18 ## Import compile-time configuration.
19 : ${bindir=@bindir@}
20 : ${tripectl=$bindir/tripectl}
21 PATH=/usr/bin:/usr/sbin:/bin:/sbin:$bindir
22 export PATH TRIPEDIR
23
24 ## Determine whether we have IPv6 support.
25 if [ -d /proc/sys/net/ipv6 ]; then have6=t; else have6=nil; fi
26
27 ###--------------------------------------------------------------------------
28 ### Error handling.
29
30 win=t
31 try () {
32   if "$@"; then :; else
33     rc=$?
34     tripectl warn tripe-ifup command-failed rc=$rc "$*"
35     win=nil
36   fi
37 }
38
39 ###--------------------------------------------------------------------------
40 ### Collect arguments.
41
42 ## Collect the simple arguments.
43 if [ $# -lt 3 ]; then
44   echo >&2 "usage: $0 PEER IFNAME ADDR..."; exit 1
45 fi
46 peer=$1 ifname=$2 family=$3; shift 3
47
48 ## Parse the address family.
49 case "$family,$#" in
50   INET,1) addr=$1 port=4070 ;;
51   INET,2) addr=$1 port=$2 ;;
52   INET,*) echo >&2 "$0: bad INET address"; exit 1 ;;
53   *)      echo >&2 "$0: unknown address family $family"; exit 1 ;;
54 esac
55
56 ###--------------------------------------------------------------------------
57 ### Set the interface name.
58
59 case "${P_IFNAME+set}" in
60   set)
61     try ip link set "$ifname" name "$P_IFNAME"
62     ifname=$P_IFNAME
63     $tripectl setifname "$peer" "$ifname"
64     ;;
65 esac
66
67 ###--------------------------------------------------------------------------
68 ### Configure the link.
69
70 ## Split local addresses into v4 and v6 lists.
71 unset l4addr l6addr
72 for a in $P_LADDR; do
73   case "$a" in
74     *:*) l6addr=${l6addr+$l6addr }$a ;;
75     *)   l4addr=${l4addr+$l4addr }$a ;;
76   esac
77 done
78
79 ## Determine the remote v4 and v6 addresses.  We only allow one remote
80 ## address for each: others can be added as routes.
81 unset r4addr r6addr
82 for a in $P_RADDR; do
83   case "$a" in
84     *:*) r6addr=$a ;;
85     *)   r4addr=$a ;;
86   esac
87 done
88
89 ## Configure the first v4 address as point-to-point; add the others as plain
90 ## addresses.
91 haveaddr4=nil
92 set -- $l4addr
93 case $#,${r4addr+set} in
94   [1-9]*,set)
95     try ip addr add "$1" peer "$r4addr" dev "$ifname"
96     haveaddr4=t
97     shift
98     ;;
99 esac
100 for a in "$@"; do
101   try ip addr add "$a" dev "$ifname"
102   haveaddr4=t
103 done
104
105 ## IPv6 point-to-point links seem broken in Linux.  Attach the local and
106 ## remote addresses by hand.
107 haveaddr6=nil
108 set -- $l6addr
109 case $have6,$# in
110   t,[1-9]*)
111
112     ## If we're configured to set IPv6 addresses then we should ensure that
113     ## they're going to work, even if the default setting for new interfaces
114     ## is to disable IPv6.
115     try sysctl -q net.ipv6.conf."$ifname".disable_ipv6=0
116
117     ## Now add the source and destination addresses.
118     for a in "$@"; do
119       try ip addr add "$a" dev "$ifname"
120       haveaddr6=t
121     done
122     ;;
123 esac
124
125 ###--------------------------------------------------------------------------
126 ### Bring the interface up.
127
128 case $haveaddr4,$haveaddr6 in
129   nil,nil)
130     ;;
131   *)
132     case "${P_MTU+set}" in
133       set)
134         mtu=$P_MTU;;
135       *)
136         pathmtu=$(pathmtu "$addr")
137         mtu=$(expr "$pathmtu" - 29 - $A_BULK_OVERHEAD)
138         ;;
139     esac
140     try ip link set dev "$ifname" up mtu "$mtu"
141     ;;
142 esac
143
144 ###--------------------------------------------------------------------------
145 ### Set the peer IPv6 address if any.
146
147 ## IPv6 point-to-point links seem broken in Linux.  Attach the local and
148 ## remote addresses by hand.
149 set -- $l6addr
150 case $have6,$#,${r6addr+set} in
151   t,[1-9]*,set)
152     try ip route add $r6addr proto static dev "$ifname"
153     ;;
154 esac
155
156 ###--------------------------------------------------------------------------
157 ### Set up routing.
158
159 ## Split the routes into v4 and v6 lists.
160 unset route4 route6
161 for p in $P_NETS; do
162   case "$p" in
163     *:*) route6=${route6+$route6 }$p ;;
164     *)   route4=${route4+$route4 }$p ;;
165   esac
166 done
167
168 ## Add the v4 routes.
169 set -- $route4
170 case $haveaddr4,$# in
171   t,[1-9]*)
172     for p in "$@"; do
173       try ip route add $p proto static via "$r4addr"
174     done
175     ;;
176 esac
177
178 ## Add the v6 routes.
179 set -- $route6
180 case $haveaddr6,$# in
181   t,[1-9]*)
182     for p in "$@"; do
183       try ip route add $p proto static via "${r6addr%/*}"
184     done
185     ;;
186 esac
187
188 ###--------------------------------------------------------------------------
189 ### Maybe invoke a follow-on script.
190
191 case "${P_IFUPEXTRA+set}" in
192   set)
193     eval "$P_IFUPEXTRA"
194     ;;
195 esac
196
197 ###--------------------------------------------------------------------------
198 ### Issue a notification that we've won.
199
200 case $win in
201   t) $tripectl notify tripe-ifup configured "$peer" ;;
202   nil) $tripectl notify tripe-ifup configured "$peer" failed ;;
203 esac
204
205 ###----- That's all, folks --------------------------------------------------