vpnc-script: create dnsmasq entries for connections where default domain is set
[feed/packages.git] / net / vpnc-scripts / files / vpnc-script
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 rm -f $DNSMASQ_FILE
86 if [ -n "$CISCO_SPLIT_DNS" ] && [ -d "/tmp/dnsmasq.d/" ];then
87 SDNS=`echo $CISCO_SPLIT_DNS|sed 's/,/\n/g'`
88 echo "$SDNS" | while read i; do
89 if [ -n "$INTERNAL_IP4_DNS" ];then
90 for dns in "$INTERNAL_IP4_DNS";do
91 echo "server=/$i/$dns" >> $DNSMASQ_FILE
92 done
93 fi
94 if [ -n "$INTERNAL_IP6_DNS" ];then
95 for dns in "$INTERNAL_IP6_DNS";do
96 echo "server=/$i/$dns" >> $DNSMASQ_FILE
97 done
98 fi
99 echo "rebind-domain-ok=$i" >> $DNSMASQ_FILE
100 done
101 /etc/init.d/dnsmasq restart
102 else
103 if [ -n "$INTERNAL_IP4_DNS" ];then
104 for dns in "$INTERNAL_IP4_DNS";do
105 proto_add_dns_server "$dns"
106 done
107 fi
108 if [ -n "$INTERNAL_IP6_DNS" ];then
109 for dns in "$INTERNAL_IP6_DNS";do
110 proto_add_dns_server "$dns"
111 done
112 fi
113 if [ -n "$CISCO_DEF_DOMAIN" ];then
114 if [ -n "$INTERNAL_IP4_DNS" ];then
115 for dns in "$INTERNAL_IP4_DNS";do
116 echo "server=/$CISCO_DEF_DOMAIN/$dns" >> $DNSMASQ_FILE
117 done
118 fi
119 if [ -n "$INTERNAL_IP6_DNS" ];then
120 for dns in "$INTERNAL_IP6_DNS";do
121 echo "server=/$CISCO_DEF_DOMAIN/$dns" >> $DNSMASQ_FILE
122 done
123 fi
124 proto_add_dns_search "$CISCO_DEF_DOMAIN"
125 fi
126 fi
127
128 if [ -n "$CISCO_SPLIT_INC" ]; then
129 i=0
130 while [ $i -lt $CISCO_SPLIT_INC ] ; do
131 eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}"
132 eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}"
133 eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}"
134 if [ $NETWORK != "0.0.0.0" ]; then
135 proto_add_ipv4_route "$NETWORK" "$NETMASKLEN"
136 else
137 proto_add_ipv4_route "0.0.0.0" 0
138 fi
139 i=$(($i + 1))
140 done
141 elif [ -n "$INTERNAL_IP4_ADDRESS" ]; then
142 proto_add_ipv4_route "0.0.0.0" 0
143 fi
144 if [ -n "$CISCO_IPV6_SPLIT_INC" ]; then
145 i=0
146 while [ $i -lt $CISCO_IPV6_SPLIT_INC ] ; do
147 eval NETWORK="\${CISCO_IPV6_SPLIT_INC_${i}_ADDR}"
148 eval NETMASKLEN="\${CISCO_IPV6_SPLIT_INC_${i}_MASKLEN}"
149 if [ $NETMASKLEN -lt 128 ]; then
150 proto_add_ipv6_route "$NETWORK" "$NETMASKLEN"
151 else
152 proto_add_ipv6_route "::0" 0
153 fi
154 i=$(($i + 1))
155 done
156 elif [ -n "$INTERNAL_IP6_NETMASK" -o -n "$INTERNAL_IP6_ADDRESS" ]; then
157 proto_add_ipv6_route "::0" 0
158 fi
159 proto_send_update "$INTERFACE"
160 }
161
162 do_disconnect() {
163 rm -f "/tmp/dnsmasq.d/openconnect.$TUNDEV"
164 proto_init_update "$TUNDEV" 0
165 proto_send_update "$INTERFACE"
166 }
167
168 #### Hooks
169 run_hooks() {
170 HOOK="$1"
171
172 if [ -d ${HOOKS_DIR}/${HOOK}.d ]; then
173 for script in ${HOOKS_DIR}/${HOOK}.d/* ; do
174 [ -f $script ] && . $script
175 done
176 fi
177 }
178
179 #### Main
180
181 if [ -z "$reason" ]; then
182 logger -t openconnect "this script must be called from vpnc" 1>&2
183 exit 1
184 fi
185 if [ -z "$INTERFACE" ]; then
186 logger -t openconnect "this script must be called for an active interface"
187 exit 1
188 fi
189
190 . /lib/netifd/netifd-proto.sh
191
192 case "$reason" in
193 pre-init)
194 run_hooks pre-init
195 ;;
196 connect)
197 run_hooks connect
198 do_connect
199 run_hooks post-connect
200 ;;
201 disconnect)
202 run_hooks disconnect
203 do_disconnect
204 run_hooks post-disconnect
205 ;;
206 reconnect)
207 run_hooks reconnect
208 ;;
209 *)
210 logger -t openconnect "unknown reason '$reason'. Maybe vpnc-script is out of date" 1>&2
211 exit 1
212 ;;
213 esac
214
215 exit 0