"Fossies" - the Fresh Open Source Software Archive

Member "vpnc-0.5.3/vpnc-script.in" (19 Nov 2008, 14993 Bytes) of package /linux/privat/old/vpnc-0.5.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bash source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #!/bin/sh
    2 #* reason                       -- why this script was called, one of: pre-init connect disconnect
    3 #* VPNGATEWAY                   -- vpn gateway address (always present)
    4 #* TUNDEV                       -- tunnel device (always present)
    5 #* INTERNAL_IP4_ADDRESS         -- address (always present)
    6 #* INTERNAL_IP4_NETMASK         -- netmask (often unset)
    7 #* INTERNAL_IP4_NETMASKLEN      -- netmask length (often unset)
    8 #* INTERNAL_IP4_NETADDR         -- address of network (only present if netmask is set)
    9 #* INTERNAL_IP4_DNS             -- list of dns serverss
   10 #* INTERNAL_IP4_NBNS            -- list of wins servers
   11 #* CISCO_DEF_DOMAIN             -- default domain name
   12 #* CISCO_BANNER                 -- banner from server
   13 #* CISCO_SPLIT_INC              -- number of networks in split-network-list
   14 #* CISCO_SPLIT_INC_%d_ADDR      -- network address
   15 #* CISCO_SPLIT_INC_%d_MASK      -- subnet mask (for example: 255.255.255.0)
   16 #* CISCO_SPLIT_INC_%d_MASKLEN   -- subnet masklen (for example: 24)
   17 #* CISCO_SPLIT_INC_%d_PROTOCOL  -- protocol (often just 0)
   18 #* CISCO_SPLIT_INC_%d_SPORT     -- source port (often just 0)
   19 #* CISCO_SPLIT_INC_%d_DPORT     -- destination port (often just 0)
   20 
   21 # FIXMEs:
   22 
   23 # Section A: route handling
   24 
   25 # 1) The 3 values CISCO_SPLIT_INC_%d_PROTOCOL/SPORT/DPORT are currently being ignored
   26 #   In order to use them, we'll probably need os specific solutions
   27 #   * Linux: iptables -t mangle -I PREROUTING <conditions> -j ROUTE --oif $TUNDEV
   28 #       This would be an *alternative* to changing the routes (and thus 2) and 3)
   29 #       shouldn't be relevant at all)
   30 # 2) There are two different functions to set routes: generic routes and the
   31 #   default route. Why isn't the defaultroute handled via the generic route case?
   32 # 3) In the split tunnel case, all routes but the default route might get replaced
   33 #   without getting restored later. We should explicitely check and save them just
   34 #   like the defaultroute
   35 # 4) Replies to a dhcp-server should never be sent into the tunnel
   36 
   37 # Section B: Split DNS handling
   38 
   39 # 1) Maybe dnsmasq can do something like that
   40 # 2) Parse dns packets going out via tunnel and redirect them to original dns-server
   41 
   42 #env | sort
   43 #set -x
   44 
   45 # =========== script (variable) setup ====================================
   46 
   47 PATH=/sbin:/usr/sbin:$PATH
   48 
   49 OS="`uname -s`"
   50 
   51 DEFAULT_ROUTE_FILE=/var/run/vpnc/defaultroute
   52 RESOLV_CONF_BACKUP=/var/run/vpnc/resolv.conf-backup
   53 FULL_SCRIPTNAME=@PREFIX@/sbin/vpnc
   54 SCRIPTNAME=`basename $FULL_SCRIPTNAME`
   55 
   56 # some systems, eg. Darwin & FreeBSD, prune /var/run on boot
   57 if [ ! -d "/var/run/vpnc" ]; then
   58     mkdir -p /var/run/vpnc
   59 fi
   60 
   61 # stupid SunOS: no blubber in /usr/local/bin ... (on stdout)
   62 IPROUTE="`which ip | grep '^/' 2> /dev/null`"
   63 
   64 if [ "$OS" = "Linux" ]; then
   65     ifconfig_syntax_ptp="pointopoint"
   66     route_syntax_gw="gw"
   67     route_syntax_del="del"
   68     route_syntax_netmask="netmask"
   69 else
   70     ifconfig_syntax_ptp=""
   71     route_syntax_gw=""
   72     route_syntax_del="delete"
   73     route_syntax_netmask="-netmask"
   74 fi
   75 
   76 if [ -x /sbin/resolvconf ]; then # Optional tool on Debian, Ubuntu, Gentoo
   77     MODIFYRESOLVCONF=modify_resolvconf_manager
   78     RESTORERESOLVCONF=restore_resolvconf_manager
   79 elif [ -x /sbin/modify_resolvconf ]; then # Mandatory tool on Suse earlier than 11.1
   80     MODIFYRESOLVCONF=modify_resolvconf_suse
   81     RESTORERESOLVCONF=restore_resolvconf_suse
   82 else # Generic for any OS
   83     MODIFYRESOLVCONF=modify_resolvconf_generic
   84     RESTORERESOLVCONF=restore_resolvconf_generic
   85 fi
   86 
   87 # =========== tunnel interface handling ====================================
   88 
   89 do_ifconfig() {
   90     if [ -n "$INTERNAL_IP4_MTU" ]; then
   91         MTU=$INTERNAL_IP4_MTU
   92     elif [ -n "$IPROUTE" ]; then
   93         DEV=$($IPROUTE route | grep ^default | sed 's/^.* dev \([[:alnum:]-]\+\).*$/\1/')
   94         MTU=$(($($IPROUTE link show "$DEV" | grep mtu | sed 's/^.* mtu \([[:digit:]]\+\).*$/\1/') - 88))
   95     else
   96         MTU=1412
   97     fi
   98 
   99     # Point to point interface require a netmask of 255.255.255.255 on some systems
  100     ifconfig "$TUNDEV" inet "$INTERNAL_IP4_ADDRESS" $ifconfig_syntax_ptp "$INTERNAL_IP4_ADDRESS" netmask 255.255.255.255 mtu ${MTU} up
  101 
  102     if [ -n "$INTERNAL_IP4_NETMASK" ]; then
  103         set_network_route $INTERNAL_IP4_NETADDR $INTERNAL_IP4_NETMASK $INTERNAL_IP4_NETMASKLEN
  104     fi
  105 }
  106 
  107 destroy_tun_device() {
  108     case "$OS" in
  109     NetBSD) # and probably others...
  110         ifconfig "$TUNDEV" destroy
  111         ;;
  112     esac
  113 }
  114 
  115 # =========== route handling ====================================
  116 
  117 if [ -n "$IPROUTE" ]; then
  118     fix_ip_get_output () {
  119         sed 's/cache//;s/metric \?[0-9]\+ [0-9]\+//g;s/hoplimit [0-9]\+//g'
  120     }
  121 
  122     set_vpngateway_route() {
  123         $IPROUTE route add `$IPROUTE route get "$VPNGATEWAY" | fix_ip_get_output`
  124         $IPROUTE route flush cache
  125     }
  126     
  127     del_vpngateway_route() {
  128         $IPROUTE route $route_syntax_del "$VPNGATEWAY"
  129         $IPROUTE route flush cache
  130     }
  131     
  132     set_default_route() {
  133         $IPROUTE route | grep '^default' | fix_ip_get_output > "$DEFAULT_ROUTE_FILE"
  134         $IPROUTE route replace default dev "$TUNDEV"
  135         $IPROUTE route flush cache
  136     }
  137     
  138     set_network_route() {
  139         NETWORK="$1"
  140         NETMASK="$2"
  141         NETMASKLEN="$3"
  142         $IPROUTE route replace "$NETWORK/$NETMASKLEN" dev "$TUNDEV"
  143         $IPROUTE route flush cache
  144     }
  145     
  146     reset_default_route() {
  147         if [ -s "$DEFAULT_ROUTE_FILE" ]; then
  148             $IPROUTE route replace `cat "$DEFAULT_ROUTE_FILE"`
  149             $IPROUTE route flush cache
  150             rm -f -- "$DEFAULT_ROUTE_FILE"
  151         fi
  152     }
  153     
  154     del_network_route() {
  155         NETWORK="$1"
  156         NETMASK="$2"
  157         NETMASKLEN="$3"
  158         $IPROUTE route $route_syntax_del "$NETWORK/$NETMASKLEN" dev "$TUNDEV" 
  159         $IPROUTE route flush cache
  160     }
  161 else # use route command
  162     get_default_gw() {
  163         # isn't -n supposed to give --numeric output?
  164         # apperently not...
  165         # Get rid of lines containing IPv6 addresses (':')
  166         netstat -r -n | awk '/:/ { next; } /^(default|0\.0\.0\.0)/ { print $2; }'
  167     }
  168     
  169     set_vpngateway_route() {
  170         route add -host "$VPNGATEWAY" $route_syntax_gw "`get_default_gw`"
  171     }
  172 
  173     del_vpngateway_route() {
  174         route $route_syntax_del -host "$VPNGATEWAY"
  175     }
  176     
  177     set_default_route() {
  178         DEFAULTGW="`get_default_gw`"
  179         echo "$DEFAULTGW" > "$DEFAULT_ROUTE_FILE"
  180         route $route_syntax_del default
  181         route add default $route_syntax_gw "$INTERNAL_IP4_ADDRESS"
  182     }
  183     
  184     set_network_route() {
  185         NETWORK="$1"
  186         NETMASK="$2"
  187         NETMASKLEN="$3"
  188         del_network_route "$NETWORK" "$NETMASK" "$NETMASKLEN"
  189         route add -net "$NETWORK" $route_syntax_netmask "$NETMASK" $route_syntax_gw "$INTERNAL_IP4_ADDRESS"
  190     }
  191     
  192     reset_default_route() {
  193         if [ -s "$DEFAULT_ROUTE_FILE" ]; then
  194             route $route_syntax_del default
  195             route add default $route_syntax_gw `cat "$DEFAULT_ROUTE_FILE"`
  196             rm -f -- "$DEFAULT_ROUTE_FILE"
  197         fi
  198     }
  199     
  200     del_network_route() {
  201         case "$OS" in
  202         Linux|NetBSD|Darwin) # and probably others...
  203             # routes are deleted automatically on device shutdown
  204             return
  205             ;;
  206         esac
  207         NETWORK="$1"
  208         NETMASK="$2"
  209         NETMASKLEN="$3"
  210         route $route_syntax_del -net "$NETWORK" $route_syntax_netmask "$NETMASK" $route_syntax_gw "$INTERNAL_IP4_ADDRESS"
  211     }
  212 fi
  213 
  214 # =========== resolv.conf handling ====================================
  215 
  216 # =========== resolv.conf handling for any OS =========================
  217 
  218 modify_resolvconf_generic() {
  219     grep '^#@VPNC_GENERATED@' /etc/resolv.conf > /dev/null 2>&1 || cp -- /etc/resolv.conf "$RESOLV_CONF_BACKUP"
  220     NEW_RESOLVCONF="#@VPNC_GENERATED@ -- this file is generated by vpnc
  221 # and will be overwritten by vpnc
  222 # as long as the above mark is intact"
  223 
  224     # Remember the original value of CISCO_DEF_DOMAIN we need it later
  225     CISCO_DEF_DOMAIN_ORIG="$CISCO_DEF_DOMAIN"
  226     # Don't step on INTERNAL_IP4_DNS value, use a temporary variable
  227     INTERNAL_IP4_DNS_TEMP="$INTERNAL_IP4_DNS"
  228     exec 6< "$RESOLV_CONF_BACKUP"
  229     while read LINE <&6 ; do
  230         case "$LINE" in
  231             nameserver*)
  232                 if [ -n "$INTERNAL_IP4_DNS_TEMP" ]; then
  233                     read ONE_NAMESERVER INTERNAL_IP4_DNS_TEMP <<-EOF
  234     $INTERNAL_IP4_DNS_TEMP
  235 EOF
  236                     LINE="nameserver $ONE_NAMESERVER"
  237                 else
  238                     LINE=""
  239                 fi
  240                 ;;
  241             search*)
  242                 if [ -n "$CISCO_DEF_DOMAIN" ]; then
  243                     LINE="$LINE $CISCO_DEF_DOMAIN"
  244                     CISCO_DEF_DOMAIN=""
  245                 fi
  246                 ;;
  247             domain*)
  248                 if [ -n "$CISCO_DEF_DOMAIN" ]; then
  249                     LINE="domain $CISCO_DEF_DOMAIN"
  250                     CISCO_DEF_DOMAIN=""
  251                 fi
  252                 ;;
  253         esac
  254         NEW_RESOLVCONF="$NEW_RESOLVCONF
  255 $LINE"
  256     done
  257     exec 6<&-
  258     
  259     for i in $INTERNAL_IP4_DNS_TEMP ; do
  260         NEW_RESOLVCONF="$NEW_RESOLVCONF
  261 nameserver $i"
  262     done
  263     if [ -n "$CISCO_DEF_DOMAIN" ]; then
  264         NEW_RESOLVCONF="$NEW_RESOLVCONF
  265 search $CISCO_DEF_DOMAIN"
  266     fi
  267     echo "$NEW_RESOLVCONF" > /etc/resolv.conf
  268 
  269     if [ "$OS" = "Darwin" ]; then
  270         case "`uname -r`" in
  271             # Skip for pre-10.4 systems
  272             4.*|5.*|6.*|7.*)
  273                 ;;
  274             # 10.4 and later require use of scutil for DNS to work properly
  275             *)
  276                 OVERRIDE_PRIMARY=""
  277                 if [ -n "$CISCO_SPLIT_INC" ]; then
  278                     if [ $CISCO_SPLIT_INC -lt 1 ]; then
  279                         # Must override for correct default route
  280                         # Cannot use multiple DNS matching in this case
  281                         OVERRIDE_PRIMARY='d.add OverridePrimary # 1'
  282                     fi
  283                 fi
  284                 # Uncomment the following if/fi pair to use multiple
  285                 # DNS matching when available.  When multiple DNS matching
  286                 # is present, anything reading the /etc/resolv.conf file
  287                 # directly will probably not work as intended.
  288                 #if [ -z "$CISCO_DEF_DOMAIN_ORIG" ]; then
  289                     # Cannot use multiple DNS matching without a domain
  290                     OVERRIDE_PRIMARY='d.add OverridePrimary # 1'
  291                 #fi
  292                 scutil >/dev/null 2>&1 <<-EOF
  293                     open
  294                     d.init
  295                     d.add ServerAddresses * $INTERNAL_IP4_DNS
  296                     set State:/Network/Service/$TUNDEV/DNS
  297                     d.init
  298                     # next line overrides the default gateway and breaks split routing
  299                     # d.add Router $INTERNAL_IP4_ADDRESS
  300                     d.add Addresses * $INTERNAL_IP4_ADDRESS
  301                     d.add SubnetMasks * 255.255.255.255
  302                     d.add InterfaceName $TUNDEV
  303                     $OVERRIDE_PRIMARY
  304                     set State:/Network/Service/$TUNDEV/IPv4
  305                     close
  306                 EOF
  307                 if [ -n "$CISCO_DEF_DOMAIN_ORIG" ]; then
  308                     scutil >/dev/null 2>&1 <<-EOF
  309                         open
  310                         get State:/Network/Service/$TUNDEV/DNS
  311                         d.add DomainName $CISCO_DEF_DOMAIN_ORIG
  312                         d.add SearchDomains * $CISCO_DEF_DOMAIN_ORIG
  313                         d.add SupplementalMatchDomains * $CISCO_DEF_DOMAIN_ORIG
  314                         set State:/Network/Service/$TUNDEV/DNS
  315                         close
  316                     EOF
  317                 fi
  318                 ;;
  319         esac
  320     fi
  321 }
  322 
  323 restore_resolvconf_generic() {
  324     if [ ! -e "$RESOLV_CONF_BACKUP" ]; then
  325         return
  326     fi
  327     grep '^#@VPNC_GENERATED@' /etc/resolv.conf > /dev/null 2>&1 && cat "$RESOLV_CONF_BACKUP" > /etc/resolv.conf
  328     rm -f -- "$RESOLV_CONF_BACKUP"
  329 
  330     if [ "$OS" = "Darwin" ]; then
  331         case "`uname -r`" in
  332             # Skip for pre-10.4 systems
  333             4.*|5.*|6.*|7.*)
  334                 ;;
  335             # 10.4 and later require use of scutil for DNS to work properly
  336             *)
  337                 scutil >/dev/null 2>&1 <<-EOF
  338                     open
  339                     remove State:/Network/Service/$TUNDEV/IPv4
  340                     remove State:/Network/Service/$TUNDEV/DNS
  341                     close
  342                 EOF
  343                 ;;
  344         esac
  345     fi
  346 }
  347 # === resolv.conf handling via /sbin/modify_resolvconf (Suse) =====================
  348 
  349 # Suse provides a script that modifies resolv.conf. Use it because it will
  350 # restart/reload all other services that care about it (e.g. lwresd).
  351 
  352 modify_resolvconf_suse()
  353 {
  354     RESOLV_OPTS=''
  355     test -n "$INTERNAL_IP4_DNS" && RESOLV_OPTS="-n \"$INTERNAL_IP4_DNS\""
  356     test -n "$CISCO_DEF_DOMAIN" && RESOLV_OPTS="$RESOLV_OPTS -d $CISCO_DEF_DOMAIN"
  357     test -n "$RESOLV_OPTS" && eval /sbin/modify_resolvconf modify -s $SCRIPTNAME -p $SCRIPTNAME -f $FULL_SCRIPTNAME -e $TUNDEV $RESOLV_OPTS -t \"This file was created by $SCRIPTNAME\"
  358 }
  359 
  360 # Restore resolv.conf to old contents on Suse
  361 restore_resolvconf_suse()
  362 {
  363     /sbin/modify_resolvconf restore -s vpnc -p $SCRIPTNAME -f $FULL_SCRIPTNAME -e $TUNDEV
  364 }
  365 
  366 # === resolv.conf handling via /sbin/resolvconf (Debian, Ubuntu, Gentoo)) =========
  367 
  368 modify_resolvconf_manager() {
  369     NEW_RESOLVCONF=""
  370     for i in $INTERNAL_IP4_DNS; do
  371         NEW_RESOLVCONF="$NEW_RESOLVCONF
  372 nameserver $i"
  373     done
  374     if [ -n "$CISCO_DEF_DOMAIN" ]; then
  375         NEW_RESOLVCONF="$NEW_RESOLVCONF
  376 domain $CISCO_DEF_DOMAIN"
  377     fi
  378     echo "$NEW_RESOLVCONF" | /sbin/resolvconf -a $TUNDEV
  379 }
  380 
  381 restore_resolvconf_manager() {
  382     /sbin/resolvconf -d $TUNDEV
  383 }
  384 
  385 # ========= Toplevel state handling  =======================================
  386 
  387 kernel_is_2_6_or_above() {
  388     case `uname -r` in
  389         1.*|2.[012345]*)
  390             return 1
  391             ;;
  392         *)
  393             return 0
  394             ;;
  395     esac
  396 }
  397 
  398 do_pre_init() {
  399     if [ "$OS" = "Linux" ]; then
  400         if (exec 6<> /dev/net/tun) > /dev/null 2>&1 ; then
  401             :
  402         else # can't open /dev/net/tun
  403             test -e /proc/sys/kernel/modprobe && `cat /proc/sys/kernel/modprobe` tun 2>/dev/null
  404             # fix for broken devfs in kernel 2.6.x
  405             if [ "`readlink /dev/net/tun`" = misc/net/tun \
  406                 -a ! -e /dev/net/misc/net/tun -a -e /dev/misc/net/tun ] ; then
  407                 ln -sf /dev/misc/net/tun /dev/net/tun
  408             fi
  409             # make sure tun device exists
  410             if [ ! -e /dev/net/tun ]; then
  411                 mkdir -p /dev/net
  412                 mknod -m 0640 /dev/net/tun c 10 200
  413             fi
  414             # workaround for a possible latency caused by udev, sleep max. 10s
  415             if kernel_is_2_6_or_above ; then
  416                 for x in `seq 100` ; do
  417                     (exec 6<> /dev/net/tun) > /dev/null 2>&1 && break;
  418                     sleep 0.1
  419                 done
  420             fi
  421         fi
  422     elif [ "$OS" = "FreeBSD" ]; then
  423         if [ ! -e /dev/tun ]; then
  424             kldload if_tun
  425         fi
  426     elif [ "$OS" = "GNU/kFreeBSD" ]; then
  427         if [ ! -e /dev/tun ]; then
  428             kldload if_tun
  429         fi
  430     elif [ "$OS" = "NetBSD" ]; then
  431         :
  432     elif [ "$OS" = "OpenBSD" ]; then
  433         :
  434     elif [ "$OS" = "SunOS" ]; then
  435         :
  436     elif [ "$OS" = "Darwin" ]; then
  437         :
  438     fi
  439 }
  440 
  441 do_connect() {
  442     if [ -n "$CISCO_BANNER" ]; then
  443         echo "Connect Banner:"
  444         echo "$CISCO_BANNER" | while read LINE ; do echo "|" "$LINE" ; done
  445         echo
  446     fi
  447     
  448     do_ifconfig
  449     set_vpngateway_route
  450     if [ -n "$CISCO_SPLIT_INC" ]; then
  451         i=0
  452         while [ $i -lt $CISCO_SPLIT_INC ] ; do
  453             eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}"
  454             eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}"
  455             eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}"
  456             if [ $NETWORK != "0.0.0.0" ]; then
  457                 set_network_route "$NETWORK" "$NETMASK" "$NETMASKLEN"
  458             else
  459                 set_default_route
  460             fi
  461             i=`expr $i + 1`
  462         done
  463         for i in $INTERNAL_IP4_DNS ; do
  464             set_network_route "$i" "255.255.255.255" "32"
  465         done
  466     else
  467         set_default_route
  468     fi
  469     
  470     if [ -n "$INTERNAL_IP4_DNS" ]; then
  471         $MODIFYRESOLVCONF
  472     fi
  473 }
  474 
  475 do_disconnect() {
  476     if [ -n "$CISCO_SPLIT_INC" ]; then
  477         i=0
  478         while [ $i -lt $CISCO_SPLIT_INC ] ; do
  479             eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}"
  480             eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}"
  481             eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}"
  482             if [ $NETWORK != "0.0.0.0" ]; then
  483                 # FIXME: This doesn't restore previously overwritten
  484                 #        routes.
  485                 del_network_route "$NETWORK" "$NETMASK" "$NETMASKLEN"
  486             else
  487                 reset_default_route
  488             fi
  489             i=`expr $i + 1`
  490         done
  491         for i in $INTERNAL_IP4_DNS ; do
  492             del_network_route "$i" "255.255.255.255" "32"
  493         done
  494     else
  495         reset_default_route
  496     fi
  497     
  498     del_vpngateway_route
  499     
  500     if [ -n "$INTERNAL_IP4_DNS" ]; then
  501         $RESTORERESOLVCONF
  502     fi
  503     destroy_tun_device
  504 }
  505 
  506 #### Main
  507 
  508 if [ -z "$reason" ]; then
  509     echo "this script must be called from vpnc" 1>&2
  510     exit 1
  511 fi
  512 
  513 case "$reason" in
  514     pre-init)
  515         do_pre_init
  516         ;;
  517     connect)
  518         do_connect
  519         ;;
  520     disconnect)
  521         do_disconnect
  522         ;;
  523     *)
  524         echo "unknown reason '$reason'. Maybe vpnc-script is out of date" 1>&2
  525         exit 1
  526         ;;
  527 esac
  528 
  529 exit 0