Add fastd, a very small VPN daemon
authorMatthias Schiffer <[email protected]>
Thu, 12 Jun 2014 13:10:47 +0000 (15:10 +0200)
committerMatthias Schiffer <[email protected]>
Thu, 12 Jun 2014 13:12:38 +0000 (15:12 +0200)
net/fastd/Config.in [new file with mode: 0644]
net/fastd/Makefile [new file with mode: 0644]
net/fastd/files/fastd.config [new file with mode: 0644]
net/fastd/files/fastd.init [new file with mode: 0644]
net/fastd/files/fastd.upgrade [new file with mode: 0644]

diff --git a/net/fastd/Config.in b/net/fastd/Config.in
new file mode 100644 (file)
index 0000000..7d7c80c
--- /dev/null
@@ -0,0 +1,82 @@
+menu "Configuration"
+       depends on PACKAGE_fastd
+
+config FASTD_ENABLE_METHOD_CIPHER_TEST
+       bool "Enable cipher-test method provider"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_ENABLE_METHOD_COMPOSED_GMAC
+       bool "Enable composed-gmac method provider"
+       depends on PACKAGE_fastd
+       default y
+
+config FASTD_ENABLE_METHOD_GENERIC_GMAC
+       bool "Enable generic-gmac method provider"
+       depends on PACKAGE_fastd
+       default y
+
+config FASTD_ENABLE_METHOD_GENERIC_POLY1305
+       bool "Enable generic-poly1305 method provider"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_ENABLE_METHOD_NULL
+       bool "Enable null method"
+       depends on PACKAGE_fastd
+       default y
+
+config FASTD_ENABLE_METHOD_XSALSA20_POLY1305
+       bool "Enable xsalsa20-poly1305 method"
+       depends on PACKAGE_fastd
+       default n
+
+
+config FASTD_ENABLE_CIPHER_AES128_CTR
+       bool "Enable the AES128-CTR cipher"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_ENABLE_CIPHER_NULL
+       bool "Enable the null cipher"
+       depends on PACKAGE_fastd
+       default y
+
+config FASTD_ENABLE_CIPHER_SALSA20
+       bool "Enable the Salsa20 cipher"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_ENABLE_CIPHER_SALSA2012
+       bool "Enable the Salsa20/12 cipher"
+       depends on PACKAGE_fastd
+       default y
+
+
+config FASTD_ENABLE_MAC_GHASH
+       bool "Enable the GHASH message authentication code"
+       depends on PACKAGE_fastd
+       default y
+
+
+config FASTD_WITH_CMDLINE_USER
+       bool "Include support for setting user/group related options on the command line"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_WITH_CMDLINE_LOGGING
+       bool "Include support for setting logging related options on the command line"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_WITH_CMDLINE_OPERATION
+       bool "Include support for setting options related to the VPN operation (like mode, interface, encryption method) on the command line"
+       depends on PACKAGE_fastd
+       default n
+
+config FASTD_WITH_CMDLINE_COMMANDS
+       bool "Include support for setting handler scripts (e.g. --on-up) on the command line"
+       depends on PACKAGE_fastd
+       default n
+
+endmenu
diff --git a/net/fastd/Makefile b/net/fastd/Makefile
new file mode 100644 (file)
index 0000000..873ace8
--- /dev/null
@@ -0,0 +1,163 @@
+#
+# Copyright (C) 2012-2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=fastd
+PKG_VERSION:=12
+PKG_RELEASE:=1
+
+PKG_MAINTAINER:=Matthias Schiffer <[email protected]>
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/73
+PKG_MD5SUM:=1dadc61f4d712a10844afcb9b9f49a41
+
+PKG_CONFIG_DEPENDS:=\
+       CONFIG_FASTD_ENABLE_METHOD_CIPHER_TEST \
+       CONFIG_FASTD_ENABLE_METHOD_COMPOSED_GMAC \
+       CONFIG_FASTD_ENABLE_METHOD_GENERIC_GMAC \
+       CONFIG_FASTD_ENABLE_METHOD_GENERIC_POLY1305 \
+       CONFIG_FASTD_ENABLE_METHOD_NULL \
+       CONFIG_FASTD_ENABLE_METHOD_XSALSA20_POLY1305 \
+       CONFIG_FASTD_ENABLE_CIPHER_AES128_CTR \
+       CONFIG_FASTD_ENABLE_CIPHER_NULL \
+       CONFIG_FASTD_ENABLE_CIPHER_SALSA20 \
+       CONFIG_FASTD_ENABLE_CIPHER_SALSA2012 \
+       CONFIG_FASTD_ENABLE_MAC_GHASH \
+       CONFIG_FASTD_WITH_CMDLINE_USER \
+       CONFIG_FASTD_WITH_CMDLINE_LOGGING \
+       CONFIG_FASTD_WITH_CMDLINE_OPERATION \
+       CONFIG_FASTD_WITH_CMDLINE_COMMANDS
+
+
+PKG_BUILD_DEPENDS:=nacl libuecc
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+define Package/fastd
+  SECTION:=net
+  CATEGORY:=Network
+  DEPENDS:=+kmod-tun +librt +libpthread
+  TITLE:=Fast and Secure Tunneling Daemon
+  URL:=https://projects.universe-factory.net/projects/fastd
+  SUBMENU:=VPN
+endef
+
+define Package/fastd/config
+  source "$(SOURCE)/Config.in"
+endef
+
+TARGET_CFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+CMAKE_OPTIONS += \
+       -DCMAKE_BUILD_TYPE:STRING=MINSIZEREL \
+       -DWITH_METHOD_CIPHER_TEST:BOOL=FALSE \
+       -DWITH_METHOD_COMPOSED_GMAC:BOOL=FALSE \
+       -DWITH_METHOD_GENERIC_GMAC:BOOL=FALSE \
+       -DWITH_METHOD_GENERIC_POLY1305:BOOL=FALSE \
+       -DWITH_METHOD_NULL:BOOL=FALSE \
+       -DWITH_METHOD_XSALSA20_POLY1305:BOOL=FALSE \
+       -DWITH_CIPHER_AES128_CTR:BOOL=FALSE \
+       -DWITH_CIPHER_NULL:BOOL=FALSE \
+       -DWITH_CIPHER_SALSA20:BOOL=FALSE \
+       -DWITH_CIPHER_SALSA2012:BOOL=FALSE \
+       -DWITH_MAC_GHASH:BOOL=FALSE \
+       -DWITH_CMDLINE_USER:BOOL=FALSE \
+       -DWITH_CMDLINE_LOGGING:BOOL=FALSE \
+       -DWITH_CMDLINE_OPERATION:BOOL=FALSE \
+       -DWITH_CMDLINE_COMMANDS:BOOL=FALSE \
+       -DWITH_CAPABILITIES:BOOL=FALSE
+
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_CIPHER_TEST),y)
+CMAKE_OPTIONS += -DWITH_METHOD_CIPHER_TEST:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_COMPOSED_GMAC),y)
+CMAKE_OPTIONS += -DWITH_METHOD_COMPOSED_GMAC:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_GENERIC_GMAC),y)
+CMAKE_OPTIONS += -DWITH_METHOD_GENERIC_GMAC:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_GENERIC_POLY1305),y)
+CMAKE_OPTIONS += -DWITH_METHOD_GENERIC_POLY1305:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_NULL),y)
+CMAKE_OPTIONS += -DWITH_METHOD_NULL:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_METHOD_XSALSA20_POLY1305),y)
+CMAKE_OPTIONS += -DWITH_METHOD_XSALSA20_POLY1305:BOOL=TRUE
+endif
+
+
+ifeq ($(CONFIG_FASTD_ENABLE_CIPHER_AES128_CTR),y)
+CMAKE_OPTIONS += -DWITH_CIPHER_AES128_CTR:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_CIPHER_NULL),y)
+CMAKE_OPTIONS += -DWITH_CIPHER_NULL:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_CIPHER_SALSA20),y)
+CMAKE_OPTIONS += -DWITH_CIPHER_SALSA20:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_ENABLE_CIPHER_SALSA2012),y)
+CMAKE_OPTIONS += -DWITH_CIPHER_SALSA2012:BOOL=TRUE
+endif
+
+
+ifeq ($(CONFIG_FASTD_ENABLE_MAC_GHASH),y)
+CMAKE_OPTIONS += -DWITH_MAC_GHASH:BOOL=TRUE
+endif
+
+
+ifeq ($(CONFIG_FASTD_WITH_CMDLINE_USER),y)
+CMAKE_OPTIONS += -DWITH_CMDLINE_USER:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_WITH_CMDLINE_LOGGING),y)
+CMAKE_OPTIONS += -DWITH_CMDLINE_LOGGING:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_WITH_CMDLINE_OPERATION),y)
+CMAKE_OPTIONS += -DWITH_CMDLINE_OPERATION:BOOL=TRUE
+endif
+
+ifeq ($(CONFIG_FASTD_WITH_CMDLINE_COMMANDS),y)
+CMAKE_OPTIONS += -DWITH_CMDLINE_COMMANDS:BOOL=TRUE
+endif
+
+
+define Package/fastd/description
+ Fast and secure tunneling daemon, which is optimized on small code size and few dependencies
+endef
+
+define Package/fastd/conffiles
+/etc/config/fastd
+endef
+
+define Package/fastd/install
+       $(INSTALL_DIR) $(1)/usr/bin
+       $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/fastd $(1)/usr/bin/
+
+       $(INSTALL_DIR) $(1)/etc/init.d/
+       $(INSTALL_BIN) files/fastd.init $(1)/etc/init.d/fastd
+       $(INSTALL_DIR) $(1)/etc/config
+       $(INSTALL_CONF) files/fastd.config $(1)/etc/config/fastd
+       $(INSTALL_DIR) $(1)/etc/fastd
+       $(INSTALL_DIR) $(1)/lib/upgrade/keep.d
+       $(INSTALL_DATA) files/fastd.upgrade $(1)/lib/upgrade/keep.d/fastd
+endef
+
+$(eval $(call BuildPackage,fastd))
diff --git a/net/fastd/files/fastd.config b/net/fastd/files/fastd.config
new file mode 100644 (file)
index 0000000..b47cc65
--- /dev/null
@@ -0,0 +1,143 @@
+package fastd
+
+config fastd sample_config
+
+       # Set to 1 to enable this instance:
+       option enabled 0
+
+       # Sets a static config file, optional
+       # Options set via UCI have higher priority that statically configured ones
+#      list config '/etc/fastd/sample_config/fastd.conf'
+
+       # Configures a single static peer from a configuration file
+#      list config_peer '/etc/fastd/sample_config/sample_peer.conf'
+
+       # Sets an additional directory from which peers configurations are read
+       # The peer list can be reloaded without restarting fastd
+       # Peer can either be configured via UCI (see examples below) or via peer dirs
+       # Can't be used in tun mode
+#      list config_peer_dir '/etc/fastd/sample_config/peers'
+
+       # Sets the log level
+       # Possible values: error, warn, info, verbose, debug
+       # Default: info
+       option syslog_level 'info'
+
+       # IP address and port of the local end, optional
+       # 'any' can be used to bind to both IPv4 and IPv6
+       # If no port is given fastd will bind to a random port
+#      list bind 'any:1337'
+#      list bind '0.0.0.0:1337'
+#      list bind '[::]:1337'
+
+       # "method null" uses no encryption or MAC
+       # "method xsalsa20-poly1305" uses the XSalsa20 encryption ad the Poly1305 MAC
+       list method 'xsalsa20-poly1305'
+
+       # "mode tap" will create an ethernet tunnel (tap device),
+       # "mode tun" will create an IP tunnel (tun device).
+       option mode 'tap'
+
+       # Set the name of the tunnel interface to use
+       option interface 'tap0'
+#      option interface 'tun0'
+#      option interface 'fastd0'
+
+       # Sets the MTU of the tunnel interface, default is 1500
+       # 1426 is a good value that avoids fragmentation for the xsalsa20-poly1305 method
+       # when the tunnel uses an IPv4 connection on a line with an MTU of 1492 or higher
+       option mtu 1426
+
+       # Enables direct forwaring of packets between peers
+       # WARNING: Only enable this if you know what you are doing, as this can lead to forwarding loops!
+       option forward 0
+
+       # Disable for compatiblity with fastd v10 and older
+       option secure_handshakes 1
+
+       # Set a packet mark to filter for with iptables or ip rules
+#      option packet_mark 42
+
+       # Limits the maximum number of connections, optional
+#      option peer_limit 5
+
+       # The secret key
+       # A keypair can be generated with `fastd --generate-key`
+       # When the corresponding public key is lost it can be recovered with `/etc/init.d/fastd show-key <config name>`
+#      option secret '0000000000000000000000000000000000000000000000000000000000000000'
+
+       # Sets the user to run fastd as. Defaults to root
+#      option user 'daemon'
+
+       # Sets the group to run fastd as. Defaults to the user's primary group
+#      option group 'daemon'
+
+       # If set to 1, the logs won't contain peers' IP addresses
+#      option hide_ip_addresses '0'
+
+       # If set to 1, the logs won't contain peers' MAC addresses
+#      option hide_mac_addresses '0'
+
+       # Read the documentation about this one. Only ever useful in severly broken networks.
+#      option pmtu ''
+
+       # command to configure IP addresses etc. after the tunnel interface is up; $1 will be the interface name (optional)
+#      option up ''
+
+       # command to execute before the tunnel interface is set down; $1 will be the interface name (optional)
+#      option down ''
+
+
+config peer sample_peer
+
+       # Set to 1 to enable this peer
+       # In tap mode peers can be reloaded dynamically
+       option enabled 0
+
+       # Controls which instance this peer is associated with
+       option net 'sample_config'
+
+       # Controls which peer group this peer belongs to, optional
+       # For most use cases peer groups aren't necessary
+#      option group 'sample_group'
+
+       # The peer's public key
+       option key '0000000000000000000000000000000000000000000000000000000000000000'
+
+       # A remote specification consists of an address or a hostname, and a port
+       # When a hostname is given, it is recommended to specify the address family to use
+       # It is possible to specify no, one or multiple remotes
+       # (but all entries must designate the same host as the public key must be unique)
+#      list remote '192.0.2.1:1337'
+#      list remote '[2001:db8::1]:1337'
+#      list remote '"example.com" port 1337'
+#      list remote 'ipv4 "example.com" port 1337'
+#      list remote 'ipv6 "example.com" port 1337'
+
+       # Setting float to 1 allow incoming connections with this key from other addresses/hostnames/ports than the specified remotes
+#      option float 0
+
+
+config peer_group sample_group
+
+       # Set to 1 to enable this peer group
+       option enabled 0
+
+       # Controls which instance this peer group is associated with
+       # Peer groups can't be used in tun mode
+       option net 'sample_config'
+
+       # Allows configuring nested groups
+#      option parent 'other_group'
+
+       # Includes another config file inside the peer group definition
+#      list config '/etc/fastd/sample_config/sample_group.conf'
+
+       # Configures a single static peer from a configuration file
+#      list config_peer '/etc/fastd/sample_config/sample_peer.conf'
+
+       # Configures an additional peer directory for this group
+#      list config_peer_dir '/etc/fastd/sample_config/peers2'
+
+       # Limits the maximum number of connections to peers in this group (optional)
+#      option peer_limit 5
diff --git a/net/fastd/files/fastd.init b/net/fastd/files/fastd.init
new file mode 100644 (file)
index 0000000..d55e6ff
--- /dev/null
@@ -0,0 +1,420 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2012-2013 OpenWrt.org
+
+START=95
+
+EXTRA_COMMANDS="up down show_key generate_key"
+
+LIST_SEP="
+"
+TMP_FASTD=/tmp/fastd
+FASTD_COMMAND=/usr/bin/fastd
+
+
+section_enabled() {
+       config_get_bool enabled "$1" 'enabled' 0
+       [ $enabled -gt 0 ]
+}
+
+error() {
+       echo "${initscript}:" "$@" 1>&2
+}
+
+get_key_instance() {
+       local s="$1"
+
+       config_get secret "$s" secret
+       if [ "$secret" = 'generate' ]; then
+               secret=`"$FASTD_COMMAND" --generate-key --machine-readable`
+               uci -q set fastd."$s".secret="$secret" && uci -q commit fastd
+       fi
+
+       echo "$secret"
+}
+
+
+escape_string() {
+       local t=${1//\\/\\\\}
+       echo -n "\"${t//\"/\\\"}\""
+}
+
+guard_value() {
+       local t=${1//[^-a-z0-9\[\].:]/}
+       echo -n "$t"
+}
+
+guard_remote() {
+       local t=${1//[^-a-zA-Z0-9\[\].:\"% ]/}
+       local quotes=${t//[^\"]/}
+       if [ "${#quotes}" = 0 -o "${#quotes}" = 2 ]; then
+               echo -n "$t"
+       fi
+}
+
+yes_no() {
+       case "$1" in
+               0|no|off|false|disabled) echo -n no;;
+               *) echo -n yes;;
+       esac
+}
+
+config_string_config='include $(escape_string "$value");'
+config_string_config_peer='include peer $(escape_string "$value");'
+config_string_config_peer_dir='include peers from $(escape_string "$value");'
+config_string_bind='bind $(guard_value "$value");'
+config_string_method='method $(escape_string "$value");'
+config_string_syslog_level='log to syslog level $(guard_value "$value");'
+config_string_mode='mode $(guard_value "$value");'
+config_string_interface='interface $(escape_string "$value");'
+config_string_mtu='mtu $(guard_value "$value");'
+config_string_peer_limit='peer limit $(guard_value "$value");'
+config_string_user='user $(escape_string "$value");'
+config_string_group='group $(escape_string "$value");'
+config_string_pmtu='pmtu $(yes_no "$value");'
+config_string_forward='forward $(yes_no "$value");'
+config_string_hide_ip_addresses='hide ip addresses $(yes_no "$value");'
+config_string_hide_mac_addresses='hide mac addresses $(yes_no "$value");'
+config_string_secure_handshakes='secure handshakes $(yes_no "$value");'
+config_string_packet_mark='packet mark $(guard_value "$value");'
+
+config_string_peer='peer $(escape_string "$value") {'
+config_string_peer_group='peer group $(escape_string "$value") {'
+
+peer_string_key='key $(escape_string "$value");'
+peer_string_float='float $(yes_no "$value");'
+peer_string_remote='remote $(guard_remote "$value");'
+
+generate_option() {
+       local __string=$(eval echo \"\$$2\")
+       local value="$1";
+       eval echo "\"$__string\""
+}
+
+append_option() {
+       local v; local len; local s="$1"; local prefix="$2"; local p="$3"
+
+       config_get len "$s" "${p}_LENGTH"
+
+       if [ -z "$len" ]; then
+               config_get v "$s" "$p"
+               [ -n "$v" ] && generate_option "$v" "${prefix}_string_${p}"
+       else
+               config_list_foreach "$s" "$p" generate_option "${prefix}_string_${p}"
+       fi
+}
+
+append_options() {
+       local p; local s="$1"; local prefix="$2"; shift; shift
+       for p in $*; do
+               append_option "$s" "$prefix" "$p"
+       done
+}
+
+
+generate_config_secret() {
+       echo "secret $(escape_string "$1");"
+}
+
+
+generate_peer_config() {
+       local peer="$1"
+
+       # These options are deprecated
+       config_get address "$peer" address
+       config_get hostname "$peer" hostname
+       config_get address_family "$peer" address_family
+       config_get port "$peer" port
+
+       if [ "$address" -o "$hostname" ]; then
+               if [ -z "$port" ]; then
+                       error "peer $peer: address or hostname, but no port given"
+                       return 1
+               fi
+
+               if [ "$hostname" ]; then
+                       generate_option peer_string_remote "$address_family \"$hostname\" port $port"
+               fi
+
+               if [ "$address" ]; then
+                       generate_option peer_string_remote "$address port $port"
+               fi
+       fi
+
+       append_options "$peer" peer \
+               key float remote
+}
+
+generate_single_peer_config() {
+       local peer="$1"; local net="$2"
+
+       config_get peer_net "$peer" net
+       config_get peer_group "$peer" group
+       [ "$net" = "$peer_net" -a "$peer_group" = '' ] || return 0
+
+       section_enabled "$peer" || return 0
+
+       generate_option "$peer" config_string_peer
+       generate_peer_config "$peer"
+       echo '}'
+}
+
+create_peer_config() {
+       local peer="$1"; local net="$2"; local group="$3"; local path="$4"
+
+       config_get peer_net "$peer" net
+       config_get peer_group "$peer" group
+       [ "$group" = "$peer_group" ] || return 0
+
+       if [ "$net" != "$peer_net" ]; then
+               [ -z "$group" ] || error "warning: the peer group of peer '$peer' doesn't match its net, the peer will be ignored"
+               return 0
+       fi
+
+       section_enabled "$peer" || return 0
+
+       generate_peer_config "$peer" >"$path/$peer"
+}
+
+update_peer_group() {
+       local net="$1"; local group_dir="$2"; local group="$3"; local update_only="$4"
+       local path="$TMP_FASTD/fastd.$net/$group_dir"
+
+       rm -rf "$path"
+       mkdir -p "$path"
+
+       config_foreach create_peer_config 'peer' "$net" "$group" "$path"
+
+       if [ -z "$update_only" ]; then
+               generate_option "$path" config_string_config_peer_dir
+       fi
+
+       config_foreach generate_peer_group_config 'peer_group' "$net" "$group_dir" "$update_only" "$group"
+}
+
+generate_peer_group_config() {
+       local group="$1"; local net="$2"; local group_dir="$3%$group"; local update_only="$4"; local parent="$5"
+
+       config_get group_net "$group" net
+       config_get group_parent "$group" parent
+       [ "$parent" = "$group_parent" ] || return 0
+
+       if [ "$net" != "$peer_net" ]; then
+               [ -z "$parent" ] || error "warning: the parent of peer group '$group' doesn't match its net, the peer group will be ignored"
+               return 0
+       fi
+
+       section_enabled "$group" || return 0
+
+       if [ -z "$update_only" ]; then
+               generate_option "$group" config_string_peer_group
+               append_options "$group" config \
+                       config config_peer config_peer_dir peer_limit
+       fi
+
+       update_peer_group "$net" "$group_dir" "$group" "$update_only"
+
+       if [ -z "$update_only" ]; then
+               echo '}'
+       fi
+}
+
+update_peer_groups() {
+       local net="$1"; local update_only="$2"
+
+       update_peer_group "$net" 'peers' '' "$update_only"
+}
+
+generate_config() {
+       local s="$1"
+
+       generate_option 'info' config_string_syslog_level
+
+       append_options "$s" config \
+               config config_peer config_peer_dir bind method syslog_level mode interface mtu peer_limit \
+               user group pmtu forward hide_ip_addresses hide_mac_addresses secure_handshakes packet_mark
+
+       config_get mode "$s" mode
+
+       if [ "$mode" = "tun" ]; then
+               config_foreach generate_single_peer_config 'peer' "$s"
+       else
+               update_peer_groups "$s"
+       fi
+}
+
+
+generate_key_instance() {
+       local s="$1"
+
+       config_get secret "$s" secret
+       if [ -z "$secret" -o "$secret" = 'generate' ]; then
+               secret=`fastd --generate-key --machine-readable`
+               uci -q set fastd."$s".secret="$secret" && uci -q commit fastd
+       fi
+
+       generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable
+}
+
+show_key_instance() {
+       local s="$1"
+
+       local secret=`get_key_instance "$s"`
+       if [ -z "$secret" ]; then
+               error "$s: secret is not set"
+               return 1
+       fi
+
+       generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable
+}
+
+start_instance() {
+       local s="$1"
+
+       section_enabled "$s" || return 1
+
+       SERVICE_PID_FILE="/var/run/fastd.$s.pid"
+
+       config_get interface "$s" interface
+       if [ -z "$interface" ]; then
+               error "$s: interface is not set"
+               return 1
+       fi
+
+       if ifconfig "$interface" &>/dev/null; then
+               error "$s: interface '$interface' is already in use"
+               return 1
+       fi
+
+       config_get mode "$s" mode
+       if [ -z "$mode" ]; then
+               error "$s: mode is not set"
+               return 1
+       fi
+
+       local secret=`get_key_instance "$s"`
+       if [ -z "$secret" ]; then
+               error "$s: secret is not set"
+               return 1
+       fi
+
+       rm -f "$SERVICE_PID_FILE"
+       touch "$SERVICE_PID_FILE"
+
+       config_get user "$s" user
+       if [ "$user" ]; then
+               chown "$user" "$SERVICE_PID_FILE"
+       fi
+
+       (generate_config_secret "$secret"; generate_config "$s") | service_start "$FASTD_COMMAND" --config - --daemon --pid-file "$SERVICE_PID_FILE"
+
+       if ! ifconfig "$interface" >/dev/null 2>&1; then
+               error "$s: startup failed"
+               return 1
+       fi
+
+       config_get up "$s" up
+       [ -n "$up" ] && sh -c "$up" - "$interface"
+}
+
+stop_instance() {
+       local s="$1"
+
+       section_enabled "$s" || return 1
+
+       SERVICE_PID_FILE="/var/run/fastd.$s.pid"
+
+       config_get interface "$s" interface
+       if [ -z "$interface" ]; then
+               error "$s: interface is not set"
+               return 1
+       fi
+
+       if ! ifconfig "$interface" &>/dev/null; then
+               error "$s: interface '$interface' does not exist"
+               return 1
+       fi
+
+       config_get down "$s" down
+       [ -n "$down" ] && sh -c "$down" - "$interface"
+
+       service_stop "$FASTD_COMMAND"
+
+       rm -rf "$TMP_FASTD/fastd.$s"
+}
+
+reload_instance() {
+       local s="$1"
+
+       section_enabled "$s" || return 1
+
+       config_get mode "$s" mode
+       [ "$mode" = "tun" ] && return 1
+
+       update_peer_groups "$s" true
+
+       SERVICE_PID_FILE="/var/run/fastd.$s.pid"
+       service_reload "$FASTD_COMMAND"
+}
+
+start() {
+       config_load 'fastd'
+       config_foreach start_instance 'fastd'
+}
+
+stop() {
+       config_load 'fastd'
+       config_foreach stop_instance 'fastd'
+}
+
+reload() {
+       config_load 'fastd'
+       config_foreach reload_instance 'fastd'
+}
+
+up() {
+       local exists
+       local instance
+       config_load 'fastd'
+       for instance in "$@"; do
+               config_get exists "$instance" 'TYPE'
+               if [ "$exists" = 'fastd' ]; then
+                       start_instance "$instance"
+               fi
+       done
+}
+
+down() {
+       local exists
+       local instance
+       config_load 'fastd'
+       for instance in "$@"; do
+               config_get exists "$instance" 'TYPE'
+               if [ "$exists" = 'fastd' ]; then
+                       stop_instance "$instance"
+               fi
+       done
+}
+
+show_key() {
+       local exists
+       local instance
+       config_load 'fastd'
+       for instance in "$@"; do
+               config_get exists "$instance" 'TYPE'
+               if [ "$exists" = 'fastd' ]; then
+                       show_key_instance "$instance"
+               fi
+       done
+}
+
+generate_key() {
+       local exists
+       local instance
+       config_load 'fastd'
+       for instance in "$@"; do
+               config_get exists "$instance" 'TYPE'
+               if [ "$exists" = 'fastd' ]; then
+                       generate_key_instance "$instance"
+               fi
+       done
+}
diff --git a/net/fastd/files/fastd.upgrade b/net/fastd/files/fastd.upgrade
new file mode 100644 (file)
index 0000000..7406613
--- /dev/null
@@ -0,0 +1 @@
+/etc/fastd/