#!/bin/bash # Filename: terminalserver # Purpose: Program to do something # Authors: grml-team (grml.org), (c) Michael Gebetsroither # Bug-Reports: see http://grml.org/bugs/ # License: This file is licensed under the GPL v2. # Latest change: Sat Aug 06 14:14:40 CEST 2005 ################################################################################ ### ### __INCLUDES ### . /etc/grml/sh-lib #. /etc/grml/sysexits-sh ### ### __VARIABLES ### FORCE_='false' verbose_=0 # this file holds all variable definitions SHARED_PROG_VARS_="/usr/share/grml-terminalserver/shared_prog_vars" isExistent $SHARED_PROG_VARS_ die . $SHARED_PROG_VARS_ ### ### __FUNCTIONS ### function printUsage { cat < $PROG_NAME__ is the configuration program for the terminalserver provided by Grml. COMMANDS: help This help text start Start services (if all services are started, configs will be updated) stop Stop services config Update config of given service (or from all if no services given) clean Stop all + remove config and boot files from services interactive SERVICES: tftp Tftp daemon dhcp Dhcp daemon ipt Iptables setup (snat for clients) nfs All necessary nfs daemons <> ALL services OPTIONS: -v verbose (show what is going on, v++) -h this help text -f Force EOT } function killPortmapper { if [ -f /etc/init.d/portmap ] ; then /etc/init.d/portmap stop >/dev/null &>/dev/null elif [ -f /etc/init.d/rpcbind ] ; then /etc/init.d/rpcbind stop >/dev/null &>/dev/null fi killall -9 portmap &>/dev/null killall -9 rpcbind &>/dev/null } # DHCP SERVICE {{{ function createDhcpConf { if [ -e "$DHCPD_CONFIG_FILE_" ]; then if grep $CONFIG_PATTERN_ $DHCPD_CONFIG_FILE_ &>/dev/null; then execute "mv -fb \"$DHCPD_CONFIG_FILE_\" \"$DHCPD_CONFIG_FILE_.old\"" eprint &>/dev/null execute "source $TEMPLATE_CONFIG_DIR_/dhcpd_config" die else if [[ $FORCE_ == "true" ]]; then execute "mv -fb \"$DHCPD_CONFIG_FILE_\" \"$DHCPD_CONFIG_FILE_.old\"" eprint &>/dev/null execute "source $TEMPLATE_CONFIG_DIR_/dhcpd_config" die else warn "Not updating user edited configfile $DHCPD_CONFIG_FILE_, user -f to override" fi fi else execute "source $TEMPLATE_CONFIG_DIR_/dhcpd_config" die fi } function removeDhcpConf { if [ -e "$DHCPD_CONFIG_FILE_" ]; then if grep $CONFIG_PATTERN_ $DHCPD_CONFIG_FILE_ &>/dev/null; then rm -f "$DHCPD_CONFIG_FILE_" else if [[ $FORCE_ == "true" ]]; then rm -f "$DHCPD_CONFIG_FILE_" else warn "Not deleting user edited configfile $DHCPD_CONFIG_FILE_, user -f to override" fi fi fi } function stopDhcp { start-stop-daemon --stop --quiet --pidfile "$DHCPD_PID_" rm -f $DHCPD_PID_ # ugly but necessary :-/ find /var/lib/dhcp* -type f -name dhcpd.leases -delete local dhcpdir for dhcpdir in /var/lib/dhcp* ; do touch ${dhcpdir}/dhcpd.leases done } function startDhcp { local conf_file_="$DHCPD_CONFIG_FILE_" test -f $DHCPD_BIN_ || die "could not find dhcpd \"$DHCPD_BIN_\"" start-stop-daemon --start --quiet --pidfile "$DHCPD_PID_" \ --exec "$DHCPD_BIN_" -- -cf "$conf_file_" -q "$INTERFACE_" || warn "problems starting dhcpd" } function runDhcp { isExistent "$DHCPD_CONFIG_FILE_" || \ warn "no config for dhcpd: \"$DHCPD_CONFIG_FILE_\" => not starting dhcpd" || return 1 stopDhcp sleep 1 startDhcp } # }}} # IPTABLES {{{ function runIptables { if [[ $IPTABLES_SNAT_ != "true" ]]; then return fi startIptables } function startIptables { if [ -x $(command -v iptables) ] ; then if [[ $NAT_INTERFACE_ != "" ]]; then local nat_source_ip_=`netGetIp "$NAT_INTERFACE_" warn` if iptables -t nat -vnL POSTROUTING | grep -q "SNAT.*${NAT_INTERFACE_}.*to:${nat_source_ip_}" ; then echo "Rule for SNAT already present, nothing to be done." else echo "Setting up SNAT for terminalserver clients on ${NAT_INTERFACE_}:" echo "* iptables -t nat -F POSTROUTING" echo -n "* iptables -t nat -A POSTROUTING -o $NAT_INTERFACE_ -j SNAT --to-source $nat_source_ip_ ... " { iptables -t nat -F POSTROUTING && \ iptables -t nat -A POSTROUTING -o "$NAT_INTERFACE_" -j SNAT --to-source "$nat_source_ip_" ; } && \ echo done || echo failed fi if [ `cat /proc/sys/net/ipv4/ip_forward` -eq 1 ]; then echo "IP-Forwarding already enabled, nothing to be done." else echo -n "Enabling IP-Forwarding: " echo 1 > /proc/sys/net/ipv4/ip_forward && echo done || echo failed fi fi else warn "iptables executable not available" fi } function stopIptables { if [[ $IPTABLES_SNAT_ != "true" ]]; then return fi if [ -x $(command -v iptables) ] ; then if [[ $NAT_INTERFACE_ != "" ]]; then local nat_source_ip_=`netGetIp "$NAT_INTERFACE_" warn` if iptables -t nat -vnL POSTROUTING | grep -q "SNAT.*${NAT_INTERFACE_}.*to:${nat_source_ip_}" ; then iptables -t nat -F POSTROUTING &>/dev/null && \ iptables -t nat -D POSTROUTING -o "$NAT_INTERFACE_" -j SNAT --to-source "$nat_source_ip_" fi echo 0 > /proc/sys/net/ipv4/ip_forward fi fi } # }}} # TFTP SERVICE {{{ function removeTftpConf { rm -rf $TFTPD_DATA_DIR_/* } function createTftpConf { removeTftpConf execute "mkdir -p $TFTPD_DATA_DIR_/pxelinux.cfg" die if [ -r /usr/lib/PXELINUX/pxelinux.0 ] ; then execute "install -m 644 /usr/lib/PXELINUX/pxelinux.0 $TFTPD_DATA_DIR_" die else # older versions of syslinux-common (<= 2:4.05+dfsg-6+deb7u1): execute "install -m 644 /usr/lib/syslinux/pxelinux.0 $TFTPD_DATA_DIR_" die fi if [ -d "$MOUNT_POINT_"/boot/release ] ; then cp -r "$MOUNT_POINT_"/boot/release "$TFTPD_DATA_DIR_" fi [ -f "$MEMTEST_IMAGE" ] && execute "install -m 644 $MEMTEST_IMAGE_ $TFTPD_DATA_DIR_/memtest" die execute "install -m 644 $PXE_BOOT_MSG_ $TFTPD_DATA_DIR_" die [ -f "$PXE_BOOT_LOGO_" ] && execute "install -m 644 $PXE_BOOT_LOGO_ $TFTPD_DATA_DIR_" die # PXE / BIOS boot (pxelinux) execute "source $TEMPLATE_CONFIG_DIR_/grub-pxelinux_config" die # PXE / EFI boot (GRUB) execute "source $TEMPLATE_CONFIG_DIR_/grub-shim_config" die } function stopTftp { start-stop-daemon --stop --quiet -p "$TFTPD_PID_" --user nobody } function startTftp { test -f $TFTPD_BIN_ || die "could not find \"$TFTPD_BIN_\"" start-stop-daemon --start --quiet --exec "$TFTPD_BIN_" -- --daemon --no-multicast --pidfile "$TFTPD_PID_" --bind-address "$IP_" "$TFTPD_DATA_DIR_" || \ warn "problems starting tftpd server" } function runTftp { stopTftp sleep 1 startTftp } # }}} # NFS {{{ function createNfsConfig { execute "exportfs -o ro,no_root_squash,async,nohide,fsid=42 $NETWORK_/$NETMASK_:$MOUNT_POINT_" warn } function removeNfsConfig { execute "exportfs -u -o ro,no_root_squash,async,nohide,fsid=42 $NETWORK_/$NETMASK_:$MOUNT_POINT_" warn } function startNfs { if [ -f /etc/init.d/portmap ] ; then /etc/init.d/portmap start elif [ -f /etc/init.d/rpcbind ] ; then /etc/init.d/rpcbind start else echo "Warning: Could not start portmapper/rpcbind" >&2 fi /etc/init.d/nfs-common start # FIXME /etc/init.d/nfs-kernel-server start $USR_SHARE_/nfs-kernel-server start echo createNfsConfig } function stopNfs { removeNfsConfig if [[ `exportfs |wc -l` > 0 ]]; then dprint "There are other exports, not stopping NFS serivces" else /etc/init.d/nfs-kernel-server stop >/dev/null 2>&1 /etc/init.d/nfs-common stop >/dev/null 2>&1 killPortmapper fi } # }}} function createConfig { # FIXME execute "sed -i 's/^ALL/\#ALL/' /etc/hosts.deny" warn execute "sed -i 's/^ALL : ALL@ALL : DENY/ALL : ALL@ALL : ALLOW/' /etc/hosts.allow" warn createTftpConf createDhcpConf } function actionStart { createConfig echo -n "Starting tftpd: " runTftp && echo done || echo failed echo -n "Starting dhcpd: " runDhcp && echo done || echo failed runIptables echo "Finally starting nfs services..." startNfs && echo "Successfully finished startup of grml-terminalserver." || echo 'Startup of grml-terminalserver failed!' } function actionStop { stopTftp stopDhcp stopIptables stopNfs notice "Terminal-server stopped" } function actionClean { actionStop removeTftpConf removeDhcpConf stopNfs } function updateConfig { local service_="$1" case "$service_" in "") createConfig ;; tftp) createTftpConf ;; dhcp) createDhcpConf ;; nfs) removeNfsConfig; createNfsConfig ;; *) warn "Service $service_ not available" ;; esac } # SERVICES {{{ function serviceStart { local service_="$1" # service to start, if nothing => all case "$service_" in "") actionStart ;; tftp) runTftp ;; dhcp) runDhcp ;; ipt) startIptables ;; nfs) startNfs ;; *) warn "Service $service_ not available" ;; esac } function serviceStop { local service_="$1" # service to stop, if nothing => all case "$service_" in "") actionStop ;; tftp) stopTftp ;; dhcp) stopDhcp ;; ipt) stopIptables ;; nfs) stopNfs ;; *) warn "Service $service_ not available" ;; esac } # }}} ### ### __MAIN ### while getopts "fi:hv" opt; do case "$opt" in f) FORCE_='true' ;; h) printUsage; exit ;; v) let verbose_=$verbose_+1 ;; ?) printUsage; exit 64 ;; esac done shift $(($OPTIND - 1)) # set ARGV to the first not parsed commandline parameter setVerbose $verbose_ case "$1" in help) printUsage; exit 0 ;; esac checkRoot die "You have to be root to use this program" disableSyslog isExistent $DEFAULT_CONFIG_ die . $DEFAULT_CONFIG_ . $CONFIG_ # used config vars: # MOUNT_POINT_ # MEMTEST_IMAGE_ # PXE_BOOT_MSG_ # PXE_BOOT_LOGO_ if [[ $MOUNT_POINT_ == "" || $MEMTEST_IMAGE_ == "" || \ $PXE_BOOT_MSG_ == "" || $PXE_BOOT_MSG_ == "" ]]; then warn "MOUNT_POINT_=\"$MOUNT_POINT_\" \ MEMTEST_IMAGE_=\"$MEMTEST_IMAGE_\" PXE_BOOT_MSG_=\"$PXE_BOOT_MSG_\" PXE_BOOT_LOGO_=\"$PXE_BOOT_LOGO_\"" die "False configuration, please update $CONFIG_" fi case "$1" in clean) actionClean; exit 0 ;; esac while true; do isExistent "$CONF_FILE_" warn "sorry configfile \"$CONF_FILE_\" not found" if [ $? -eq 1 ]; then $CONFIG_PROG_ && continue $DIALOG_ --clear --backtitle "$BACK_TITLE_" --title "Question" --yesno \ "grml-terminalserver-config returned an error, do you want to quit now?" 5 75 && exit 1 else break fi done source $CONF_FILE_ # check for necessary files check_necessary_files_='no' if [ "$1" == 'start' ]; then case "$2" in tftp|"") check_necessary_files_='yes' ;; esac fi if [ $check_necessary_files_ == 'yes' ]; then # test for files absolutely necessary for grml-terminalserver and created from -config problem_=0 for i in $PATH_/initrd.img; do isExistent $i warn || problem_=1 done if [ $problem_ -eq 1 ]; then die 'Some necessary files are missing, please rerun grml-terminalserver-config, or copy the files manually' fi fi case "$1" in start) serviceStart "$2" ;; stop) serviceStop "$2" ;; config) updateConfig "$2" ;; "") actionStart ;; *) printUsage ;; esac # END OF FILE ################################################################################ # vim:foldmethod=marker tabstop=2 expandtab shiftwidth=2