#!/bin/sh # #!F:triggersit-ip6 # #!P:/usr/local/bin # #!S:root:root 555 # #!D:Client program to trigger "ctrlsit-ip6" on an IPv6 tunnelserver # #!C:Copyright 1997-2001 Peter Bieringer # # You will find more information of sitctrl at # http://www.bieringer.de/linux/IPv6/sitctrl/ # And also more general information in the IPv6-HowTo for Linux at # http://www.bieringer.de/linux/IPv6/ # # Changes to # 1.02: Options now in UNIX style, root and users have now different access # 1.11: Some corrections # 1.12: Add new option to run as root, but login as user # Test if IPv4 address on interface exists # Add new option to change the tunnel IPv4 address # Add new option to change the device # More help # 1.13: Test for existing ssh, Correct input device for ssh # 1.14: Info display # 1.15: Help is also with option '-?' availible # 1.17: Fix: Exit if host is not running IPv6 # 20000720: Review for RedHat 6.2, see new hints at # (no longer a patched ssh is needed) # 20000722: New option handling, changed: '-d devname' to '-i devname' # new: '-d debuglevel' # some checks # 20000824: Add a lock file to detect a hanging script # 20001007: Set full path to "sudo" # 20010103: Add ping test to remote tunnel (to disable with '-np') # Test, if specified interface exists, add a beep mode (dis: -nb) # Add auto-optional beeper for background execution # (i.e. run by ip-up.local) # Change message output to log style, add option for a log file # (only really usable by root), options -lf, -ulf, -ll # Extend exit code handling # 20000104: Change logfile handling to syslog usage # Change path of lock file for usable by non root users # 20000106: Minor fixes ##--------------- need to review below this line (can also be changed by the use of options) # Name of syslog facility DEFAULT_SyslogFacility="daemon" # Run a IPv4 ping test to remote tunnel IP before doing the rest DEFAULT_IPv4PingTest="yes" # Default debug option DEFAULT_DEBUG="0" # Default beep mode DEFAULT_BeepMode="yes" # Specify the IPv4 address of your friendly tunnelendpoint DEFAULT_TUNNEL="195.226.187.50" # Specify the network interface (device) of your host connected to the Internet # needed to grab the dynamic assigned IPv4 address of your dialup connection DEFAULT_DEVNAME="ippp1" ##---- Defines of binaries, normally not to be reviewed (on RedHat 6.2 systems) # Specify binary of 'ssh' (Secure SHell client) BIN_SSH="/usr/bin/ssh" # Specify binary of 'whoami' BIN_WHOAMI="/usr/bin/whoami" # Specify binary of 'su' BIN_SU="/bin/su" # Specify binary of 'touch' BIN_TOUCH="/bin/touch" # Specify binary of 'rm' BIN_RM="/bin/rm" # Specify binary of 'echo' BIN_ECHO="/bin/echo" # Specify binary of 'ping' BIN_PING="/bin/ping" # Specify binary of 'sleep' BIN_SLEEP="/bin/sleep" # Specify binary of 'cat' BIN_CAT="/bin/cat" # Specify binary of 'ps' BIN_PS="/bin/ps" # Specify binary of 'logger' BIN_LOGGER="/usr/bin/logger" # Specify binary of 'beep' (optional, see http://www.johnath.com/beep/ for package) BIN_BEEP="/usr/bin/beep" # Specify path to sudo on remote site BINREMOTE_SUDO="/usr/bin/sudo" ##---- Related defines, normally not to be reviewed below this line # Specify the program on the remote tunnel server SCRIPT_CTRLSIT="/usr/local/sbin/ctrlsit-ip6" # Lockfile to detect hanging a script of last dial-up FILE_LOCK="/tmp/triggersit-ip6.lock.`$BIN_WHOAMI`" # Name for logging LOGNAME="triggersit-ip6" # Name of temp file for su executed ssh exit code FILE_EXITCODE="/tmp/triggersit-ip6.su.`$BIN_WHOAMI`" ##--------------- normally nothing to change below this line # Set umask to prevent race conditions umask 077 # Displays information function info() { grep "^#!D" $0 | sed 's/^#!D://g' >&2 grep "^#!C" $0 | sed 's/^#!C://g' >&2 grep "^#!V" $0 | sed 's/^#!V://g' >&2 echo } # Help information function help() { cat <&2 fi if ! [ "$OPTION_QUIET" = "0" ]; then echo "$loginfo: $logmessage" >&2 else echo "$logmessage" >&2 fi fi } # Function "Get options" function getoptions() { # Returnvalue 1: display help OPTION_QUIET="0" OPTION_UseSyslog="no" OPTION_FORCE="0" OPTION_DEBUG="$DEFAULT_DEBUG" OPTION_IPv4PingTest="$DEFAULT_IPv4PingTest" OPTION_BeepMode="$DEFAULT_BeepMode" while [ ! -z "$1" ]; do # strip "-" OPTION=`echo $1 | sed 's/^-//g'` #echo $OPTION if [ "$OPTION" = '?' -o "$OPTION" = 'h' ]; then return 1 elif [ "$OPTION" = 'u' ]; then shift if [ $# -ge 1 ]; then OPTION_USER="$1" shift else log err "Missing user!" return 1 fi elif [ "$OPTION" = 'l' ]; then shift if [ $# -ge 1 ]; then OPTION_LOGIN="$1" shift else log err "Missing loginname!" return 1 fi elif [ "$OPTION" = 't' ]; then shift if [ $# -ge 1 ]; then OPTION_TUNNEL="$1" shift else log err "Missing tunnel (hostname or IP address)!" return 1 fi elif [ "$OPTION" = "i" ]; then shift if [ $# -ge 1 ]; then OPTION_DEVNAME="$1" shift else log err "Missing interface name!" return 1 fi elif [ "$OPTION" = "ip" ]; then shift if [ $# -ge 1 ]; then OPTION_DEVIP4="$1" shift else log err "Missing IPv4 address!" return 1 fi elif [ "$OPTION" = "ipv6" ]; then shift if [ $# -ge 1 ]; then OPTION_IPV6="$1" shift else log err "Missing IPv6 address!" return 1 fi elif [ "$OPTION" = "c" ]; then shift if [ $# -ge 1 ]; then OPTION_CMD="$1" shift else log err "Missing command!" return 1 fi elif [ "$OPTION" = "d" ]; then shift if [ $# -ge 1 ]; then OPTION_DEBUG="$1" shift else log err "Missing debug level!" return 1 fi elif [ "$OPTION" = "slf" ]; then shift if [ $# -ge 1 ]; then OPTION_SyslogFacility="$1" shift else log err "Missing syslog facility name!" return 1 fi elif [ "$OPTION" = "q" ]; then # Option quiet OPTION_QUIET="1" shift elif [ "$OPTION" = "f" ]; then # Option force OPTION_FORCE="1" shift elif [ "$OPTION" = "np" ]; then # Option ping test OPTION_IPv4PingTest="no" shift elif [ "$OPTION" = "nb" ]; then # Option beep mode OPTION_BeepMode="no" shift elif [ "$OPTION" = "usl" ]; then # Option use syslog OPTION_UseSyslog="yes" shift else log err "Option '$1' isn't understood!" return 1 fi done } # Function for lock file function create_lockfile () { # Remove old lock file $BIN_RM -rf $FILE_LOCK # Create new lock file $BIN_TOUCH $FILE_LOCK # Write PID of script in lock file $BIN_ECHO $$ >>$FILE_LOCK } function remove_lockfile () { # Remove lock file $BIN_RM -f $FILE_LOCK } # Beep functions for background execution, i.e. for use in ip-up.local function do_beep() { code=$1 if [ "$OPTION_BeepMode" = "yes" ]; then # beep relating to exit codes if [ ! -z "$BIN_BEEP" ] ; then # use of a controllable beeper case $code in 0) # success $BIN_BEEP -f 2000 & ;; 1) # option error $BIN_BEEP -f 500 -n -f 250 -n -f 125 & ;; 2) # mandatory error $BIN_BEEP -f 500 -r 5 & ;; 3) # temp error $BIN_BEEP -f 500 -n -f 250 & ;; esac else case $code in 0) # success (echo -en "\a" >/dev/console) & ;; 1) # option error (echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console) & ;; 2) # mandatory error (echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console) & ;; 3) # temp error (echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console; sleep 1; echo -en "\a" >/dev/console) & ;; esac fi fi } ####--------------------------------- Start # Get options (before IPv6 testing, so you can read help) getoptions $* if [ $? -gt 0 ]; then info help do_beep 1 exit 1 fi #Test whether syslog facility, default is $DEFAULT_SyslogFacility if [ -z "$OPTION_SyslogFacility" ] ; then OPTION_SyslogFacility=$DEFAULT_SyslogFacility fi # Show information if ! [ "$OPTION_QUIET" = "1" ]; then info else log notice "Triggering starts now" fi #Test whether needed binares exist for testbin in $BIN_SSH $BIN_WHOAMI $BIN_SU $BIN_TOUCH $BIN_RM $BIN_ECHO $BIN_PING $BIN_SLEEP $BIN_CAT $BIN_PS $BIN_LOGGER; do if [ ! -x $testbin ]; then log err "Needed binary '$testbin' missing, check whether installed or change location in this script!" do_beep 2 exit 2 fi done # Test for optional beeper if [ ! -x $BIN_BEEP ]; then BIN_BEEP="" elif [ "$OPTION_BeepMode" = "yes" ]; then # Test, if beep can be executed by user if ! $BIN_BEEP -l 1 -f 10 >/dev/null 2>&1; then log warn "The beeper binary '$BIN_BEEP' has not set the SUID bit, users cannot" log notice " trigger the sound output!" log notice "You can fix this by executing 'chmod u+s $BIN_BEEP' but keep in mind that" log notice " this can be a local securtiy hole - for now turn back to simple console beep!" BIN_BEEP="" fi fi # Beep mode tester if [ ! $[ $OPTION_DEBUG & 16 ] = 0 ]; then log notice "Beep mode tester" OPTION_BeepMode="yes" if [ -z "$BIN_BEEP" ]; then log err "Sorry, beep binary doesn't exist, see http://www.johnath.com/beep/ for information" exit 2 fi CODE_BEEP=$[ $OPTION_DEBUG & 7 ] log notice "Code for beeper is '$CODE_BEEP'" do_beep $CODE_BEEP exit 1 fi # Hanging script simulator if [ ! $[ $OPTION_DEBUG & 8 ] = 0 ]; then log notice "You choosed a debug value for simulating a hanging script..." log notice " Create lock file '$FILE_LOCK' now and sleep 1000 s..." create_lockfile PID_RUN="$$" log notice " PID of running script is $PID_RUN" C=0 while [ $C -lt 1000 ]; do $BIN_SLEEP 1 C=$[ $C + 1 ] done remove_lockfile log notice " awaken and lock file removed!" do_beep 3 exit 3 fi # Test whether lock file exists if [ -f $FILE_LOCK ]; then log notice "Lock file of a previous execution exists, perhaps the script is hanging!" if [ "$OPTION_FORCE" = "0" ]; then log err " Check this or use '-f'!" exit 3 else log notice " Try to kill old script!" PID_OLD="`$BIN_CAT $FILE_LOCK`" log info " Old script should have PID '$PID_OLD', check it now" if $BIN_PS --no-heading $PID_OLD | grep -q "triggersit-ip6"; then kill $PID_OLD $BIN_SLEEP 1 # Still alive? if $BIN_PS --no-heading $PID_OLD | grep -q "triggersit-ip6"; then kill -9 $PID_OLD $BIN_SLEEP 1 fi if $BIN_PS --no-heading $PID_OLD | grep -q "triggersit-ip6"; then log err " Kill of old script not successful!" else log info " Kill of old script succesful!" fi else log info " PID doesn't match utility" >&2 fi remove_lockfile fi fi # Test for IPv6 kernel if ! [ -f /proc/net/if_inet6 ]; then log err "Kernel not compiled for IPv6 - please fix this - stop!" do_beep 2 exit 2 fi # WhoAmI VAL_WHOAMI=`$BIN_WHOAMI` if [ -z "$VAL_WHOAMI" ]; then log err "Result of 'whoami' is empty - very strange!" do_beep 2 exit 2 fi #Test whether account given, default is $LOGNAME if [ -z "$OPTION_USER" ] ; then OPTION_USER=$VAL_WHOAMI fi #Test whether login is given, default is $OPTION_USER if [ -z "$OPTION_LOGIN" ] ; then OPTION_LOGIN=$OPTION_USER fi #Test whether tunnel address is given, default is $DEFAULT_TUNNEL if [ -z "$OPTION_TUNNEL" ] ; then OPTION_TUNNEL=$DEFAULT_TUNNEL fi #Test whether device is given, default is $DEFAULT_DEVNAME if [ -z "$OPTION_DEVNAME" ] ; then OPTION_DEVNAME=$DEFAULT_DEVNAME fi # Set default option if [ -z "$OPTION_CMD" ] ; then OPTION_CMD="new" fi # Show info log info "User : '$OPTION_USER'" log info "Login : '$OPTION_LOGIN'" log info "Tunnel : '$OPTION_TUNNEL'" log info "PingTest : '$OPTION_IPv4PingTest'" log info "Device : '$OPTION_DEVNAME'" if [ "$OPTION_DEBUG" -gt 0 ]; then log notice "Debuglevel : '$OPTION_DEBUG'" else log info "Debuglevel : '$OPTION_DEBUG'" fi log info "BeepMode : '$OPTION_BeepMode'" log info "UseSyslog : '$OPTION_UseSyslog'" log info "SyslogFacility: '$OPTION_SyslogFacility'" # Now we start to work with the network, create lock file now create_lockfile #Test whether an IPv4 address is given, default is the device's one if [ -z $OPTION_DEVIP4 ] ; then # Test, whether given interface exists if ! grep -q "$OPTION_DEVNAME:" /proc/net/dev; then log err "Given interface '$OPTION_DEVNAME' doesn't exist - stop!" remove_lockfile do_beep 1 exit 1 fi # Get own IPv4 address for the interface connected to the Internet # (This is surely not the best method, but an easy one...) OPTION_DEVIP4=`/sbin/ifconfig $OPTION_DEVNAME | grep "inet addr:" | awk -F ":" '{ print $2 }' | awk '{ print $1 }'` # Address valid? if [ -z $OPTION_DEVIP4 ] ; then log err "No IPv4 address is given on device '$OPTION_DEVNAME'!" log err " Possible you haven't dial up until now!\n" remove_lockfile do_beep 3 exit 3 fi fi log info "IPv4 : '$OPTION_DEVIP4'" # Build option string OPTIONS="-c $OPTION_CMD -u $OPTION_USER" if [ ! -z $OPTION_IPV6 ]; then OPTIONS="$OPTIONS -ipv6 $OPTION_IPV6" log info "IPv6 : '$OPTION_IPV6'" fi # Add IPv4 address, if command is "new" if [ "$OPTION_CMD" = "new" ]; then OPTIONS="$OPTIONS -ip $OPTION_DEVIP4" fi # Add server script name OPTIONS="$SCRIPT_CTRLSIT $OPTIONS" # If not 'root', add 'sudo' option if ! [ "$OPTION_LOGIN" = "root" ]; then OPTIONS="$BINREMOTE_SUDO $OPTIONS" fi # Show options log debug "Secure shell options are: '$OPTIONS'" # Now run IPv4 ping test if enabled if [ "$OPTION_IPv4PingTest" = "yes" -o "$OPTION_IPv4PingTest" = "1" ]; then log info "Run IPv4 ping test [5 tries] to '$OPTION_TUNNEL'" >&2 VAL_ERROR=`$BIN_PING -q -n -c 5 $OPTION_TUNNEL | grep "%" | awk -F% '{ print $1 }' | awk '{ print $NF }'` log info " Packet loss: $VAL_ERROR %" if [ "$VAL_ERROR" = "100" ]; then # remote tunnel endpoint not reachable through IPv4, skip log err "Oh, remote tunnel '$OPTION_TUNNEL' not reachable, stop trigger!" remove_lockfile do_beep 3 exit 3 fi fi ### Now build up connection log debug "Trigger IPv6 tunnel server by ssh [perhaps you have to enter your password/passphrase]" # Show tunnel endpoint log debug "Now a connection to '$OPTION_TUNNEL' is build up, login is '$OPTION_LOGIN'" # Remove exit code file, if exits $BIN_RM -rf $FILE_EXITCODE code=0 code2=0 if [ $[ $OPTION_DEBUG & 1 ] = 0 ]; then if ! [ "$OPTION_QUIET" = "1" ]; then if [ "$OPTION_LOGIN" != "$VAL_WHOAMI" ]; then $BIN_SU - $OPTION_LOGIN -c "$BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL \"$OPTIONS\"; echo \$? >$FILE_EXITCODE" code2="$?" if [ -f $FILE_EXITCODE ]; then code=`cat $FILE_EXITCODE` fi else $BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL "$OPTIONS" code="$?" fi else if [ "$OPTION_LOGIN" != "$VAL_WHOAMI" ]; then $BIN_SU - $OPTION_LOGIN -c "$BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL \"$OPTIONS\" >/dev/null 2>&1; echo \$? >$FILE_EXITCODE" code2="$?" if [ -f $FILE_EXITCODE ]; then code=`cat $FILE_EXITCODE` fi else $BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL "$OPTIONS" >/dev/null 2>&1 code="$?" fi fi else # Display debug output log info "Debug set to 'dry-run', here is the not executed command shown:" if [ "$OPTION_LOGIN" != "$VAL_WHOAMI" ]; then log info "$BIN_SU - $OPTION_LOGIN -c \"$BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL \"$OPTIONS\"\"" else log info "$BIN_SSH -l $OPTION_LOGIN $OPTION_TUNNEL \"$OPTIONS\"" fi fi if [ $[ $OPTION_DEBUG & 1 ] = 0 ]; then if [ "$OPTION_LOGIN" != "$VAL_WHOAMI" ]; then $BIN_RM -rf $FILE_EXITCODE log debug "Exit code of su is '$code2'" fi log debug "Exit code of ssh is '$code'" if [ "$code" != "0" -o "$code2" != "0" ]; then log err "Exit code '$code/$code2' - trigger not successful!" remove_lockfile do_beep 3 exit 3 else log notice "Trigger succesful!" fi else log debug "Trigger ran in dry-run mode!" fi if [ "$OPTION_BeepMode" = "yes" ]; then if [ $[ $OPTION_DEBUG & 1 ] = 0 ]; then # not in dry-run mode do_beep 0 fi fi remove_lockfile