vpnc-script 6.6 KB

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