Add openconnect protocol support to network scripts
authorGabor Juhos <juhosg@openwrt.org>
Wed, 2 May 2012 19:28:08 +0000 (19:28 +0000)
committerGabor Juhos <juhosg@openwrt.org>
Wed, 2 May 2012 19:28:08 +0000 (19:28 +0000)
This is very basic — username/password only, and doesn't even check
certificates which it *definitely* should. But it's a good start.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
SVN-Revision: 31559

net/openconnect/Makefile
net/openconnect/files/openconnect.sh [new file with mode: 0755]
net/openconnect/files/run-openconnect [new file with mode: 0755]

index 372841c659cbbd969fdc022993880c79e7e1baaf..4a03fa8f6552db8ea052c651415774f32cb9a637 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=openconnect
 PKG_VERSION:=3.16
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=ftp://ftp.infradead.org/pub/openconnect/
@@ -20,7 +20,7 @@ include $(INCLUDE_DIR)/package.mk
 define Package/openconnect
   SECTION:=net
   CATEGORY:=Network
-  DEPENDS:=+libxml2 +libopenssl +kmod-tun
+  DEPENDS:=+libxml2 +libopenssl +kmod-tun +vpnc-scripts
   TITLE:=VPN client for Cisco's AnyConnect SSL VPN
   URL:=http://www.infradead.org/openconnect/
   SUBMENU:=VPN
@@ -37,9 +37,11 @@ endef
 CONFIGURE_ARGS+=--disable-shared
 
 define Package/openconnect/install
+       $(INSTALL_DIR) $(1)/lib/network
+       $(INSTALL_BIN) ./files/openconnect.sh $(1)/lib/network/
        $(INSTALL_DIR) $(1)/usr/sbin
-       $(INSTALL_BIN) $(PKG_BUILD_DIR)/openconnect \
-               $(1)/usr/sbin/
+       $(INSTALL_BIN) ./files/run-openconnect $(1)/usr/sbin/
+       $(INSTALL_BIN) $(PKG_BUILD_DIR)/openconnect $(1)/usr/sbin/
 endef
 
 $(eval $(call BuildPackage,openconnect))
diff --git a/net/openconnect/files/openconnect.sh b/net/openconnect/files/openconnect.sh
new file mode 100755 (executable)
index 0000000..13221ab
--- /dev/null
@@ -0,0 +1,39 @@
+find_gw() {
+       route -n | awk '$1 == "0.0.0.0" { print $2; exit }'
+}
+
+scan_openconnect() {
+       config_set "$1" device "vpn-$1"
+}
+
+stop_interface_openconnect() {
+       local config="$1"
+       local lock="/var/lock/openconnect-$config"
+
+        uci_set_state network "$config" up 0
+
+       lock "$lock"
+
+       SERVICE_PID_FILE="/var/run/openconnect-${config}.pid" \
+         SERVICE_SIG=HUP service_stop /bin/sh
+
+       remove_dns "$config"
+
+       lock -u "$lock"
+}
+
+setup_interface_openconnect() {
+       local config="$2"
+
+       /sbin/insmod tun 2>&- >&-
+
+       # creating the tunnel below will trigger a net subsystem event
+        # prevent it from touching or iface by disabling .auto here
+        uci_set_state network "$config" ifname "vpn-$config"
+        uci_set_state network "$config" auto 0
+        uci_set_state network "$config" up 1
+
+       SERVICE_PID_FILE="/var/run/openconnect-${config}.pid" \
+          SERVICE_WRITE_PID=1  SERVICE_DAEMONIZE=1 \
+        service_start /usr/sbin/run-openconnect $config
+}
diff --git a/net/openconnect/files/run-openconnect b/net/openconnect/files/run-openconnect
new file mode 100755 (executable)
index 0000000..e835891
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/sh -x
+
+. /etc/functions.sh
+
+[ $# = 0 ] && { echo "  $0 <group>"; exit; }
+
+include /lib/network
+scan_interfaces
+
+config="$1"
+export OPENWRT_INTERFACE="$config"
+
+config_get proto "$config" proto
+
+if [ "$proto" != "openconnect" ]; then
+    echo "Interface $config is $proto not openconnect" >&2
+    exit 1
+fi
+
+config_get device "$config" device
+
+local server
+config_get server "$config" server
+
+local port
+config_get port "$config" port
+if [ -n "$port" ]; then
+    args="$server:$port"
+else
+    args="$server"
+fi
+
+local cookie
+config_get cookie "$config" cookie
+[ -n "$cookie" ] && args="$args -C $cookie"
+
+local username
+config_get username "$config" username
+[ -n "$username" ] && args="$args -u $username"
+
+local password
+config_get password "$password" password
+
+/sbin/insmod tun
+
+local lock="/var/lock/openconnect-$config"
+
+# creating the tunnel below will trigger a net subsystem event
+# prevent it from touching or iface by disabling .auto here
+uci_set_state network "$config" ifname $link
+uci_set_state network "$config" auto 0
+
+local gw="$(find_gw)"
+[ -n "$gw" ] && {
+    local serv_addrs=""
+    for ip in $(resolveip -4 -t 3 "$server"); do
+       append serv_addrs "$ip"
+       route delete -host "$ip" 2>/dev/null
+       route add -host "$ip" gw "$gw"
+    done
+    uci_toggle_state network "$config" serv_addrs "$serv_addrs"
+}
+
+RECON=$(date +%s)
+
+trap "[ -r /var/run/openconnect-$config-oc.pid ] && kill -HUP \$(cat /var/run/openconnect-$config-oc.pid)" SIGHUP
+while [ "$(uci_get_state network ${config} up)" = "1" ]; do
+    NOW=$(date +%s)
+    if [ $RECON -gt $NOW ]; then
+       DELAY=$(expr $RECON - $NOW)
+       logger -t openconnect "Waiting for $DELAY seconds before reconnecting"
+       sleep $(expr $DELAY)
+    fi
+
+    # The lock prevents a race condition where /lib/network/openconnect.sh could
+    # send us SIGHUP after we spawn openconnect, but before we store its pid.
+    # Thus leaving it running after we should have killed it.
+    lock $lock
+    echo "$passwd" | /usr/sbin/openconnect $args -i "vpn-$config" \
+       --no-cert-check --non-inter --passwd-on-stdin --syslog --script /etc/vpnc/vpnc-script &
+    echo $! > /var/run/openconnect-$config-oc.pid
+    lock -u $lock
+    wait $!
+    rm /var/run/openconnect-$config-oc.pid
+    RECON=$(expr $NOW + 60)
+done