| 1 | #!/bin/sh | 
|---|
| 2 | # Wireless Leiden config-update script for FreeBSD 8.0 (nanobsd) | 
|---|
| 3 | # Based on the 'API' of Jasper | 
|---|
| 4 | # Rick van der Zwet | 
|---|
| 5 | # XXX: TODO, some proper error checking for fetch | 
|---|
| 6 |  | 
|---|
| 7 |  | 
|---|
| 8 | # Slow connection = no connection | 
|---|
| 9 | export HTTP_TIMEOUT=5 | 
|---|
| 10 |  | 
|---|
| 11 |  | 
|---|
| 12 | check_access() { | 
|---|
| 13 | # Direct Access - Internal IP | 
|---|
| 14 | BASEURL="http://172.16.4.46/wleiden/config/" | 
|---|
| 15 | # Connectivity check | 
|---|
| 16 | fetch -o /dev/null -q $BASEURL > /dev/null && return | 
|---|
| 17 | echo "# WARN: Fetch via internal $BASEURL failed" | 
|---|
| 18 |  | 
|---|
| 19 | # Direct Access - External DNS | 
|---|
| 20 | BASEURL="http://132.229.112.21/wleiden/config/" | 
|---|
| 21 | fetch -o /dev/null -q $BASEURL > /dev/null && return | 
|---|
| 22 | echo "# CRIT: Fetch via external $BASEURL failed" | 
|---|
| 23 |  | 
|---|
| 24 | exit 1 | 
|---|
| 25 | } | 
|---|
| 26 | check_access | 
|---|
| 27 |  | 
|---|
| 28 |  | 
|---|
| 29 | # Default config to fetch | 
|---|
| 30 | CONFIG=`hostname -s` | 
|---|
| 31 |  | 
|---|
| 32 | # Determine it's statup and running location and some other hints | 
|---|
| 33 | # Skip named.conf as it not planned in current release | 
|---|
| 34 | FILES="authorized_keys dhcpd.conf dnsmasq.conf motd rc.conf.local resolv.conf pf.hybrid.conf.local wleiden.yaml" | 
|---|
| 35 | file_details() { | 
|---|
| 36 | POST_CMD="" | 
|---|
| 37 | FILE_HINT="" | 
|---|
| 38 |  | 
|---|
| 39 | case "$1" in | 
|---|
| 40 | 'authorized_keys') | 
|---|
| 41 | STARTUP_LOC="/cfg/ssh/${FILE}" | 
|---|
| 42 | RUNNING_LOC="/etc/ssh/${FILE}" | 
|---|
| 43 | ;; | 
|---|
| 44 | 'dhcpd.conf') | 
|---|
| 45 | STARTUP_LOC="/cfg/local/${FILE}" | 
|---|
| 46 | RUNNING_LOC="/etc/local/${FILE}" | 
|---|
| 47 | FILE_HINT="service isc-dhcpd restart" | 
|---|
| 48 | ;; | 
|---|
| 49 | 'dnsmasq.conf') | 
|---|
| 50 | STARTUP_LOC="/cfg/local/${FILE}" | 
|---|
| 51 | RUNNING_LOC="/etc/local/${FILE}" | 
|---|
| 52 | FILE_HINT="service dnsmasq restart" | 
|---|
| 53 | ;; | 
|---|
| 54 | 'motd') | 
|---|
| 55 | STARTUP_LOC="/cfg/${FILE}" | 
|---|
| 56 | RUNNING_LOC="/etc/${FILE}" | 
|---|
| 57 | POST_CMD="/etc/rc.d/motd onestart" | 
|---|
| 58 | ;; | 
|---|
| 59 | 'named.conf') | 
|---|
| 60 | STARTUP_LOC="/cfg/namedb/${FILE}" | 
|---|
| 61 | RUNNING_LOC="/etc/namedb/${FILE}" | 
|---|
| 62 | FILE_HINT="service named restart" | 
|---|
| 63 | ;; | 
|---|
| 64 | 'rc.conf.local') | 
|---|
| 65 | STARTUP_LOC="/cfg/${FILE}" | 
|---|
| 66 | RUNNING_LOC="/etc/${FILE}" | 
|---|
| 67 | FILE_HINT="service netif restart" | 
|---|
| 68 | ;; | 
|---|
| 69 | 'resolv.conf') | 
|---|
| 70 | STARTUP_LOC="/cfg/${FILE}" | 
|---|
| 71 | RUNNING_LOC="/etc/${FILE}" | 
|---|
| 72 | ;; | 
|---|
| 73 | 'pf.hybrid.conf.local') | 
|---|
| 74 | STARTUP_LOC="/cfg/${FILE}" | 
|---|
| 75 | RUNNING_LOC="/etc/${FILE}" | 
|---|
| 76 | POST_CMD="service pf reload" | 
|---|
| 77 | ;; | 
|---|
| 78 | 'wleiden.yaml') | 
|---|
| 79 | STARTUP_LOC="/cfg/local/${FILE}" | 
|---|
| 80 | RUNNING_LOC="/etc/local/${FILE}" | 
|---|
| 81 | ;; | 
|---|
| 82 | esac | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | usage() { | 
|---|
| 86 | ( | 
|---|
| 87 | echo "Usage: $0 [-bn] [-c <config>] [-m <all|startup|testing|running>]" | 
|---|
| 88 | echo "  -b          = batch mode, no user input" | 
|---|
| 89 | echo "  -c <config> = default configuration to fetch" | 
|---|
| 90 | echo "  -d          = do not run the POST_CMD commands" | 
|---|
| 91 | echo "  -n          = do not mount config partition" | 
|---|
| 92 | echo "  -m all      = copy config files to running & config partition [default]" | 
|---|
| 93 | echo "  -m startup  = copy config files to config partition" | 
|---|
| 94 | echo "  -m testing  = do not copy config files" | 
|---|
| 95 | echo "  -m running  = copy config files to running partition" | 
|---|
| 96 | echo "  -m hack     = copy running files to config partition" | 
|---|
| 97 | ) 1>&2 | 
|---|
| 98 | exit 2 | 
|---|
| 99 | } | 
|---|
| 100 |  | 
|---|
| 101 | # Argument parsing using getopts | 
|---|
| 102 | USE_API=1               # Whether or not to use the webinterface | 
|---|
| 103 | OPT_MOUNT=1 | 
|---|
| 104 | OPT_RUNNING=1 | 
|---|
| 105 | OPT_STARTUP=1 | 
|---|
| 106 | OPT_HACK=0              # Hack for people without configuration managment and testing | 
|---|
| 107 | OPT_BATCH=0 | 
|---|
| 108 | OPT_POSTCMD=true | 
|---|
| 109 |  | 
|---|
| 110 | parse_options() { | 
|---|
| 111 | while getopts "bc:nm:d" OPT; do | 
|---|
| 112 | case "$OPT" in | 
|---|
| 113 | b) OPT_BATCH=1;; | 
|---|
| 114 | c) CONFIG="${OPTARG}";; | 
|---|
| 115 | d) OPT_POSTCMD=false;; | 
|---|
| 116 | n) OPT_MOUNT=0;; | 
|---|
| 117 | m) case "$OPTARG" in | 
|---|
| 118 | all) true;; | 
|---|
| 119 | live) OPT_STARTUP=0;; | 
|---|
| 120 | startup) OPT_RUNNING=0;; | 
|---|
| 121 | testing) OPT_RUNNING=0; OPT_STARTUP=0; OPT_MOUNT=0;; | 
|---|
| 122 | hack) OPT_RUNNING=0; OPT_STARTUP=0; OPT_HACK=1; USE_API=0;; | 
|---|
| 123 | *) usage;; | 
|---|
| 124 | esac;; | 
|---|
| 125 | h) usage;; | 
|---|
| 126 | \?) usage;; | 
|---|
| 127 | esac | 
|---|
| 128 | done | 
|---|
| 129 | # Allow to override automatic mounting, in case of external mount 'managment' | 
|---|
| 130 | if [ "$1" = "-n" ]; then | 
|---|
| 131 | OPT_MOUNT=0 | 
|---|
| 132 | fi | 
|---|
| 133 |  | 
|---|
| 134 | if [ "${OPT_RUNNING}" -eq 1 ]; then | 
|---|
| 135 | echo "# INFO: Storing new config files in running configuration" | 
|---|
| 136 | fi | 
|---|
| 137 |  | 
|---|
| 138 | if [ "${OPT_STARTUP}" -eq 1 ]; then | 
|---|
| 139 | echo "# INFO: Storing new config files in startup configuration" | 
|---|
| 140 | fi | 
|---|
| 141 |  | 
|---|
| 142 | if [ "${OPT_HACK}" -eq 1 ]; then | 
|---|
| 143 | echo "# WARN: Copy running configuration to startup configuration" | 
|---|
| 144 | echo "# WARN: Please do mind to document/mention this changes somewhere" | 
|---|
| 145 | fi | 
|---|
| 146 |  | 
|---|
| 147 | # New line before the real work gets started | 
|---|
| 148 | echo "" | 
|---|
| 149 | } | 
|---|
| 150 |  | 
|---|
| 151 |  | 
|---|
| 152 |  | 
|---|
| 153 |  | 
|---|
| 154 | # test validity of input | 
|---|
| 155 | config_validator() { | 
|---|
| 156 | INPUT="$1" | 
|---|
| 157 | `grep -q "^${INPUT}\$" ${TMPDIR}/node_list.txt` | 
|---|
| 158 | if [ $? -eq 0 ]; then | 
|---|
| 159 | return 0 | 
|---|
| 160 | else | 
|---|
| 161 | echo "WARNING: Input '${INPUT}' is not valid, some hints..." | 
|---|
| 162 | grep -i "${INPUT}" ${TMPDIR}/node_list.txt | 
|---|
| 163 | return 1 | 
|---|
| 164 | fi | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 |  | 
|---|
| 168 |  | 
|---|
| 169 | select_node() { | 
|---|
| 170 | # List of all available nodes | 
|---|
| 171 | fetch -q -o ${TMPDIR}/node_list.txt ${BASEURL} || exit 1 | 
|---|
| 172 |  | 
|---|
| 173 | if [ ${OPT_BATCH} -eq 1 ]; then | 
|---|
| 174 | config_validator "${CONFIG}" | 
|---|
| 175 | if [ $? -eq 1 ]; then | 
|---|
| 176 | echo "ERROR: Please provide valid config" 1>&2 | 
|---|
| 177 | exit 1 | 
|---|
| 178 | fi | 
|---|
| 179 | else | 
|---|
| 180 | # Provide Nodelist and feedback | 
|---|
| 181 | cat ${TMPDIR}/node_list.txt | column | 
|---|
| 182 | echo '       THIS script adds the config from GENESIS to this operating system' | 
|---|
| 183 | echo '       make sure you know what you are doing, if not press control-C' | 
|---|
| 184 | echo '       ENTER CONFIG NAME  ......(and press enter)' | 
|---|
| 185 |  | 
|---|
| 186 | # Have the user to select the right node | 
|---|
| 187 | INVALID_CONFIG=1 | 
|---|
| 188 | while [ ${INVALID_CONFIG} -eq 1 ]; do | 
|---|
| 189 | # Ask for node name, play around with prev option | 
|---|
| 190 | echo -n "Name [${CONFIG}]: " | 
|---|
| 191 | read INPUT | 
|---|
| 192 | if [ -z "${INPUT}" ]; then | 
|---|
| 193 | INPUT=${CONFIG} | 
|---|
| 194 | else | 
|---|
| 195 | CONFIG=${INPUT} | 
|---|
| 196 | fi | 
|---|
| 197 |  | 
|---|
| 198 | config_validator "${INPUT}" | 
|---|
| 199 | if [ $? -eq 0 ]; then | 
|---|
| 200 | INVALID_CONFIG=0 | 
|---|
| 201 | fi | 
|---|
| 202 | done | 
|---|
| 203 | fi | 
|---|
| 204 | } | 
|---|
| 205 |  | 
|---|
| 206 |  | 
|---|
| 207 |  | 
|---|
| 208 |  | 
|---|
| 209 | # Copy file, saving some bits if no change needed | 
|---|
| 210 | copy_file() { | 
|---|
| 211 | SOURCE=$1 | 
|---|
| 212 | TARGET=$2 | 
|---|
| 213 | diff -I '^FreeBSD ' -I '^# Generated at ' ${TARGET} ${SOURCE} 2>/dev/null | 
|---|
| 214 | if [ $? -ne 0 ]; then | 
|---|
| 215 | mkdir -p `dirname ${TARGET}` || exit 1 | 
|---|
| 216 | cp ${SOURCE} ${TARGET} || exit 1 | 
|---|
| 217 | return $? | 
|---|
| 218 | fi | 
|---|
| 219 | return 1 | 
|---|
| 220 | } | 
|---|
| 221 |  | 
|---|
| 222 | # Main function | 
|---|
| 223 | main() { | 
|---|
| 224 | TMPDIR=`mktemp -d -t $(basename $0)` | 
|---|
| 225 | # Clear out tempdir when done | 
|---|
| 226 | if [ ${OPT_MOUNT} -eq 1 ]; then | 
|---|
| 227 | trap "rm -Rf ${TMPDIR}; umount /cfg; mount -ro noatime /; exit" 0 1 2 3 15 | 
|---|
| 228 | else | 
|---|
| 229 | trap "rm -Rf ${TMPDIR}; exit" 0 1 2 3 15 | 
|---|
| 230 |  | 
|---|
| 231 | fi | 
|---|
| 232 |  | 
|---|
| 233 | # Mount if requested | 
|---|
| 234 | if [ ${OPT_MOUNT} -eq 1 ]; then | 
|---|
| 235 | mount -uwo noatime / | 
|---|
| 236 | mount /cfg | 
|---|
| 237 | fi | 
|---|
| 238 |  | 
|---|
| 239 | # Select node from web-interface | 
|---|
| 240 | if [ ${USE_API} -eq 1 ]; then | 
|---|
| 241 | select_node | 
|---|
| 242 | fi | 
|---|
| 243 |  | 
|---|
| 244 | # Worker, place all files in required directory | 
|---|
| 245 | for FILE in ${FILES}; do | 
|---|
| 246 | if [ ${USE_API} -eq 1 ]; then | 
|---|
| 247 | # Fetch needed file | 
|---|
| 248 | FRESH_LOC=${TMPDIR}/${FILE} | 
|---|
| 249 | fetch -q -o ${FRESH_LOC} ${BASEURL}/${CONFIG}/${FILE} || exit 1 | 
|---|
| 250 | fi | 
|---|
| 251 |  | 
|---|
| 252 | # Needed file details, like locations and hints | 
|---|
| 253 | file_details ${FILE} | 
|---|
| 254 |  | 
|---|
| 255 | echo "# INFO: Working on file: '${FILE}'" | 
|---|
| 256 | # Copy file boot location | 
|---|
| 257 | if [ ${OPT_STARTUP} -eq 1 ]; then | 
|---|
| 258 | copy_file ${FRESH_LOC} ${STARTUP_LOC} | 
|---|
| 259 | fi | 
|---|
| 260 |  | 
|---|
| 261 | # Copy file running location | 
|---|
| 262 | if [ ${OPT_RUNNING} -eq 1 ]; then | 
|---|
| 263 | copy_file ${FRESH_LOC} ${RUNNING_LOC} | 
|---|
| 264 | if [ $? -eq 0 ]; then | 
|---|
| 265 | echo "# INFO: '${FILE}' changed" | 
|---|
| 266 | if $OPT_POSTCMD && [ -n "${POST_CMD}" ]; then | 
|---|
| 267 | echo "## Running post_cmd: $POST_CMD" | 
|---|
| 268 | $POST_CMD | 
|---|
| 269 | fi | 
|---|
| 270 | if [ -n "${FILE_HINT}" ]; then | 
|---|
| 271 | echo "# INFO: For instant activate: ${FILE_HINT}" | 
|---|
| 272 | echo "" | 
|---|
| 273 | fi | 
|---|
| 274 | fi | 
|---|
| 275 | fi | 
|---|
| 276 |  | 
|---|
| 277 | # Direct copy | 
|---|
| 278 | if [ ${OPT_HACK} -eq 1 ]; then | 
|---|
| 279 | # No checking, just dumb try to copy mode | 
|---|
| 280 | cp -v ${RUNNING_LOC} ${STARTUP_LOC} | 
|---|
| 281 | fi | 
|---|
| 282 | done | 
|---|
| 283 |  | 
|---|
| 284 | exit 0 | 
|---|
| 285 | } | 
|---|
| 286 |  | 
|---|
| 287 | parse_options $* | 
|---|
| 288 | main | 
|---|