vpnc-script (6758B)
1 #!/bin/sh 2 # List of parameters passed through environment 3 #* reason -- why this script was called, one of: pre-init connect disconnect 4 #* VPNGATEWAY -- vpn gateway address (always present) 5 #* TUNDEV -- tunnel device (always present) 6 #* INTERNAL_IP4_ADDRESS -- address (always present) 7 #* INTERNAL_IP4_MTU -- mtu (often unset) 8 #* INTERNAL_IP4_NETMASK -- netmask (often unset) 9 #* INTERNAL_IP4_NETMASKLEN -- netmask length (often unset) 10 #* INTERNAL_IP4_NETADDR -- address of network (only present if netmask is set) 11 #* INTERNAL_IP4_DNS -- list of dns servers 12 #* INTERNAL_IP4_NBNS -- list of wins servers 13 #* INTERNAL_IP6_ADDRESS -- IPv6 address 14 #* INTERNAL_IP6_NETMASK -- IPv6 netmask 15 #* INTERNAL_IP6_DNS -- IPv6 list of dns servers 16 #* CISCO_DEF_DOMAIN -- default domain name 17 #* CISCO_BANNER -- banner from server 18 #* CISCO_SPLIT_INC -- number of networks in split-network-list 19 #* CISCO_SPLIT_INC_%d_ADDR -- network address 20 #* CISCO_SPLIT_INC_%d_MASK -- subnet mask (for example: 255.255.255.0) 21 #* CISCO_SPLIT_INC_%d_MASKLEN -- subnet masklen (for example: 24) 22 #* CISCO_SPLIT_INC_%d_PROTOCOL -- protocol (often just 0) 23 #* CISCO_SPLIT_INC_%d_SPORT -- source port (often just 0) 24 #* CISCO_SPLIT_INC_%d_DPORT -- destination port (often just 0) 25 #* CISCO_IPV6_SPLIT_INC -- number of networks in IPv6 split-network-list 26 #* CISCO_IPV6_SPLIT_INC_%d_ADDR -- IPv6 network address 27 #* CISCO_IPV6_SPLIT_INC_$%d_MASKLEN -- IPv6 subnet masklen 28 29 HOOKS_DIR=/etc/openconnect 30 31 # FIXMEs: 32 33 # Section A: route handling 34 35 # 1) The 3 values CISCO_SPLIT_INC_%d_PROTOCOL/SPORT/DPORT are currently being ignored 36 # In order to use them, we'll probably need os specific solutions 37 # * Linux: iptables -t mangle -I PREROUTING <conditions> -j ROUTE --oif $TUNDEV 38 # This would be an *alternative* to changing the routes (and thus 2) and 3) 39 # shouldn't be relevant at all) 40 # 2) There are two different functions to set routes: generic routes and the 41 # default route. Why isn't the defaultroute handled via the generic route case? 42 # 3) In the split tunnel case, all routes but the default route might get replaced 43 # without getting restored later. We should explicitely check and save them just 44 # like the defaultroute 45 # 4) Replies to a dhcp-server should never be sent into the tunnel 46 47 # Section B: Split DNS handling 48 49 # 1) We parse CISCO_SPLIT_DNS and use dnsmasq to set it 50 51 do_connect() { 52 if [ -n "$CISCO_BANNER" ]; then 53 logger -t openconnect "Connect Banner:" 54 echo "$CISCO_BANNER" | while read LINE ; do logger -t openconnect "|" "$LINE" ; done 55 fi 56 57 proto_init_update "$TUNDEV" 1 58 59 if [ -n "$INTERNAL_IP4_MTU" ]; then 60 MTU=$INTERNAL_IP4_MTU 61 fi 62 63 if [ -z "$MTU" ]; then 64 MTU=1412 65 fi 66 67 proto_add_ipv4_address "$INTERNAL_IP4_ADDRESS" 32 "" "$INTERNAL_IP4_ADDRESS" 68 69 if [ -n "$INTERNAL_IP4_NETMASKLEN" ]; then 70 proto_add_ipv4_route "$INTERNAL_IP4_NETADDR" "$INTERNAL_IP4_NETMASKLEN" 71 fi 72 73 # If the netmask is provided, it contains the address _and_ netmask 74 if [ -n "$INTERNAL_IP6_ADDRESS" ] && [ -z "$INTERNAL_IP6_NETMASK" ]; then 75 INTERNAL_IP6_NETMASK="$INTERNAL_IP6_ADDRESS/128" 76 fi 77 78 if [ -n "$INTERNAL_IP6_NETMASK" ]; then 79 addr="${INTERNAL_IP6_NETMASK%%/*}" 80 mask="${INTERNAL_IP6_NETMASK##*/}" 81 [[ "$addr" != "$mask" ]] && proto_add_ipv6_address "$addr" "$mask" 82 fi 83 84 DNSMASQ_FILE="/tmp/dnsmasq.d/openconnect.$TUNDEV" 85 LOCAL_DOMAIN=$(uci get dhcp.@dnsmasq[0].domain) 86 rm -f $DNSMASQ_FILE 87 if [ -n "$CISCO_SPLIT_DNS" ] && [ -d "/tmp/dnsmasq.d/" ];then 88 SDNS=`echo $CISCO_SPLIT_DNS|sed 's/,/\n/g'` 89 echo "$SDNS" | while read i; do 90 if [ "$i" = "$LOCAL_DOMAIN" ];then 91 continue 92 fi 93 if [ -n "$INTERNAL_IP4_DNS" ];then 94 for dns in $INTERNAL_IP4_DNS;do 95 echo "server=/$i/$dns" >> $DNSMASQ_FILE 96 done 97 fi 98 if [ -n "$INTERNAL_IP6_DNS" ];then 99 for dns in $INTERNAL_IP6_DNS;do 100 echo "server=/$i/$dns" >> $DNSMASQ_FILE 101 done 102 fi 103 echo "rebind-domain-ok=$i" >> $DNSMASQ_FILE 104 done 105 /etc/init.d/dnsmasq restart 106 else 107 if [ -n "$INTERNAL_IP4_DNS" ];then 108 for dns in $INTERNAL_IP4_DNS;do 109 proto_add_dns_server "$dns" 110 done 111 fi 112 if [ -n "$INTERNAL_IP6_DNS" ];then 113 for dns in $INTERNAL_IP6_DNS;do 114 proto_add_dns_server "$dns" 115 done 116 fi 117 if [ -n "$CISCO_DEF_DOMAIN" ] && [ "$CISCO_DEF_DOMAIN" != "$LOCAL_DOMAIN" ];then 118 if [ -n "$INTERNAL_IP4_DNS" ];then 119 for dns in $INTERNAL_IP4_DNS;do 120 echo "server=/$CISCO_DEF_DOMAIN/$dns" >> $DNSMASQ_FILE 121 done 122 fi 123 if [ -n "$INTERNAL_IP6_DNS" ];then 124 for dns in $INTERNAL_IP6_DNS;do 125 echo "server=/$CISCO_DEF_DOMAIN/$dns" >> $DNSMASQ_FILE 126 done 127 fi 128 proto_add_dns_search "$CISCO_DEF_DOMAIN" 129 fi 130 fi 131 132 if [ -n "$CISCO_SPLIT_INC" ]; then 133 i=0 134 while [ $i -lt $CISCO_SPLIT_INC ] ; do 135 eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}" 136 eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}" 137 eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}" 138 if [ $NETWORK != "0.0.0.0" ]; then 139 proto_add_ipv4_route "$NETWORK" "$NETMASKLEN" 140 else 141 proto_add_ipv4_route "0.0.0.0" 0 142 fi 143 i=$(($i + 1)) 144 done 145 elif [ -n "$INTERNAL_IP4_ADDRESS" ]; then 146 proto_add_ipv4_route "0.0.0.0" 0 147 fi 148 if [ -n "$CISCO_IPV6_SPLIT_INC" ]; then 149 i=0 150 while [ $i -lt $CISCO_IPV6_SPLIT_INC ] ; do 151 eval NETWORK="\${CISCO_IPV6_SPLIT_INC_${i}_ADDR}" 152 eval NETMASKLEN="\${CISCO_IPV6_SPLIT_INC_${i}_MASKLEN}" 153 if [ $NETMASKLEN -lt 128 ]; then 154 proto_add_ipv6_route "$NETWORK" "$NETMASKLEN" 155 else 156 proto_add_ipv6_route "::0" 0 157 fi 158 i=$(($i + 1)) 159 done 160 elif [ -n "$INTERNAL_IP6_NETMASK" -o -n "$INTERNAL_IP6_ADDRESS" ]; then 161 proto_add_ipv6_route "::0" 0 162 fi 163 proto_send_update "$INTERFACE" 164 } 165 166 do_disconnect() { 167 rm -f "/tmp/dnsmasq.d/openconnect.$TUNDEV" 168 proto_init_update "$TUNDEV" 0 169 proto_send_update "$INTERFACE" 170 } 171 172 #### Hooks 173 run_hooks() { 174 HOOK="$1" 175 176 if [ -d ${HOOKS_DIR}/${HOOK}.d ]; then 177 for script in ${HOOKS_DIR}/${HOOK}.d/* ; do 178 [ -f $script ] && . $script 179 done 180 fi 181 } 182 183 #### Main 184 185 if [ -z "$reason" ]; then 186 logger -t openconnect "this script must be called from vpnc" 1>&2 187 exit 1 188 fi 189 if [ -z "$INTERFACE" ]; then 190 logger -t openconnect "this script must be called for an active interface" 191 exit 1 192 fi 193 194 . /lib/netifd/netifd-proto.sh 195 196 case "$reason" in 197 pre-init) 198 run_hooks pre-init 199 ;; 200 connect) 201 run_hooks connect 202 do_connect 203 run_hooks post-connect 204 ;; 205 disconnect) 206 run_hooks disconnect 207 do_disconnect 208 run_hooks post-disconnect 209 ;; 210 reconnect) 211 run_hooks reconnect 212 ;; 213 *) 214 logger -t openconnect "unknown reason '$reason'. Maybe vpnc-script is out of date" 1>&2 215 exit 1 216 ;; 217 esac 218 219 exit 0