#!/bin/sh # Wireless Leiden config-update script for FreeBSD 8.0 (nanobsd) # Based on the 'API' of Jasper # Rick van der Zwet # XXX: TODO, some proper error checking for fetch # Slow connection = no connection export HTTP_TIMEOUT=10 check_access() { # Direct Access - External BASEURL="http://wirelessleiden.nl/config/" fetch -o /dev/null -q $BASEURL > /dev/null && return echo "# WARN: Fetch via external $BASEURL failed" # Direct Access - Internal IP BASEURL="http://172.16.4.46/wleiden/config/" # Connectivity check fetch -o /dev/null -q $BASEURL > /dev/null && return echo "# WARN: Fetch via internal $BASEURL failed" # Direct Access - External DNS BASEURL="http://132.229.112.21/wleiden/config/" fetch -o /dev/null -q $BASEURL > /dev/null && return echo "# CRIT: Fetch via external $BASEURL failed" exit 1 } check_access # Default config to fetch CONFIG=`hostname -s` # Determine it's statup and running location and some other hints # Skip named.conf as it not planned in current release, making sure resolv.conf # is altered at the end, since having to replace this file will cause next files # not be downloaded anymore if no (currently) valid resolver can be found anymore. # TODO(rvdz): Download files _before_ changes # FILES="authorized_keys dhcpd.conf dnsmasq.conf motd rc.conf.local pf.hybrid.conf.local wleiden.yaml resolv.conf" file_details() { POST_CMD="" FILE_HINT="" case "$1" in 'authorized_keys') STARTUP_LOC="/cfg/ssh/${FILE}" RUNNING_LOC="/etc/ssh/${FILE}" ;; 'dhcpd.conf') STARTUP_LOC="/cfg/local/${FILE}" RUNNING_LOC="/usr/local/etc/${FILE}" POST_CMD="service isc-dhcpd restart" ;; 'dnsmasq.conf') STARTUP_LOC="/cfg/local/${FILE}" RUNNING_LOC="/usr/local/etc/${FILE}" POST_CMD="service dnsmasq restart" ;; 'motd') STARTUP_LOC="/cfg/${FILE}" RUNNING_LOC="/etc/${FILE}" POST_CMD="/etc/rc.d/motd onestart" ;; 'named.conf') STARTUP_LOC="/cfg/namedb/${FILE}" RUNNING_LOC="/etc/namedb/${FILE}" POST_CMD="service named restart" ;; 'rc.conf.local') STARTUP_LOC="/cfg/${FILE}" RUNNING_LOC="/etc/${FILE}" FILE_HINT="Restart interfaces with: nohup service netif restart" ;; 'resolv.conf') STARTUP_LOC="/cfg/${FILE}" RUNNING_LOC="/etc/${FILE}" FILE_HINT="To get the ordering right run: nameserver-shuffle" ;; 'pf.hybrid.conf.local') STARTUP_LOC="/cfg/${FILE}" RUNNING_LOC="/etc/${FILE}" POST_CMD="service pf reload" ;; 'wleiden.yaml') STARTUP_LOC="/cfg/local/${FILE}" RUNNING_LOC="/usr/local/etc/${FILE}" ;; esac } usage() { ( echo "Usage: $0 [-bpn] [-c ] [-m ]" echo " -b = batch mode, no user input" echo " -c = default configuration to fetch" echo " -d = do not run the POST_CMD commands [default]" echo " -p = run the POST_CMD commands to activate the services right-away" echo " -n = do not mount config partition" echo " -m all = copy config files to running & config partition [default]" echo " -m startup = copy config files to config partition" echo " -m testing = do not copy config files" echo " -m running = copy config files to running partition" echo " -m hack = copy running files to config partition" ) 1>&2 exit 2 } # Argument parsing using getopts USE_API=1 # Whether or not to use the webinterface OPT_MOUNT=1 OPT_RUNNING=1 OPT_STARTUP=1 OPT_HACK=0 # Hack for people without configuration managment and testing OPT_BATCH=0 OPT_POSTCMD=false parse_options() { while getopts "bc:nm:dp" OPT; do case "$OPT" in b) OPT_BATCH=1;; c) CONFIG="${OPTARG}";; d) OPT_POSTCMD=false;; n) OPT_MOUNT=0;; m) case "$OPTARG" in all) true;; live) OPT_STARTUP=0;; startup) OPT_RUNNING=0;; testing) OPT_RUNNING=0; OPT_STARTUP=0; OPT_MOUNT=0;; hack) OPT_RUNNING=0; OPT_STARTUP=0; OPT_HACK=1; USE_API=0;; *) usage;; esac;; h) usage;; p) OPT_POSTCMD=true;; \?) usage;; esac done # Allow to override automatic mounting, in case of external mount 'managment' if [ "$1" = "-n" ]; then OPT_MOUNT=0 fi if [ "${OPT_RUNNING}" -eq 1 ]; then echo "# INFO: Storing new config files in running configuration" fi if [ "${OPT_STARTUP}" -eq 1 ]; then echo "# INFO: Storing new config files in startup configuration" fi if [ "${OPT_HACK}" -eq 1 ]; then echo "# WARN: Copy running configuration to startup configuration" echo "# WARN: Please do mind to document/mention this changes somewhere" fi if /bin/df / | grep -q "^/dev/md[0-9]"; then OPT_MOUNT=0 echo "# WARN: Mount operations disabled as we are running in a md(4) image" fi # New line before the real work gets started echo "" } # test validity of input config_validator() { INPUT="$1" `grep -q "^${INPUT}\$" ${TMPDIR}/node_list.txt` if [ $? -eq 0 ]; then return 0 else echo "WARNING: Input '${INPUT}' is not valid, some hints..." grep -i "${INPUT}" ${TMPDIR}/node_list.txt return 1 fi } select_node() { # List of all available nodes fetch -q -o ${TMPDIR}/node_list.txt ${BASEURL} || exit 1 if [ ${OPT_BATCH} -eq 1 ]; then config_validator "${CONFIG}" if [ $? -eq 1 ]; then echo "ERROR: Please provide valid config" 1>&2 exit 1 fi else # Provide Nodelist and feedback cat ${TMPDIR}/node_list.txt | column echo ' THIS script adds the config from GENESIS to this operating system' echo ' make sure you know what you are doing, if not press control-C' echo ' ENTER CONFIG NAME ......(and press enter)' # Have the user to select the right node INVALID_CONFIG=1 while [ ${INVALID_CONFIG} -eq 1 ]; do # Ask for node name, play around with prev option echo -n "Name [${CONFIG}]: " read INPUT if [ -z "${INPUT}" ]; then INPUT=${CONFIG} else CONFIG=${INPUT} fi config_validator "${INPUT}" if [ $? -eq 0 ]; then INVALID_CONFIG=0 fi done fi } # Copy file, saving some bits if no change needed copy_file() { SOURCE=$1 TARGET=$2 diff -I '^FreeBSD ' -I '^# Generated at ' ${TARGET} ${SOURCE} 2>/dev/null if [ $? -ne 0 ]; then mkdir -p `dirname ${TARGET}` || exit 1 cp ${SOURCE} ${TARGET} || exit 1 return $? fi return 1 } # Main function main() { TMPDIR=`mktemp -d -t $(basename $0)` # Clear out tempdir when done if [ ${OPT_MOUNT} -eq 1 ]; then trap "rm -Rf ${TMPDIR}; umount /cfg; mount -ro noatime /; exit" 0 1 2 3 15 else trap "rm -Rf ${TMPDIR}; exit" 0 1 2 3 15 fi # Mount if requested if [ ${OPT_MOUNT} -eq 1 ]; then mount -uwo noatime / mount /cfg fi # Select node from web-interface if [ ${USE_API} -eq 1 ]; then select_node fi # Worker, place all files in required directory for FILE in ${FILES}; do if [ ${USE_API} -eq 1 ]; then # Fetch needed file FRESH_LOC=${TMPDIR}/${FILE} fetch -q -o ${FRESH_LOC} ${BASEURL}/${CONFIG}/${FILE} || exit 1 fi # Needed file details, like locations and hints file_details ${FILE} echo "# INFO: Working on file: '${FILE}'" # Copy file boot location if [ ${OPT_STARTUP} -eq 1 ]; then copy_file ${FRESH_LOC} ${STARTUP_LOC} fi # Copy file running location if [ ${OPT_RUNNING} -eq 1 ]; then copy_file ${FRESH_LOC} ${RUNNING_LOC} if [ $? -eq 0 ]; then echo "# INFO: '${FILE}' changed" if [ -n "${POST_CMD}" ]; then if $OPT_POSTCMD; then echo "## Running post_cmd: $POST_CMD" $POST_CMD else echo "## To activate run the post_cmd: $POST_CMD" fi fi if [ -n "${FILE_HINT}" ]; then echo "# INFO: ${FILE_HINT}" echo "" fi fi fi # Direct copy if [ ${OPT_HACK} -eq 1 ]; then # No checking, just dumb try to copy mode cp -v ${RUNNING_LOC} ${STARTUP_LOC} fi done exit 0 } parse_options $* main