chiark / gitweb /
Host changeover.
[firewall] / prologue.m4
1 ### -*-sh-*-
2 ###
3 ### Failsafe prologue for firewall scripts
4 ###
5 ### (c) 2008 Mark Wooding
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This program is free software; you can redistribute it and/or modify
11 ### it under the terms of the GNU General Public License as published by
12 ### the Free Software Foundation; either version 2 of the License, or
13 ### (at your option) any later version.
14 ###
15 ### This program is distributed in the hope that it will be useful,
16 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ### GNU General Public License for more details.
19 ###
20 ### You should have received a copy of the GNU General Public License
21 ### along with this program; if not, write to the Free Software Foundation,
22 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24 m4_divert(10)m4_dnl
25 ###--------------------------------------------------------------------------
26 ### Failsafe prologue.
27
28 revert () {
29   escape=$1 badness=$2
30   ## Report a firewall script failure and retreat to a safe place.
31
32   echo "$2!  Retreating to safe version..."
33   if ! "$1" revert; then
34     echo >&2 "Safe firewall failed.  You're screwed.  Good luck."
35     exit 1
36   fi
37   echo >&2 "Phew!  Fallback to safe version successful."
38   exit 1
39 }
40
41 finished () {
42   echo "Done."
43   exit 0
44 }
45
46 try () {
47   old=$1 new=$2
48   ## Install the NEW firewall rules.  If it fails, revert to the OLD ones.
49   ## Updating firewall rules can fail spectacularly, so be careful.  Leave a
50   ## timebomb in the form of NEW.errors: if this isn't removed in 10 seconds
51   ## after the NEW rules complete successfully, then revert.  Write errors to
52   ## NEW.errors.
53
54   ## Make sure we have an escape route.
55   if [ ! -x "$old" ]; then
56     echo >&2 "$0: no escape plan: \`$old' is missing"
57     exit 1
58   fi
59
60   ## Clear the air and make the errors file.
61   rm -f "$new.errors" "$new.timebomb" "$new.grabbed"
62   exec >"$new.errors" 2>&1
63
64   ## Now try to install the new firewall.
65   "$new" install || revert "$old" "Failed"
66
67   ## Set up the time bomb.  Leave the errors file there if we failed.
68   (sleep 10
69    if [ -f "$new.errors" ]; then
70      mv "$new.errors" "$new.timebomb"
71      revert "$old" "Time bomb"
72    fi)&
73 }
74
75 catch () {
76   new=$1
77   ## Report successful installation of the script.
78
79   if mv "$new.errors" "$new.grabbed" 2>/dev/null; then
80     rc=0
81     echo "Installed OK."
82   else
83     mv "$new.timebomb" "$new.grabbed"
84     echo "Timebomb went off."
85     rc=1
86   fi
87   cat "$new.grabbed" >&2
88   rm -f "$new.grabbed"
89   return $rc
90 }
91
92 exit_after_clearing=:
93 export FWCOOKIE=magical
94 case "$#,${1-update}" in
95   1,start | 1,restart | 1,reload | 1,force-reload)
96     echo -n "Starting up firewall... "
97     "$firewall_script" install || revert "$firewall_failsafe" "Failed"
98     finished
99     ;;
100   1,stop)
101     echo -n "Shutting down firewall... "
102     exit_after_clearing=finished
103     ;;
104   1,replace | 1,test)
105     echo -n "Running new firewall... "
106     if ! (try "$firewall_script" "$0"); then
107       echo "FAILED."
108       cat "$0.errors" >&2
109       exit
110     fi
111     echo "done."
112     echo "Can you hear me?"
113     (trap 'exit 127' TERM
114      while :; do
115        if [ -f "$0.timebomb" ]; then
116          kill $$
117          echo "Timebomb went off!"
118          cat "$0.timebomb"
119          exit 1
120        fi
121        sleep 1
122      done)&
123     read answer
124     kill $!
125     catch "$0"
126     case "$1,$answer" in
127       replace,y* | replace,Y*)
128         install -m755 "$0" "$firewall_script"
129         echo "Cool.  Firewall script replaced."
130         exit 0
131         ;;
132       test,y* | test,Y*)
133         echo "Cool.  Everything seems good."
134         exit 0
135         ;;
136       *)
137         revert "$firewall_script" "Bogus"
138         ;;
139     esac
140     ;;
141   1,remote-prepare)
142     try "$firewall_script" "$0"
143     exit 0
144     ;;
145   1,remote-commit)
146     catch "$0"
147     install -m755 "$0" "$firewall_script"
148     exit 0
149     ;;
150   1,install | 1,revert)
151     ;;
152   *)
153     cat >&2 <<EOF
154 Usage:
155         $0 start|stop|reload|restart|force-reload
156         $0 replace|test|remote-prepare|remote-commit
157 EOF
158     exit 1
159     ;;
160 esac
161
162 m4_divert(-1)
163 ###----- That's all, folks --------------------------------------------------