openvpn: add proto handler openvpn
authorFlorian Eckert <fe@dev.tdt.de>
Tue, 30 May 2017 10:36:06 +0000 (12:36 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 14 Aug 2019 05:56:58 +0000 (07:56 +0200)
Redmine-patch-id: 1227
Signed-off-by: Florian Eckert <fe@dev.tdt.de>
package/network/services/openvpn/Makefile
package/network/services/openvpn/files/lib/netifd/openvpn-down [new file with mode: 0644]
package/network/services/openvpn/files/lib/netifd/openvpn-up [new file with mode: 0644]
package/network/services/openvpn/files/lib/netifd/proto/openvpn.sh [new file with mode: 0644]
package/network/services/openvpn/files/openvpn.init

index aed9f43f802f79dae6fd32abea9073263317586f..573e0f7efa94fa153511bd8e01e28ea571144de9 100644 (file)
@@ -111,7 +111,9 @@ define Package/openvpn-$(BUILD_VARIANT)/install
                $(1)/etc/init.d \
                $(1)/etc/config \
                $(1)/etc/openvpn \
-               $(1)/lib/upgrade/keep.d
+               $(1)/lib/upgrade/keep.d \
+               $(1)/lib/netifd \
+               $(1)/lib/netifd/proto
 
        $(INSTALL_BIN) \
                $(PKG_INSTALL_DIR)/usr/sbin/openvpn \
@@ -130,6 +132,18 @@ define Package/openvpn-$(BUILD_VARIANT)/install
        $(INSTALL_DATA) \
                files/openvpn.upgrade \
                $(1)/lib/upgrade/keep.d/openvpn
+
+       $(INSTALL_BIN) \
+               files/lib/netifd/openvpn-down \
+               $(1)/lib/netifd/openvpn-down
+
+       $(INSTALL_BIN) \
+               files/lib/netifd/openvpn-up \
+               $(1)/lib/netifd/openvpn-up
+
+       $(INSTALL_BIN) \
+               files/lib/netifd/proto/openvpn.sh \
+               $(1)/lib/netifd/proto/openvpn.sh
 endef
 
 $(eval $(call BuildPackage,openvpn-openssl))
diff --git a/package/network/services/openvpn/files/lib/netifd/openvpn-down b/package/network/services/openvpn/files/lib/netifd/openvpn-down
new file mode 100644 (file)
index 0000000..6b945a9
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+#DBG=1
+
+[ -n "$INTERFACE" ] || {
+       echo "openvpn-down no INTERFACE variable appended"
+       exit 1
+}
+
+[ -n "$DBG" ] && {
+       env > /tmp/openvpn-down-${INTERFACE}-env.log
+}
+
+. /lib/netifd/netifd-proto.sh
+proto_init_update "$dev" 0
+proto_send_update "$INTERFACE"
+
+[ -d /etc/openvpn/ip-down.d ] && {
+       for SCRIPT in /etc/openvpn/ip-down.d/*
+       do
+               [ -x "$SCRIPT" ] && "$SCRIPT" "$@"
+       done
+}
+
+exit 0
diff --git a/package/network/services/openvpn/files/lib/netifd/openvpn-up b/package/network/services/openvpn/files/lib/netifd/openvpn-up
new file mode 100644 (file)
index 0000000..5a3ec4f
--- /dev/null
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+#DBG=1
+
+[ -n "$INTERFACE" ] || {
+       echo "openvpn-up no INTERFACE variable appended"
+       exit 1
+}
+
+[ -n "$DBG" ] && {
+       env > /tmp/openvpn-up-${INTERFACE}-env.log
+}
+
+. /lib/netifd/netifd-proto.sh
+proto_init_update "$dev" 1 1
+proto_set_keep 1
+[ -n "$ifconfig_local" ] && proto_add_ipv4_address "$ifconfig_local" 32
+[ -n "$ifconfig_ipv6_local" ] && proto_add_ipv6_address "$ifconfig_ipv6_local" 128
+
+# set ipv4 routen
+c=1
+while true ; do
+       v=route_network_$c
+       eval "network=\$$v"
+       [ -n "$network" ] || break
+       v=route_gateway_$c
+       eval "gw=\$$v"
+       v=route_netmask_$c
+       eval "mask=\$$v"
+       v=route_metric_$c
+       eval "metric=\$$v"
+       [ -n "$metric" ] || metric="$METRIC"
+
+       proto_add_ipv4_route "$network" "$mask" "$gw" "" "$metric"
+       c=$(( $c+1 ))
+done
+
+# set default route
+[ -n "$DEFAULTROUTE" ] && {
+       proto_add_ipv4_route "0.0.0.0" "0" "$gw" "0.0.0.0/0" "$METRIC"
+}
+
+# set ipv6 routen
+c=1
+while true ; do
+       v=route_ipv6_network_$c
+       eval "network=\$$v"
+       [ -n "$network" ] || break
+       v=route_ipv6_gateway_$c
+       eval "gw=\$$v"
+
+       pref=${network%%/*}
+       preff=$pref/
+       preflen=${network#$preff}
+
+       proto_add_ipv6_route "$pref" "$preflen" "$gw"
+       c=$(( $c+1 ))
+done
+
+# set dns server
+c=1
+while true ; do
+       v=foreign_option_$c
+       eval "fo=\$$v"
+       [ -n "$fo" ] || break
+       [ "${fo%% *}" = "dhcp-option" ] && {
+               s=${fo#dhcp-option }
+               [ "${s%% *}" = "DNS" ] && {
+                       dns=${s#DNS }
+                       [ -n "$PEERDNS" ] && {
+                               proto_add_dns_server "$dns"
+                       }
+               }
+       }
+       c=$(( $c+1 ))
+done
+
+proto_send_update "$INTERFACE"
+
+[ -d /etc/openvpn/ip-up.d ] && {
+       for SCRIPT in /etc/openvpn/ip-up.d/*
+       do
+               [ -x "$SCRIPT" ] && "$SCRIPT" "$@"
+       done
+}
+
+exit 0
diff --git a/package/network/services/openvpn/files/lib/netifd/proto/openvpn.sh b/package/network/services/openvpn/files/lib/netifd/proto/openvpn.sh
new file mode 100644 (file)
index 0000000..0ed914d
--- /dev/null
@@ -0,0 +1,95 @@
+#!/bin/sh
+
+[ -x /usr/sbin/openvpn ] || exit 1
+
+[ -n "$INCLUDE_ONLY" ] || {
+       . /lib/functions.sh
+       . /lib/functions/network.sh
+       . ../netifd-proto.sh
+       init_proto "$@"
+}
+
+proto_openvpn_init_config() {
+       available=1
+       no_device=1
+       proto_config_add_string "ifname"
+       proto_config_add_defaults
+}
+
+get_config_param() {
+       local variable="$1"
+       local config="$2"
+       local option="$3"
+       local default="$4"
+
+       local value="$(sed -rne 's/^[ \t]*'"$option"'[ \t]+([^ \t]+)[ \t]*$/\1/p' "$config" | tail -n1)"
+       export -n "$variable=${value:-$default}"
+}
+
+proto_openvpn_setup() {
+       local cfg="$1"
+       local iface="$2"
+
+       local config dev_type opts
+
+       local ifname $PROTO_DEFAULT_OPTIONS
+       json_get_vars ifname $PROTO_DEFAULT_OPTIONS
+
+       if ! /etc/init.d/openvpn prepare "$cfg" ; then
+               echo "openvpn[$$]" "Failed to setup configuration"
+               proto_notify_error "$cfg" "SERVICE_ENABLED"
+               proto_block_restart "$cfg"
+               return 1
+       fi
+
+       if [ -f "/var/etc/openvpn-${cfg}.conf" ]; then
+               config="/var/etc/openvpn-${cfg}.conf"
+       else
+               config="/etc/openvpn/${cfg}.conf"
+       fi
+
+       [ -n "$ifname" ] || get_config_param ifname "$config" dev
+       [ -z "$ifname" ] && {
+               echo "openvpn[$$]" "Failed to get ifname"
+               proto_notify_error "$cfg" "NO_IFNAME_SET"
+               proto_block_restart "$cfg"
+               return 1
+       }
+       append opts "--dev $ifname"
+
+       get_config_param dev_type "$config" dev-type
+       case "${dev_type:-$ifname}" in
+               tap*) dev_type="tap" ;;
+               *) dev_type="tun" ;;
+       esac
+       append opts "--dev-type $dev_type"
+
+       [ -n "$metric" ] || get_config_param metric "$config" metric 0
+       append opts "--setenv METRIC ${metric}"
+
+       [ "$peerdns" = 1 ] && append opts "--setenv PEERDNS 1"
+
+       [ "$defaultroute" = 1 ] && append opts "--setenv DEFAULTROUTE 1"
+
+       proto_run_command "$cfg" /usr/sbin/openvpn \
+               --syslog "openvpn($cfg)" \
+               --status "/var/run/openvpn.${cfg}.status" \
+               --cd /etc/openvpn \
+               --config "$config" \
+               --setenv INTERFACE "$cfg" \
+               --resolv-retry infinite \
+               --route-noexec \
+               --script-security 3 \
+               --route-up /lib/netifd/openvpn-up \
+               --route-pre-down /lib/netifd/openvpn-down \
+               $opts
+}
+
+proto_openvpn_teardown() {
+       local cfg="$1"
+       proto_kill_command "$cfg"
+}
+
+[ -n "$INCLUDE_ONLY" ] || {
+       add_protocol openvpn
+}
index a7d35d1a985ed609971ac2c6a8161e97cc4decb0..2315efedc41099e1bc08637eeb5d42c2876d8b47 100644 (file)
@@ -7,6 +7,11 @@
 START=90
 STOP=10
 
+EXTRA_COMMANDS="prepare"
+EXTRA_HELP="\
+        prepare Build config from uci\
+"
+
 USE_PROCD=1
 PROG=/usr/sbin/openvpn
 
@@ -165,3 +170,56 @@ start_service() {
 service_triggers() {
        procd_add_reload_trigger openvpn
 }
+
+LOG="logger -t openvpn-prepare -p"
+prepare() {
+       local s="$1"
+
+       local log="logger -t openvpn-prepare -p"
+
+       [ -z "$s" ] && {
+               $log error "Config not specified"
+               exit 1
+       }
+
+       uci -q get openvpn.$s > /dev/null || {
+               $log error "Config $s not found"
+               exit 2
+       }
+
+       . /usr/share/openvpn/openvpn.options
+
+       config_load 'openvpn'
+       config_get enabled "$s" 'enabled' 0
+       config_get config "$s" 'config'
+
+       [ "$enabled" != 0 ] && {
+               $log warning "This config $s is enabled and is started by the openvpn service"
+               exit 3
+       }
+
+       if [ ! -z "$config" ]; then
+               readlink -f "$config"
+               [ "$?" -ne 0 ] && {
+                       $log error "Config file '$config' does not exist"
+                       exit 4
+               }
+               local name=${config##*/}
+               if [ "${name%%.*}" != "$s" ]; then
+                       $log error "Pre generated config file name '${config}' is not equal to openvpn section name '$s'"
+                       exit 5
+               else
+                       $log notice "Using pre generated config $config"
+                       exit 0
+               fi
+       fi
+
+       [ ! -d "/var/etc" ] && mkdir -p "/var/etc"
+       [ -f "/var/etc/openvpn-${s}.conf" ] && rm "/var/etc/openvpn-${s}.conf"
+
+       append_bools "$s" $OPENVPN_BOOLS
+       append_params "$s" $OPENVPN_PARAMS
+
+       $log notice "Config $s generated"
+       exit 0
+}