aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorIan Leonard <antonlacon@gmail.com>2014-08-10 01:09:06 -0700
committerIan Leonard <antonlacon@gmail.com>2014-08-10 01:09:06 -0700
commitf5a1d1bba66d293486dc74bbc1de767dc7054013 (patch)
tree7685a0f8f7e195e22d93ab8ea8825a92d117e229 /net
parentd55f37ea1a920beea420a50f4104a3d4109b095a (diff)
parent048e700bfc72247e425bd5ace12d90bbc39f8599 (diff)
Merge branch 'master' into license-updates
Signed-off-by: Ian Leonard <antonlacon@gmail.com> Conflicts: devel/patch/Makefile multimedia/minidlna/Makefile
Diffstat (limited to 'net')
-rw-r--r--net/dhcpcd/Makefile63
-rwxr-xr-xnet/dhcpcd/files/dhcpcd.init24
-rw-r--r--net/ethtool/Makefile7
-rw-r--r--net/ethtool/patches/100-ixp4xx.patch166
-rw-r--r--net/fastd/Makefile3
-rw-r--r--net/freeradius2/Makefile17
-rw-r--r--net/horst/Makefile45
-rw-r--r--net/mwan3-luci/Makefile40
-rw-r--r--net/mwan3-luci/files/etc/hotplug.d/iface/16-mwan3custombak38
-rwxr-xr-xnet/mwan3-luci/files/etc/uci-defaults/mwan314
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/controller/mwan3.lua355
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_hotplug.lua55
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_mwan3.lua32
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_network.lua32
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interface.lua266
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interfaceconfig.lua191
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_member.lua46
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_memberconfig.lua47
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policy.lua82
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policyconfig.lua58
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_rule.lua109
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_ruleconfig.lua99
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/admin_status/index/mwan3.htm1
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_diagnostics.htm134
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_hotplug.htm23
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_mwan3.htm23
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_network.htm23
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_troubleshoot.htm77
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_config_css.htm34
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_detail.htm62
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_interface.htm146
-rw-r--r--net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_status.htm95
-rw-r--r--net/mwan3/Makefile48
-rw-r--r--net/mwan3/files/etc/config/mwan379
-rw-r--r--net/mwan3/files/etc/hotplug.d/iface/15-mwan3328
-rwxr-xr-xnet/mwan3/files/etc/init.d/mwan320
-rwxr-xr-xnet/mwan3/files/usr/sbin/mwan3208
-rwxr-xr-xnet/mwan3/files/usr/sbin/mwan3track65
-rw-r--r--net/netatalk/Makefile86
-rw-r--r--net/netatalk/files/AppleVolumes.default2
-rw-r--r--net/netatalk/files/afpd.conf1
-rw-r--r--net/netatalk/files/afpd.init23
-rw-r--r--net/netatalk/patches/001-automake-compat.patch9
-rw-r--r--net/nginx/Makefile2
-rw-r--r--net/nginx/patches/400-nginx-1.4.x_proxy_protocol_patch_v2.patch11
-rw-r--r--net/ocserv/files/ocserv.init26
-rw-r--r--net/p910nd/Makefile59
-rw-r--r--net/p910nd/files/p910nd.config5
-rw-r--r--net/p910nd/files/p910nd.init51
-rw-r--r--net/radsecproxy/Makefile57
-rw-r--r--net/radsecproxy/files/radsecproxy.init16
-rw-r--r--net/radsecproxy/patches/100-missing-return.patch58
-rw-r--r--net/radsecproxy/patches/200-logdest-on-foreground.patch31
-rw-r--r--net/rsync/Makefile1
-rw-r--r--net/sslh/Makefile2
-rw-r--r--net/tgt/Makefile1
-rw-r--r--net/tinc/Makefile60
-rw-r--r--net/tinc/files/tinc.config56
-rw-r--r--net/tinc/files/tinc.init241
-rw-r--r--net/tinc/files/tinc.upgrade1
-rw-r--r--net/vsftpd/Makefile1
-rw-r--r--net/wget/Makefile1
62 files changed, 3741 insertions, 215 deletions
diff --git a/net/dhcpcd/Makefile b/net/dhcpcd/Makefile
new file mode 100644
index 000000000..9add73476
--- /dev/null
+++ b/net/dhcpcd/Makefile
@@ -0,0 +1,63 @@
+#
+# Copyright (C) 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:=dhcpcd
+PKG_VERSION:=6.4.3
+PKG_RELEASE:=1
+
+PKG_SOURCE_URL:=ftp://roy.marples.name/pub/dhcpcd \
+ http://roy.marples.name/downloads/dhcpcd
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_MD5SUM:=b22005c131e7108ecf598b6a4ac091eb
+
+PKG_LICENSE:=BSD-2c
+PKG_LICENSE_FILES:=
+
+PKG_MAINTAINER:=Roy Marples <roy@marples.name>
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/dhcpcd
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=DHCPv4/IPv4LL/IPv6RS/DHCPv6 quad stack client
+ URL:=http://roy.marples.name/projects/dhcpcd
+endef
+
+define Package/dhcpcd/description
+ DHCPv4, IPv6RS and DHCPv6 client with IPv4LL support
+ dhcpcd is a one stop network management daemon which includes
+ * RFC compliant DHCPv4 and DHCPv6 clients
+ * DHCPv6 Prefix Delegation support
+ * IPv4LL (aka ZeroConf) support
+ * ARP address conflict resolution
+ * Link carrier detection
+ * Wireless SSID profiles
+ * ARP ping profiles
+endef
+
+CONFIGURE_ARGS+= --prefix=/ --sbindir=/sbin \
+ --libexecdir=/lib/dhcpcd --dbdir=/var/dhcpcd
+
+define Package/dhcpcd/install
+ $(INSTALL_DIR) $(1)/sbin $(1)/etc $(1)/lib/dhcpcd/dhcpcd-hooks
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/sbin/dhcpcd $(1)/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/lib/dhcpcd/dhcpcd-run-hooks \
+ $(1)/lib/dhcpcd/
+ $(INSTALL_DATA) $(PKG_INSTALL_DIR)/lib/dhcpcd/dhcpcd-hooks/* \
+ $(1)/lib/dhcpcd/dhcpcd-hooks/
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/dhcpcd.init $(1)/etc/init.d/dhcpcd
+ $(INSTALL_CONF) $(PKG_INSTALL_DIR)/etc/dhcpcd.conf $(1)/etc/dhcpcd.conf
+endef
+
+$(eval $(call BuildPackage,dhcpcd))
diff --git a/net/dhcpcd/files/dhcpcd.init b/net/dhcpcd/files/dhcpcd.init
new file mode 100755
index 000000000..2fad41dd4
--- /dev/null
+++ b/net/dhcpcd/files/dhcpcd.init
@@ -0,0 +1,24 @@
+#!/bin/sh /etc/rc.common
+#
+# Copyright (C) 2014 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+START=30
+STOP=85
+USE_PROCD=1
+
+start_service()
+{
+ procd_open_instance
+ procd_set_param command /sbin/dhcpcd -B
+ procd_set_param respawn
+ procd_close_instance
+}
+
+reload_service()
+{
+ /sbin/dhcpcd -n
+}
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 1f2cea167..7fa772aed 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -8,13 +8,16 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ethtool
-PKG_VERSION:=3.14
+PKG_VERSION:=3.15
PKG_RELEASE:=1
PKG_MAINTAINER:=Matthias Schiffer <mschiffer@universe-factory.net>
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/software/network/ethtool
-PKG_MD5SUM:=d46b809ddd672b51d7e23787ae9122e0
+PKG_MD5SUM:=e7bf0c355d2bf6ee281ebc713c5fb987
+
+PKG_LICENSE:=GPL-2.0
+PKG_LICENSE_FILE:=COPYING
PKG_FIXUP:=autoreconf
PKG_INSTALL:=1
diff --git a/net/ethtool/patches/100-ixp4xx.patch b/net/ethtool/patches/100-ixp4xx.patch
deleted file mode 100644
index 48c011920..000000000
--- a/net/ethtool/patches/100-ixp4xx.patch
+++ /dev/null
@@ -1,166 +0,0 @@
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -13,7 +13,7 @@ ethtool_SOURCES += \
- fec_8xx.c ibm_emac.c ixgb.c ixgbe.c natsemi.c \
- pcnet32.c realtek.c tg3.c marvell.c vioc.c \
- smsc911x.c at76c50x-usb.c sfc.c stmmac.c \
-- sfpid.c sfpdiag.c ixgbevf.c
-+ sfpid.c sfpdiag.c ixgbevf.c ixp4xx.c
- endif
-
- TESTS = test-cmdline test-features
---- a/ethtool.c
-+++ b/ethtool.c
-@@ -894,6 +894,7 @@ static const struct {
- { "ixgb", ixgb_dump_regs },
- { "ixgbe", ixgbe_dump_regs },
- { "ixgbevf", ixgbevf_dump_regs },
-+ { "ixp4xx", ixp4xx_dump_regs },
- { "natsemi", natsemi_dump_regs },
- { "e100", e100_dump_regs },
- { "amd8111e", amd8111e_dump_regs },
---- a/internal.h
-+++ b/internal.h
-@@ -243,6 +243,9 @@ int st_gmac_dump_regs(struct ethtool_drv
- /* Et131x ethernet controller */
- int et131x_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
-
-+/* Intel IXP4xx internal MAC */
-+int ixp4xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs);
-+
- /* Rx flow classification */
- int rxclass_parse_ruleopts(struct cmd_context *ctx,
- struct ethtool_rx_flow_spec *fsp);
---- /dev/null
-+++ b/ixp4xx.c
-@@ -0,0 +1,130 @@
-+/*
-+ * Copyright (c) 2006 Christian Hohnstaed <chohnstaedt@innominate.com>
-+ * This file is released under the GPLv2
-+ */
-+
-+#include <stdio.h>
-+#include "internal.h"
-+
-+#ifndef BIT
-+#define BIT(x) (1<<x)
-+#endif
-+
-+#define TX_CNTRL1_TX_EN BIT(0)
-+#define TX_CNTRL1_DUPLEX BIT(1)
-+#define TX_CNTRL1_RETRY BIT(2)
-+#define TX_CNTRL1_PAD_EN BIT(3)
-+#define TX_CNTRL1_FCS_EN BIT(4)
-+#define TX_CNTRL1_2DEFER BIT(5)
-+#define TX_CNTRL1_RMII BIT(6)
-+
-+/* TX Control Register 2 */
-+#define TX_CNTRL2_RETRIES_MASK 0xf
-+
-+/* RX Control Register 1 */
-+#define RX_CNTRL1_RX_EN BIT(0)
-+#define RX_CNTRL1_PADSTRIP_EN BIT(1)
-+#define RX_CNTRL1_CRC_EN BIT(2)
-+#define RX_CNTRL1_PAUSE_EN BIT(3)
-+#define RX_CNTRL1_LOOP_EN BIT(4)
-+#define RX_CNTRL1_ADDR_FLTR_EN BIT(5)
-+#define RX_CNTRL1_RX_RUNT_EN BIT(6)
-+#define RX_CNTRL1_BCAST_DIS BIT(7)
-+
-+/* Core Control Register */
-+#define CORE_RESET BIT(0)
-+#define CORE_RX_FIFO_FLUSH BIT(1)
-+#define CORE_TX_FIFO_FLUSH BIT(2)
-+#define CORE_SEND_JAM BIT(3)
-+#define CORE_MDC_EN BIT(4)
-+
-+#define MAC "%02x:%02x:%02x:%02x:%02x:%02x"
-+#define MAC_DATA(d) (d)[0], (d)[1], (d)[2], (d)[3], (d)[4], (d)[5]
-+
-+int ixp4xx_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
-+{
-+ u8 *data = regs->data;
-+
-+ fprintf(stdout,
-+ "TXctrl: 0x%02x:0x%02x\n"
-+ " Enable: %s\n"
-+ " Duplex: %s\n"
-+ " Retry: %s (%d)\n"
-+ " Padding: %s\n"
-+ " Frame check: %s\n"
-+ " TX deferral: %s\n"
-+ " Connection: %s\n"
-+ "\n",
-+ data[0], data[1],
-+ data[0] & TX_CNTRL1_TX_EN ? "yes" : "no",
-+ data[0] & TX_CNTRL1_DUPLEX ? "half" : "full",
-+ data[0] & TX_CNTRL1_RETRY ? "enabled" : "disabled",
-+ data[1] & TX_CNTRL2_RETRIES_MASK,
-+ data[0] & TX_CNTRL1_PAD_EN ? "enabled" : "disabled",
-+ data[0] & TX_CNTRL1_FCS_EN ? "enabled" : "disabled",
-+ data[0] & TX_CNTRL1_2DEFER ? "two-part" : "one-part",
-+ data[0] & TX_CNTRL1_RMII ? "RMII" : "Full MII"
-+ );
-+
-+ fprintf(stdout,
-+ "RXctrl: 0x%02x\n"
-+ " Enable: %s\n"
-+ " Pad strip: %s\n"
-+ " CRC check: %s\n"
-+ " Pause: %s\n"
-+ " Loop: %s\n"
-+ " Promiscous: %s\n"
-+ " Runt frames: %s\n"
-+ " Broadcast: %s\n"
-+ "\n",
-+ data[2],
-+ data[2] & RX_CNTRL1_RX_EN ? "yes" : "no",
-+ data[2] & RX_CNTRL1_PADSTRIP_EN ? "enabled" : "disabled",
-+ data[2] & RX_CNTRL1_CRC_EN ? "enabled" : "disabled",
-+ data[2] & RX_CNTRL1_PAUSE_EN ? "enabled" : "disabled",
-+ data[2] & RX_CNTRL1_LOOP_EN ? "enabled" : "disabled",
-+ data[2] & RX_CNTRL1_ADDR_FLTR_EN ? "disabled" : "enabled",
-+ data[2] & RX_CNTRL1_RX_RUNT_EN ? "forward" : "discard",
-+ data[2] & RX_CNTRL1_BCAST_DIS ? "disabled" : "enabled"
-+ );
-+ fprintf(stdout,
-+ "Core control: 0x%02x\n"
-+ " Core state: %s\n"
-+ " RX fifo: %s\n"
-+ " TX fifo: %s\n"
-+ " Send jam: %s\n"
-+ " MDC clock %s\n"
-+ "\n",
-+ data[32],
-+ data[32] & CORE_RESET ? "reset" : "normal operation",
-+ data[32] & CORE_RX_FIFO_FLUSH ? "flush" : "ok",
-+ data[32] & CORE_TX_FIFO_FLUSH ? "flush" : "ok",
-+ data[32] & CORE_SEND_JAM ? "yes" : "no",
-+ data[32] & CORE_MDC_EN ? "output" : "input"
-+ );
-+ fprintf(stdout,
-+ "MAC addresses: \n"
-+ " Multicast mask: " MAC "\n"
-+ " Multicast address: " MAC "\n"
-+ " Unicast address: " MAC "\n"
-+ "\n",
-+ MAC_DATA(data+13), MAC_DATA(data+19), MAC_DATA(data+26)
-+ );
-+ fprintf(stdout,
-+ "Random seed: 0x%02x\n"
-+ "Threshold empty: %3d\n"
-+ "Threshold full: %3d\n"
-+ "TX buffer size: %3d\n"
-+ "TX deferral: %3d\n"
-+ "RX deferral: %3d\n"
-+ "TX two deferral 1: %3d\n"
-+ "TX two deferral 2: %3d\n"
-+ "Slot time: %3d\n"
-+ "Internal clock: %3d\n"
-+ "\n",
-+ data[4], data[5], data[6], data[7], data[8], data[9],
-+ data[10], data[11], data[12], data[25]
-+ );
-+
-+ return 0;
-+}
diff --git a/net/fastd/Makefile b/net/fastd/Makefile
index 0629cd7b6..e2fca698e 100644
--- a/net/fastd/Makefile
+++ b/net/fastd/Makefile
@@ -16,6 +16,9 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/75
PKG_MD5SUM:=34f6bdebd0410a1fba7c8fd06fff7a05
+PKG_LICENSE:=BSD-2-Clause
+PKG_LICENSE_FILE:=COPYRIGHT
+
PKG_CONFIG_DEPENDS:=\
CONFIG_FASTD_ENABLE_METHOD_CIPHER_TEST \
CONFIG_FASTD_ENABLE_METHOD_COMPOSED_GMAC \
diff --git a/net/freeradius2/Makefile b/net/freeradius2/Makefile
index 194913d17..4eddb26b2 100644
--- a/net/freeradius2/Makefile
+++ b/net/freeradius2/Makefile
@@ -18,6 +18,7 @@ PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
PKG_BUILD_DIR:=$(BUILD_DIR)/freeradius-server-$(PKG_VERSION)
PKG_FIXUP:=autoreconf
+PKG_CHECK_FORMAT_SECURITY:=0
PKG_CONFIG_DEPENDS := \
FREERADIUS_OPENSSL \
@@ -415,14 +416,14 @@ PKG_DICTIONARIES:= \
microsoft \
wispr \
-#ifneq ($(SDK)$(CONFIG_PACKAGE_freeradius2-mod-ldap),)
-# CONFIGURE_ARGS+= \
-# --with-rlm_ldap-include-dir="$(STAGING_DIR)/usr/include" \
-# --with-rlm_ldap-lib-dir="$(STAGING_DIR)/usr/lib"
-# CONFIGURE_LIBS+= -lcrypto -lssl
-#else
+ifneq ($(SDK)$(CONFIG_PACKAGE_freeradius2-mod-ldap),)
+ CONFIGURE_ARGS+= \
+ --with-rlm_ldap-include-dir="$(STAGING_DIR)/usr/include" \
+ --with-rlm_ldap-lib-dir="$(STAGING_DIR)/usr/lib"
+ CONFIGURE_LIBS+= -lcrypto -lssl
+else
CONFIGURE_ARGS+= --without-rlm_ldap
-#endif
+endif
#ifneq ($(SDK)$(CONFIG_PACKAGE_freeradius2-mod-sql-mysql),)
# CONFIGURE_ARGS+= \
@@ -612,7 +613,7 @@ $(eval $(call BuildPlugin,freeradius2-mod-exec,rlm_exec,modules/exec modules/ech
$(eval $(call BuildPlugin,freeradius2-mod-attr-rewrite,rlm_attr_rewrite,modules/attr_rewrite,modules,))
$(eval $(call BuildPlugin,freeradius2-mod-files,rlm_files,acct_users preproxy_users users modules/files,modules,))
$(eval $(call BuildPlugin,freeradius2-mod-passwd,rlm_passwd,modules/passwd,modules,))
-#$(eval $(call BuildPlugin,freeradius2-mod-ldap,rlm_ldap,ldap.attrmap modules/ldap,modules,))
+$(eval $(call BuildPlugin,freeradius2-mod-ldap,rlm_ldap,ldap.attrmap modules/ldap,modules,))
$(eval $(call BuildPlugin,freeradius2-mod-mschap,rlm_mschap,modules/mschap,modules,))
$(eval $(call BuildPlugin,freeradius2-mod-pap,rlm_pap,modules/pap,modules,))
$(eval $(call BuildPlugin,freeradius2-mod-preprocess,rlm_preprocess,hints huntgroups modules/preprocess,modules,))
diff --git a/net/horst/Makefile b/net/horst/Makefile
new file mode 100644
index 000000000..e746abea7
--- /dev/null
+++ b/net/horst/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2006 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:=horst
+PKG_VERSION:=4.0
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-git.tar.gz
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_URL:=git://br1.einfach.org/horst
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_VERSION:=version-4.0
+
+PKG_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/horst
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=wireless
+ DEPENDS:=+libncurses
+ MAINTAINER:=Bruno Randolf <br1@einfach.org>
+ TITLE:=Highly Optimized 802.11 Radio Scanning Tool
+ URL:=http://br1.einfach.org/tech/horst/
+endef
+
+define Package/horst/description
+ [horst] is a scanning and analysis tool for 802.11 wireless networks
+ and especially IBSS (ad-hoc) mode and mesh networks (OLSR).
+endef
+
+define Package/horst/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/horst $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/horst.sh $(1)/usr/sbin/
+endef
+
+$(eval $(call BuildPackage,horst))
diff --git a/net/mwan3-luci/Makefile b/net/mwan3-luci/Makefile
new file mode 100644
index 000000000..465363326
--- /dev/null
+++ b/net/mwan3-luci/Makefile
@@ -0,0 +1,40 @@
+#
+# Copyright (C) 2006-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:=luci-app-mwan3
+PKG_VERSION:=1.3
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Aedan Renner <chipdankly@gmail.com>
+PKG_LICENSE:=GPLv2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/luci-app-mwan3
+ SECTION:=LuCI
+ CATEGORY:=LuCI
+ SUBMENU:=3. Applications
+ TITLE:=LuCI support for the MWAN3 multiwan hotplug script
+ DEPENDS:=+mwan3
+ PKGARCH:=all
+ MAINTAINER:=Aedan Renner <chipdankly@gmail.com>
+endef
+
+define Package/luci-app-mwan3/description
+Hotplug script which makes configuration of multiple WAN interfaces simple and manageable
+With loadbalancing/failover support for up to 250 WAN interfaces, connection tracking and an easy to manage traffic ruleset
+endef
+
+define Build/Compile
+endef
+
+define Package/luci-app-mwan3/install
+ $(CP) ./files/* $(1)
+endef
+
+$(eval $(call BuildPackage,luci-app-mwan3))
diff --git a/net/mwan3-luci/files/etc/hotplug.d/iface/16-mwan3custombak b/net/mwan3-luci/files/etc/hotplug.d/iface/16-mwan3custombak
new file mode 100644
index 000000000..9bd0beeff
--- /dev/null
+++ b/net/mwan3-luci/files/etc/hotplug.d/iface/16-mwan3custombak
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# to enable this script uncomment the case loop at the bottom
+# to report MWAN3 status on interface up/down events modify the lines in the send_reportdata function
+
+send_alert()
+{
+ # $1 stores the mwan3 status information
+ # insert your code here to send the contents of $1
+ echo "$1"
+}
+
+gather_event_info()
+{
+ # create event information message
+ local EVENT_INFO="Interface [ "$INTERFACE" ($DEVICE) ] on router [ "$(uci get -p /var/state system.@system[0].hostname)" ] has triggered an [ "$ACTION" ] hotplug event on "$(date)""
+
+ # get current interface, policy and rule status
+ local CURRENT_STATUS="$(mwan3 status)"
+
+ # get last 50 mwan3 systemlog messages
+ local MWAN3_LOG="$(echo -e "Last 50 MWAN3 systemlog entries. Newest entries sorted at the top:\n$(logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x')")"
+
+ # pass event info to send_alert function
+ send_alert "$(echo -e "$EVENT_INFO\n\n$CURRENT_STATUS\n\n$MWAN3_LOG")"
+}
+
+#case "$ACTION" in
+# ifup)
+# gather_event_info
+# ;;
+#
+# ifdown)
+# gather_event_info
+# ;;
+#esac
+
+exit 0
diff --git a/net/mwan3-luci/files/etc/uci-defaults/mwan3 b/net/mwan3-luci/files/etc/uci-defaults/mwan3
new file mode 100755
index 000000000..a19d4cb25
--- /dev/null
+++ b/net/mwan3-luci/files/etc/uci-defaults/mwan3
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# delete existing mwan3 ucitrack entry and add new entry
+uci -q batch <<-EOF >/dev/null
+ del ucitrack.@mwan3[-1]
+ add ucitrack mwan3
+ set ucitrack.@mwan3[-1].exec="/etc/init.d/mwan3 restart"
+ commit ucitrack
+EOF
+
+# make controller file addition take effect without system restart
+rm -rf /tmp/luci-indexcache /tmp/luci-modulecache
+
+exit 0
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/controller/mwan3.lua b/net/mwan3-luci/files/usr/lib/lua/luci/controller/mwan3.lua
new file mode 100644
index 000000000..13ff0902e
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/controller/mwan3.lua
@@ -0,0 +1,355 @@
+module("luci.controller.mwan3", package.seeall)
+
+sys = require "luci.sys"
+ut = require "luci.util"
+
+function index()
+ if not nixio.fs.access("/etc/config/mwan3") then
+ return
+ end
+
+ entry({"admin", "network", "mwan3"},
+ alias("admin", "network", "mwan3", "overview"),
+ _("Load Balancing"), 600)
+
+ entry({"admin", "network", "mwan3", "overview"},
+ alias("admin", "network", "mwan3", "overview", "over_iface"),
+ _("Overview"), 10)
+ entry({"admin", "network", "mwan3", "overview", "over_iface"},
+ template("mwan3/mwan3_over_interface"))
+ entry({"admin", "network", "mwan3", "overview", "iface_status"},
+ call("mwan3_iface_status"))
+ entry({"admin", "network", "mwan3", "overview", "over_detail"},
+ template("mwan3/mwan3_over_detail"))
+ entry({"admin", "network", "mwan3", "overview", "detail_status"},
+ call("mwan3_detail_status"))
+
+ entry({"admin", "network", "mwan3", "configuration"},
+ alias("admin", "network", "mwan3", "configuration", "interface"),
+ _("Configuration"), 20)
+ entry({"admin", "network", "mwan3", "configuration", "interface"},
+ arcombine(cbi("mwan3/mwan3_interface"), cbi("mwan3/mwan3_interfaceconfig")),
+ _("Interfaces"), 10).leaf = true
+ entry({"admin", "network", "mwan3", "configuration", "member"},
+ arcombine(cbi("mwan3/mwan3_member"), cbi("mwan3/mwan3_memberconfig")),
+ _("Members"), 20).leaf = true
+ entry({"admin", "network", "mwan3", "configuration", "policy"},
+ arcombine(cbi("mwan3/mwan3_policy"), cbi("mwan3/mwan3_policyconfig")),
+ _("Policies"), 30).leaf = true
+ entry({"admin", "network", "mwan3", "configuration", "rule"},
+ arcombine(cbi("mwan3/mwan3_rule"), cbi("mwan3/mwan3_ruleconfig")),
+ _("Rules"), 40).leaf = true
+
+ entry({"admin", "network", "mwan3", "advanced"},
+ alias("admin", "network", "mwan3", "advanced", "hotplug"),
+ _("Advanced"), 100)
+ entry({"admin", "network", "mwan3", "advanced", "hotplug"},
+ form("mwan3/mwan3_adv_hotplug"))
+ entry({"admin", "network", "mwan3", "advanced", "mwan3"},
+ form("mwan3/mwan3_adv_mwan3"))
+ entry({"admin", "network", "mwan3", "advanced", "network"},
+ form("mwan3/mwan3_adv_network"))
+ entry({"admin", "network", "mwan3", "advanced", "diag"},
+ template("mwan3/mwan3_adv_diagnostics"))
+ entry({"admin", "network", "mwan3", "advanced", "diag_display"},
+ call("mwan3_diag_data"), nil).leaf = true
+ entry({"admin", "network", "mwan3", "advanced", "tshoot"},
+ template("mwan3/mwan3_adv_troubleshoot"))
+ entry({"admin", "network", "mwan3", "advanced", "tshoot_display"},
+ call("mwan3_tshoot_data"))
+end
+
+function mwan3_get_iface_status(rulenum, ifname)
+ if ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".enabled")) == "1" then
+ if ut.trim(sys.exec("ip route list table " .. rulenum)) ~= "" then
+ if ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".track_ip")) ~= "" then
+ return "on"
+ else
+ return "nm"
+ end
+ else
+ return "off"
+ end
+ else
+ return "ne"
+ end
+end
+
+function mwan3_get_iface()
+ local rulenum, str = 0, ""
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ rulenum = rulenum+1
+ str = str .. section[".name"] .. "[" .. mwan3_get_iface_status(rulenum, section[".name"]) .. "]"
+ end
+ )
+ return str
+end
+
+function mwan3_iface_status()
+ local ntm = require "luci.model.network".init()
+
+ local rv = { }
+
+ -- overview status
+ local statstr = mwan3_get_iface()
+ if statstr ~= "" then
+ rv.wans = { }
+ wansid = {}
+
+ for wanname, ifstat in string.gfind(statstr, "([^%[]+)%[([^%]]+)%]") do
+ local wanifname = ut.trim(sys.exec("uci get -p /var/state network." .. wanname .. ".ifname"))
+ if wanifname == "" then
+ wanifname = "X"
+ end
+ local wanlink = ntm:get_interface(wanifname)
+ wanlink = wanlink and wanlink:get_network()
+ wanlink = wanlink and wanlink:adminlink() or "#"
+ wansid[wanname] = #rv.wans + 1
+ rv.wans[wansid[wanname]] = { name = wanname, link = wanlink, ifname = wanifname, status = ifstat }
+ end
+ end
+
+ -- overview status log
+ local mwlg = ut.trim(sys.exec("logread | grep mwan3 | tail -n 50 | sed 'x;1!H;$!d;x'"))
+ if mwlg ~= "" then
+ rv.mwan3log = { }
+ mwlog = {}
+ mwlog[mwlg] = #rv.mwan3log + 1
+ rv.mwan3log[mwlog[mwlg]] = { mwanlog = mwlg }
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+end
+
+function mwan3_detail_status()
+ local rv = { }
+
+ -- detailed mwan3 status
+ local dst = ut.trim(sys.exec("mwan3 status"))
+ if dst ~= "" then
+ rv.mwan3dst = { }
+ dstat = {}
+ dstat[dst] = #rv.mwan3dst + 1
+ rv.mwan3dst[dstat[dst]] = { detailstat = dst }
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+end
+
+function mwan3_diag_data(iface, tool, alt)
+ function get_ifnum()
+ local num = 0
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ num = num+1
+ if section[".name"] == iface then
+ ifnum = num
+ end
+ end
+ )
+ end
+
+ local rv = { }
+
+ local res = ""
+ if tool == "service" then
+ os.execute("mwan3 " .. alt)
+ if alt == "restart" then
+ res = "MWAN3 restarted"
+ elseif alt == "stop" then
+ res = "MWAN3 stopped"
+ else
+ res = "MWAN3 started"
+ end
+ else
+ local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. iface .. ".ifname"))
+ if ifdev ~= "" then
+ if tool == "ping" then
+ local gateway = ut.trim(sys.exec("route -n | awk -F' ' '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\") print $2 }'"))
+ if gateway ~= "" then
+ if alt == "gateway" then
+ local cmd = "ping -c 3 -W 2 -I " .. ifdev .. " " .. gateway
+ res = cmd .. "\n\n" .. sys.exec(cmd)
+ else
+ local str = ut.trim(sys.exec("uci get -p /var/state mwan3." .. iface .. ".track_ip"))
+ if str ~= "" then
+ for z in str:gmatch("[^ ]+") do
+ local cmd = "ping -c 3 -W 2 -I " .. ifdev .. " " .. z
+ res = res .. cmd .. "\n\n" .. sys.exec(cmd) .. "\n\n"
+ end
+ else
+ res = "No tracking IP addresses configured on " .. iface
+ end
+ end
+ else
+ res = "No default gateway for " .. iface .. " found. Default route does not exist or is configured incorrectly"
+ end
+ elseif tool == "rulechk" then
+ get_ifnum()
+ local rule1 = sys.exec("ip rule | grep $(echo $((" .. ifnum .. " + 1000)))")
+ local rule2 = sys.exec("ip rule | grep $(echo $((" .. ifnum .. " + 2000)))")
+ if rule1 ~= "" and rule2 ~= "" then
+ res = "All required interface IP rules found:\n\n" .. rule1 .. rule2
+ elseif rule1 ~= "" or rule2 ~= "" then
+ res = "Missing 1 of the 2 required interface IP rules\n\n\nRules found:\n\n" .. rule1 .. rule2
+ else
+ res = "Missing both of the required interface IP rules"
+ end
+ elseif tool == "routechk" then
+ get_ifnum()
+ local table = sys.exec("ip route list table " .. ifnum)
+ if table ~= "" then
+ res = "Interface routing table " .. ifnum .. " was found:\n\n" .. table
+ else
+ res = "Missing required interface routing table " .. ifnum
+ end
+ elseif tool == "hotplug" then
+ if alt == "ifup" then
+ os.execute("mwan3 ifup " .. iface)
+ res = "Hotplug ifup sent to interface " .. iface .. "..."
+ else
+ os.execute("mwan3 ifdown " .. iface)
+ res = "Hotplug ifdown sent to interface " .. iface .. "..."
+ end
+ end
+ else
+ res = "Unable to perform diagnostic tests on " .. iface .. ". There is no physical or virtual device associated with this interface"
+ end
+ end
+ if res ~= "" then
+ res = ut.trim(res)
+ rv.diagres = { }
+ dres = {}
+ dres[res] = #rv.diagres + 1
+ rv.diagres[dres[res]] = { diagresult = res }
+ end
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+end
+
+function mwan3_tshoot_data()
+ local rv = { }
+
+ -- software versions
+ local wrtrelease = ut.trim(luci.version.distversion)
+ if wrtrelease ~= "" then
+ wrtrelease = "OpenWrt - " .. wrtrelease
+ else
+ wrtrelease = "OpenWrt - unknown"
+ end
+ local lucirelease = ut.trim(luci.version.luciversion)
+ if lucirelease ~= "" then
+ lucirelease = "\nLuCI - " .. lucirelease
+ else
+ lucirelease = "\nLuCI - unknown"
+ end
+ local mwan3version = ut.trim(sys.exec("opkg info mwan3 | grep Version | awk -F' ' '{ print $2 }'"))
+ if mwan3version ~= "" then
+ mwan3version = "\n\nmwan3 - " .. mwan3version
+ else
+ mwan3version = "\nmwan3 - unknown"
+ end
+ local mwan3lversion = ut.trim(sys.exec("opkg info luci-app-mwan3 | grep Version | awk -F' ' '{ print $2 }'"))
+ if mwan3lversion ~= "" then
+ mwan3lversion = "\nluci-app-mwan3 - " .. mwan3lversion
+ else
+ mwan3lversion = "\nluci-app-mwan3 - unknown"
+ end
+ local softrev = wrtrelease .. lucirelease .. mwan3version .. mwan3lversion
+ rv.mw3ver = { }
+ mwv = {}
+ mwv[softrev] = #rv.mw3ver + 1
+ rv.mw3ver[mwv[softrev]] = { mwan3v = softrev }
+
+ -- mwan3 config
+ local mwcg = ut.trim(sys.exec("cat /etc/config/mwan3"))
+ if mwcg == "" then
+ mwcg = "No data found"
+ end
+ rv.mwan3config = { }
+ mwan3cfg = {}
+ mwan3cfg[mwcg] = #rv.mwan3config + 1
+ rv.mwan3config[mwan3cfg[mwcg]] = { mwn3cfg = mwcg }
+
+ -- network config
+ local netcg = ut.trim(sys.exec("cat /etc/config/network | sed -e 's/.*username.*/ USERNAME HIDDEN/' -e 's/.*password.*/ PASSWORD HIDDEN/'"))
+ if netcg == "" then
+ netcg = "No data found"
+ end
+ rv.netconfig = { }
+ ncfg = {}
+ ncfg[netcg] = #rv.netconfig + 1
+ rv.netconfig[ncfg[netcg]] = { netcfg = netcg }
+
+ -- ifconfig
+ local ifcg = ut.trim(sys.exec("ifconfig"))
+ if ifcg == "" then
+ ifcg = "No data found"
+ end
+ rv.ifconfig = { }
+ icfg = {}
+ icfg[ifcg] = #rv.ifconfig + 1
+ rv.ifconfig[icfg[ifcg]] = { ifcfg = ifcg }
+
+ -- route -n
+ local routeshow = ut.trim(sys.exec("route -n"))
+ if routeshow == "" then
+ routeshow = "No data found"
+ end
+ rv.rtshow = { }
+ rshw = {}
+ rshw[routeshow] = #rv.rtshow + 1
+ rv.rtshow[rshw[routeshow]] = { iprtshow = routeshow }
+
+ -- ip rule show
+ local ipr = ut.trim(sys.exec("ip rule show"))
+ if ipr == "" then
+ ipr = "No data found"
+ end
+ rv.iprule = { }
+ ipruleid = {}
+ ipruleid[ipr] = #rv.iprule + 1
+ rv.iprule[ipruleid[ipr]] = { rule = ipr }
+
+ -- ip route list table 1-250
+ local routelisting, rlstr = ut.trim(sys.exec("ip rule | sed 's/://g' | awk -F' ' '$1>=2001 && $1<=2250' | awk -F' ' '{ print $NF }'")), ""
+ if routelisting ~= "" then
+ for line in routelisting:gmatch("[^\r\n]+") do
+ rlstr = rlstr .. line .. "\n" .. sys.exec("ip route list table " .. line)
+ end
+ rlstr = ut.trim(rlstr)
+ else
+ rlstr = "No data found"
+ end
+ rv.routelist = { }
+ rtlist = {}
+ rtlist[rlstr] = #rv.routelist + 1
+ rv.routelist[rtlist[rlstr]] = { iprtlist = rlstr }
+
+ -- default firewall output policy
+ local defout = ut.trim(sys.exec("uci get -p /var/state firewall.@defaults[0].output"))
+ if defout == "" then
+ defout = "No data found"
+ end
+ rv.fidef = { }
+ fwdf = {}
+ fwdf[defout] = #rv.fidef + 1
+ rv.fidef[fwdf[defout]] = { firedef = defout }
+
+ -- iptables
+ local iptbl = ut.trim(sys.exec("iptables -L -t mangle -v -n"))
+ if iptbl == "" then
+ iptbl = "No data found"
+ end
+ rv.iptables = { }
+ tables = {}
+ tables[iptbl] = #rv.iptables + 1
+ rv.iptables[tables[iptbl]] = { iptbls = iptbl }
+
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(rv)
+end
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_hotplug.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_hotplug.lua
new file mode 100644
index 000000000..93e125cf3
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_hotplug.lua
@@ -0,0 +1,55 @@
+-- ------ hotplug script configuration ------ --
+
+fs = require "nixio.fs"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+script = "/etc/hotplug.d/iface/16-mwan3custom"
+scriptbak = "/etc/hotplug.d/iface/16-mwan3custombak"
+
+if luci.http.formvalue("cbid.luci.1._restorebak") then -- restore button has been clicked
+ luci.http.redirect(luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug") .. "?restore=yes")
+elseif luci.http.formvalue("restore") == "yes" then -- restore script from backup
+ os.execute("cp -f " .. scriptbak .. " " .. script)
+end
+
+
+m5 = SimpleForm("luci", nil)
+ m5:append(Template("mwan3/mwan3_adv_hotplug")) -- highlight current tab
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/hotplug.d/iface/16-mwan3custom<br />" ..
+ "This is useful for running system commands and/or scripts based on interface ifup or ifdown hotplug events<br /><br />" ..
+ "Notes:<br />" ..
+ "The first line of the script must be &#34;#!/bin/sh&#34; without quotes<br />" ..
+ "Lines beginning with # are comments and are not executed<br /><br />" ..
+ "Available variables:<br />" ..
+ "$ACTION is the hotplug event (ifup, ifdown)<br />" ..
+ "$INTERFACE is the interface name (wan1, wan2, etc.)<br />" ..
+ "$DEVICE is the device name attached to the interface (eth0.1, eth1, etc.)"))
+
+
+restore = f:option(Button, "_restorebak", translate("Restore default hotplug script"))
+ restore.inputtitle = translate("Restore...")
+ restore.inputstyle = "apply"
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ local hps = fs.readfile(script)
+ if not hps or hps == "" then -- if script does not exist or is blank restore from backup
+ sys.call("cp -f " .. scriptbak .. " " .. script)
+ return fs.readfile(script)
+ else
+ return hps
+ end
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return fs.writefile(script, ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_mwan3.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_mwan3.lua
new file mode 100644
index 000000000..9eb0df52c
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_mwan3.lua
@@ -0,0 +1,32 @@
+-- ------ mwan3 configuration ------ --
+
+ut = require "luci.util"
+
+mwan3file = "/etc/config/mwan3"
+
+
+m5 = SimpleForm("luci", nil)
+ m5:append(Template("mwan3/mwan3_adv_mwan3")) -- highlight current tab
+
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/config/mwan3"))
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ return nixio.fs.readfile(mwan3file) or ""
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return nixio.fs.writefile(mwan3file, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function f.handle(self, state, data)
+ return true
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_network.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_network.lua
new file mode 100644
index 000000000..fee6a07d2
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_adv_network.lua
@@ -0,0 +1,32 @@
+-- ------ network configuration ------ --
+
+ut = require "luci.util"
+
+netfile = "/etc/config/network"
+
+
+m5 = SimpleForm("networkconf", nil)
+ m5:append(Template("mwan3/mwan3_adv_network")) -- highlight current tab
+
+
+f = m5:section(SimpleSection, nil,
+ translate("This section allows you to modify the contents of /etc/config/network"))
+
+t = f:option(TextValue, "lines")
+ t.rmempty = true
+ t.rows = 20
+
+ function t.cfgvalue()
+ return nixio.fs.readfile(netfile) or ""
+ end
+
+ function t.write(self, section, data) -- format and write new data to script
+ return nixio.fs.writefile(netfile, "\n" .. ut.trim(data:gsub("\r\n", "\n")) .. "\n")
+ end
+
+ function f.handle(self, state, data)
+ return true
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interface.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interface.lua
new file mode 100644
index 000000000..3d504a24f
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interface.lua
@@ -0,0 +1,266 @@
+-- ------ extra functions ------ --
+
+function iface_check() -- find issues with too many interfaces, reliability and metric
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ local ifname = section[".name"]
+ ifnum = ifnum+1 -- count number of mwan3 interfaces configured
+ -- create list of metrics for none and duplicate checking
+ local metlkp = ut.trim(sys.exec("uci get -p /var/state network." .. ifname .. ".metric"))
+ if metlkp == "" then
+ err_found = 1
+ err_nomet_list = err_nomet_list .. ifname .. " "
+ else
+ metric_list = metric_list .. ifname .. " " .. metlkp .. "\n"
+ end
+ -- check if any interfaces have a higher reliability requirement than tracking IPs configured
+ local tipnum = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. ifname .. ".track_ip) | wc -w")))
+ if tipnum > 0 then
+ local relnum = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. ifname .. ".reliability")))
+ if relnum and relnum > tipnum then
+ err_found = 1
+ err_rel_list = err_rel_list .. ifname .. " "
+ end
+ end
+ -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
+ if ut.trim(sys.exec("uci get -p /var/state network." .. ifname)) == "interface" then
+ local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. ifname .. ".ifname"))
+ if ifdev == "uci: Entry not found" or ifdev == "" then
+ err_found = 1
+ err_netcfg_list = err_netcfg_list .. ifname .. " "
+ err_route_list = err_route_list .. ifname .. " "
+ else
+ local rtcheck = ut.trim(sys.exec("route -n | awk -F' ' '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\") print $1 }'"))
+ if rtcheck == "" then
+ err_found = 1
+ err_route_list = err_route_list .. ifname .. " "
+ end
+ end
+ else
+ err_found = 1
+ err_netcfg_list = err_netcfg_list .. ifname .. " "
+ err_route_list = err_route_list .. ifname .. " "
+ end
+ end
+ )
+ -- check if any interfaces have duplicate metrics
+ local metric_dupnums = sys.exec("echo '" .. metric_list .. "' | awk -F' ' '{ print $2 }' | uniq -d")
+ if metric_dupnums ~= "" then
+ err_found = 1
+ local metric_dupes = ""
+ for line in metric_dupnums:gmatch("[^\r\n]+") do
+ metric_dupes = sys.exec("echo '" .. metric_list .. "' | grep '" .. line .. "' | awk -F' ' '{ print $1 }'")
+ err_dupmet_list = err_dupmet_list .. metric_dupes
+ end
+ err_dupmet_list = sys.exec("echo '" .. err_dupmet_list .. "' | tr '\n' ' '")
+ end
+end
+
+function iface_warn() -- display status and warning messages at the top of the page
+ local warns = ""
+ if ifnum <= 250 then
+ warns = "<strong>There are currently " .. ifnum .. " of 250 supported interfaces configured</strong>"
+ else
+ warns = "<font color=\"ff0000\"><strong>WARNING: " .. ifnum .. " interfaces are configured exceeding the maximum of 250!</strong></font>"
+ end
+ if err_rel_list ~= " " then
+ warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have a higher reliability requirement than there are tracking IP addresses!</strong></font>"
+ end
+ if err_route_list ~= " " then
+ warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no default route in the main routing table!</strong></font>"
+ end
+ if err_netcfg_list ~= " " then
+ warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces are configured incorrectly or not at all in /etc/config/network!</strong></font>"
+ end
+ if err_nomet_list ~= " " then
+ warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have no metric configured in /etc/config/network!</strong></font>"
+ end
+ if err_dupmet_list ~= " " then
+ warns = warns .. "<br /><br /><font color=\"ff0000\"><strong>WARNING: some interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
+ end
+ return warns
+end
+
+-- ------ interface configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+ifnum = 0
+metric_list = ""
+err_found = 0
+err_dupmet_list = " "
+err_netcfg_list = " "
+err_nomet_list = " "
+err_rel_list = " "
+err_route_list = " "
+iface_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Interface Configuration"),
+ translate(iface_warn()))
+ m5:append(Template("mwan3/mwan3_config_css"))
+
+
+mwan_interface = m5:section(TypedSection, "interface", translate("Interfaces"),
+ translate("MWAN3 supports up to 250 physical and/or logical interfaces<br />" ..
+ "MWAN3 requires that all interfaces have a unique metric configured in /etc/config/network<br />" ..
+ "Names must match the interface name found in /etc/config/network (see advanced tab)<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Interfaces may not share the same name as configured members, policies or rules"))
+ mwan_interface.addremove = true
+ mwan_interface.dynamic = false
+ mwan_interface.sectionhead = "Interface"
+ mwan_interface.sortable = true
+ mwan_interface.template = "cbi/tblsection"
+ mwan_interface.extedit = dsp.build_url("admin", "network", "mwan3", "configuration", "interface", "%s")
+ function mwan_interface.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(dsp.build_url("admin", "network", "mwan3", "configuration", "interface", section))
+ end
+
+
+enabled = mwan_interface:option(DummyValue, "enabled", translate("Enabled"))
+ enabled.rawhtml = true
+ function enabled.cfgvalue(self, s)
+ if self.map:get(s, "enabled") == "1" then
+ return "Yes"
+ else
+ return "No"
+ end
+ end
+
+track_ip = mwan_interface:option(DummyValue, "track_ip", translate("Tracking IP"))
+ track_ip.rawhtml = true
+ function track_ip.cfgvalue(self, s)
+ local str = ""
+ tracked = self.map:get(s, "track_ip")
+ if tracked then
+ for k,v in pairs(tracked) do
+ str = str .. v .. "<br />"
+ end
+ return str
+ else
+ return "&#8212;"
+ end
+ end
+
+reliability = mwan_interface:option(DummyValue, "reliability", translate("Tracking reliability"))
+ reliability.rawhtml = true
+ function reliability.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "reliability") or "&#8212;"
+ else
+ return "&#8212;"
+ end
+ end
+
+count = mwan_interface:option(DummyValue, "count", translate("Ping count"))
+ count.rawhtml = true
+ function count.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "count") or "&#8212;"
+ else
+ return "&#8212;"
+ end
+ end
+
+timeout = mwan_interface:option(DummyValue, "timeout", translate("Ping timeout"))
+ timeout.rawhtml = true
+ function timeout.cfgvalue(self, s)
+ if tracked then
+ local tcheck = self.map:get(s, "timeout")
+ if tcheck then
+ return tcheck .. "s"
+ else
+ return "&#8212;"
+ end
+ else
+ return "&#8212;"
+ end
+ end
+
+interval = mwan_interface:option(DummyValue, "interval", translate("Ping interval"))
+ interval.rawhtml = true
+ function interval.cfgvalue(self, s)
+ if tracked then
+ local icheck = self.map:get(s, "interval")
+ if icheck then
+ return icheck .. "s"
+ else
+ return "&#8212;"
+ end
+ else
+ return "&#8212;"
+ end
+ end
+
+down = mwan_interface:option(DummyValue, "down", translate("Interface down"))
+ down.rawhtml = true
+ function down.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "down") or "&#8212;"
+ else
+ return "&#8212;"
+ end
+ end
+
+up = mwan_interface:option(DummyValue, "up", translate("Interface up"))
+ up.rawhtml = true
+ function up.cfgvalue(self, s)
+ if tracked then
+ return self.map:get(s, "up") or "&#8212;"
+ else
+ return "&#8212;"
+ end
+ end
+
+metric = mwan_interface:option(DummyValue, "metric", translate("Metric"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ local metcheck = sys.exec("uci get -p /var/state network." .. s .. ".metric")
+ if metcheck ~= "" then
+ return metcheck
+ else
+ return "&#8212;"
+ end
+ end
+
+errors = mwan_interface:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if err_found == 1 then
+ local mouseover, linebrk = "", ""
+ if string.find(err_rel_list, " " .. s .. " ") then
+ mouseover = "Higher reliability requirement than there are tracking IP addresses"
+ linebrk = "&#10;&#10;"
+ end
+ if string.find(err_route_list, " " .. s .. " ") then
+ mouseover = mouseover .. linebrk .. "No default route in the main routing table"
+ linebrk = "&#10;&#10;"
+ end
+ if string.find(err_netcfg_list, " " .. s .. " ") then
+ mouseover = mouseover .. linebrk .. "Configured incorrectly or not at all in /etc/config/network"
+ linebrk = "&#10;&#10;"
+ end
+ if string.find(err_nomet_list, " " .. s .. " ") then
+ mouseover = mouseover .. linebrk .. "No metric configured in /etc/config/network"
+ linebrk = "&#10;&#10;"
+ end
+ if string.find(err_dupmet_list, " " .. s .. " ") then
+ mouseover = mouseover .. linebrk .. "Duplicate metric configured in /etc/config/network"
+ end
+ if mouseover == "" then
+ return ""
+ else
+ return "<span title=\"" .. mouseover .. "\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ else
+ return ""
+ end
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interfaceconfig.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interfaceconfig.lua
new file mode 100644
index 000000000..2119c048b
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_interfaceconfig.lua
@@ -0,0 +1,191 @@
+-- ------ extra functions ------ --
+
+function iface_check()
+ metcheck = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".metric"))
+ if metcheck == "" then -- no metric
+ err_nomet = 1
+ else -- if metric exists create list of interface metrics to compare against for duplicates
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ local metlkp = ut.trim(sys.exec("uci get -p /var/state network." .. section[".name"] .. ".metric"))
+ metric_list = metric_list .. section[".name"] .. " " .. metlkp .. "\n"
+ end
+ )
+ -- compare metric against list
+ local metric_dupnums, metric_dupes = sys.exec("echo '" .. metric_list .. "' | awk -F' ' '{ print $2 }' | uniq -d"), ""
+ for line in metric_dupnums:gmatch("[^\r\n]+") do
+ metric_dupes = sys.exec("echo '" .. metric_list .. "' | grep '" .. line .. "' | awk -F' ' '{ print $1 }'")
+ err_dupmet_list = err_dupmet_list .. metric_dupes
+ end
+ if sys.exec("echo '" .. err_dupmet_list .. "' | grep -w " .. arg[1]) ~= "" then
+ err_dupmet = 1
+ end
+ end
+ -- check if this interface has a higher reliability requirement than track IPs configured
+ local tipnum = tonumber(ut.trim(sys.exec("echo $(uci get -p /var/state mwan3." .. arg[1] .. ".track_ip) | wc -w")))
+ if tipnum > 0 then
+ local relnum = tonumber(ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".reliability")))
+ if relnum and relnum > tipnum then
+ err_reliability = 1
+ end
+ end
+ -- check if any interfaces are not properly configured in /etc/config/network or have no default route in main routing table
+ if ut.trim(sys.exec("uci get -p /var/state network." .. arg[1])) == "interface" then
+ local ifdev = ut.trim(sys.exec("uci get -p /var/state network." .. arg[1] .. ".ifname"))
+ if ifdev == "uci: Entry not found" or ifdev == "" then
+ err_netcfg = 1
+ err_route = 1
+ else
+ local rtcheck = ut.trim(sys.exec("route -n | awk -F' ' '{ if ($8 == \"" .. ifdev .. "\" && $1 == \"0.0.0.0\") print $1 }'"))
+ if rtcheck == "" then
+ err_route = 1
+ end
+ end
+ else
+ err_netcfg = 1
+ err_route = 1
+ end
+end
+
+function iface_warn() -- display warning messages at the top of the page
+ local warns, linebrk = "", ""
+ if err_reliability == 1 then
+ warns = "<font color=\"ff0000\"><strong>WARNING: this interface has a higher reliability requirement than there are tracking IP addresses!</strong></font>"
+ linebrk = "<br /><br />"
+ end
+ if err_route == 1 then
+ warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface has no default route in the main routing table!</strong></font>"
+ linebrk = "<br /><br />"
+ end
+ if err_netcfg == 1 then
+ warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface is configured incorrectly or not at all in /etc/config/network!</strong></font>"
+ linebrk = "<br /><br />"
+ end
+ if err_nomet == 1 then
+ warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this interface has no metric configured in /etc/config/network!</strong></font>"
+ elseif err_dupmet == 1 then
+ warns = warns .. linebrk .. "<font color=\"ff0000\"><strong>WARNING: this and other interfaces have duplicate metrics configured in /etc/config/network!</strong></font>"
+ end
+ return warns
+end
+
+-- ------ interface configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+arg[1] = arg[1] or ""
+
+metcheck = ""
+metric_list = ""
+err_dupmet_list = ""
+err_rel_list = ""
+err_nomet = 0
+err_dupmet = 0
+err_route = 0
+err_netcfg = 0
+err_reliability = 0
+iface_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Interface Configuration - " .. arg[1]),
+ translate(iface_warn()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "interface")
+
+
+mwan_interface = m5:section(NamedSection, arg[1], "interface", "")
+ mwan_interface.addremove = false
+ mwan_interface.dynamic = false
+
+
+enabled = mwan_interface:option(ListValue, "enabled", translate("Enabled"))
+ enabled.default = "1"
+ enabled:value("1", translate("Yes"))
+ enabled:value("0", translate("No"))
+
+track_ip = mwan_interface:option(DynamicList, "track_ip", translate("Tracking IP"),
+ translate("This IP address will be pinged to dermine if the link is up or down. Leave blank to assume interface is always online"))
+ track_ip.datatype = "ipaddr"
+
+reliability = mwan_interface:option(Value, "reliability", translate("Tracking reliability"),
+ translate("Acceptable values: 1-100. This many Tracking IP addresses must respond for the link to be deemed up"))
+ reliability.datatype = "range(1, 100)"
+ reliability.default = "1"
+
+count = mwan_interface:option(ListValue, "count", translate("Ping count"))
+ count.default = "1"
+ count:value("1")
+ count:value("2")
+ count:value("3")
+ count:value("4")
+ count:value("5")
+
+timeout = mwan_interface:option(ListValue, "timeout", translate("Ping timeout"))
+ timeout.default = "2"
+ timeout:value("1", translate("1 second"))
+ timeout:value("2", translate("2 seconds"))
+ timeout:value("3", translate("3 seconds"))
+ timeout:value("4", translate("4 seconds"))
+ timeout:value("5", translate("5 seconds"))
+ timeout:value("6", translate("6 seconds"))
+ timeout:value("7", translate("7 seconds"))
+ timeout:value("8", translate("8 seconds"))
+ timeout:value("9", translate("9 seconds"))
+ timeout:value("10", translate("10 seconds"))
+
+interval = mwan_interface:option(ListValue, "interval", translate("Ping interval"))
+ interval.default = "5"
+ interval:value("1", translate("1 second"))
+ interval:value("3", translate("3 seconds"))
+ interval:value("5", translate("5 seconds"))
+ interval:value("10", translate("10 seconds"))
+ interval:value("20", translate("20 seconds"))
+ interval:value("30", translate("30 seconds"))
+ interval:value("60", translate("1 minute"))
+ interval:value("300", translate("5 minutes"))
+ interval:value("600", translate("10 minutes"))
+ interval:value("900", translate("15 minutes"))
+ interval:value("1800", translate("30 minutes"))
+ interval:value("3600", translate("1 hour"))
+
+down = mwan_interface:option(ListValue, "down", translate("Interface down"),
+ translate("Interface will be deemed down after this many failed ping tests"))
+ down.default = "3"
+ down:value("1")
+ down:value("2")
+ down:value("3")
+ down:value("4")
+ down:value("5")
+ down:value("6")
+ down:value("7")
+ down:value("8")
+ down:value("9")
+ down:value("10")
+
+up = mwan_interface:option(ListValue, "up", translate("Interface up"),
+ translate("Downed interface will be deemed up after this many successful ping tests"))
+ up.default = "3"
+ up:value("1")
+ up:value("2")
+ up:value("3")
+ up:value("4")
+ up:value("5")
+ up:value("6")
+ up:value("7")
+ up:value("8")
+ up:value("9")
+ up:value("10")
+
+metric = mwan_interface:option(DummyValue, "metric", translate("Metric"),
+ translate("This displays the metric assigned to this interface in /etc/config/network"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ if err_nomet == 0 then
+ return metcheck
+ else
+ return "&#8212;"
+ end
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_member.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_member.lua
new file mode 100644
index 000000000..68b9549e1
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_member.lua
@@ -0,0 +1,46 @@
+-- ------ member configuration ------ --
+
+ds = require "luci.dispatcher"
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Member Configuration"))
+ m5:append(Template("mwan3/mwan3_config_css"))
+
+
+mwan_member = m5:section(TypedSection, "member", translate("Members"),
+ translate("Members are profiles attaching a metric and weight to an MWAN3 interface<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Members may not share the same name as configured interfaces, policies or rules"))
+ mwan_member.addremove = true
+ mwan_member.dynamic = false
+ mwan_member.sectionhead = "Member"
+ mwan_member.sortable = true
+ mwan_member.template = "cbi/tblsection"
+ mwan_member.extedit = ds.build_url("admin", "network", "mwan3", "configuration", "member", "%s")
+ function mwan_member.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(ds.build_url("admin", "network", "mwan3", "configuration", "member", section))
+ end
+
+
+interface = mwan_member:option(DummyValue, "interface", translate("Interface"))
+ interface.rawhtml = true
+ function interface.cfgvalue(self, s)
+ return self.map:get(s, "interface") or "&#8212;"
+ end
+
+metric = mwan_member:option(DummyValue, "metric", translate("Metric"))
+ metric.rawhtml = true
+ function metric.cfgvalue(self, s)
+ return self.map:get(s, "metric") or "1"
+ end
+
+weight = mwan_member:option(DummyValue, "weight", translate("Weight"))
+ weight.rawhtml = true
+ function weight.cfgvalue(self, s)
+ return self.map:get(s, "weight") or "1"
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_memberconfig.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_memberconfig.lua
new file mode 100644
index 000000000..8ea7d9824
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_memberconfig.lua
@@ -0,0 +1,47 @@
+-- ------ extra functions ------ --
+
+function cbi_add_interface(field)
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+-- ------ member configuration ------ --
+
+dsp = require "luci.dispatcher"
+arg[1] = arg[1] or ""
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Member Configuration - ") .. arg[1])
+ m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "member")
+
+
+mwan_member = m5:section(NamedSection, arg[1], "member", "")
+ mwan_member.addremove = false
+ mwan_member.dynamic = false
+
+
+interface = mwan_member:option(Value, "interface", translate("Interface"))
+ cbi_add_interface(interface)
+
+metric = mwan_member:option(Value, "metric", translate("Metric"),
+ translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
+ metric.datatype = "range(1, 1000)"
+
+weight = mwan_member:option(Value, "weight", translate("Weight"),
+ translate("Acceptable values: 1-1000. Defaults to 1 if not set"))
+ weight.datatype = "range(1, 1000)"
+
+
+-- ------ currently configured interfaces ------ --
+
+mwan_interface = m5:section(TypedSection, "interface", translate("Currently Configured Interfaces"))
+ mwan_interface.addremove = false
+ mwan_interface.dynamic = false
+ mwan_interface.sortable = false
+ mwan_interface.template = "cbi/tblsection"
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policy.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policy.lua
new file mode 100644
index 000000000..02471b992
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policy.lua
@@ -0,0 +1,82 @@
+-- ------ extra functions ------ --
+
+function policy_check() -- check to see if any policy names exceed the maximum of 15 characters
+ uci.cursor():foreach("mwan3", "policy",
+ function (section)
+ if string.len(section[".name"]) > 15 then
+ toolong = 1
+ err_name_list = err_name_list .. section[".name"] .. " "
+ end
+ end
+ )
+end
+
+function policy_warn() -- display status and warning messages at the top of the page
+ if toolong == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: Some policies have names exceeding the maximum of 15 characters!</strong></font>"
+ else
+ return ""
+ end
+end
+
+-- ------ policy configuration ------ --
+
+ds = require "luci.dispatcher"
+sys = require "luci.sys"
+
+toolong = 0
+err_name_list = " "
+policy_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Policy Configuration"),
+ translate(policy_warn()))
+ m5:append(Template("mwan3/mwan3_config_css"))
+
+
+mwan_policy = m5:section(TypedSection, "policy", translate("Policies"),
+ translate("Policies are profiles grouping one or more members controlling how MWAN3 distributes traffic<br />" ..
+ "Member interfaces with lower metrics are used first. Interfaces with the same metric load-balance<br />" ..
+ "Load-balanced member interfaces distribute more traffic out those with higher weights<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be 15 characters or less<br />" ..
+ "Policies may not share the same name as configured interfaces, members or rules"))
+ mwan_policy.addremove = true
+ mwan_policy.dynamic = false
+ mwan_policy.sectionhead = "Policy"
+ mwan_policy.sortable = true
+ mwan_policy.template = "cbi/tblsection"
+ mwan_policy.extedit = ds.build_url("admin", "network", "mwan3", "configuration", "policy", "%s")
+ function mwan_policy.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(ds.build_url("admin", "network", "mwan3", "configuration", "policy", section))
+ end
+
+
+use_member = mwan_policy:option(DummyValue, "use_member", translate("Members assigned"))
+ use_member.rawhtml = true
+ function use_member.cfgvalue(self, s)
+ local tab, str = self.map:get(s, "use_member"), ""
+ if tab then
+ for k,v in pairs(tab) do
+ str = str .. v .. "<br />"
+ end
+ return str
+ else
+ return "&#8212;"
+ end
+
+ end
+
+errors = mwan_policy:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if not string.find(err_name_list, " " .. s .. " ") then
+ return ""
+ else
+ return "<span title=\"Name exceeds 15 characters\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policyconfig.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policyconfig.lua
new file mode 100644
index 000000000..a6523ad8e
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_policyconfig.lua
@@ -0,0 +1,58 @@
+-- ------ extra functions ------ --
+
+function policy_check() -- check to see if this policy's name exceed the maximum of 15 characters
+ polchar = string.len(arg[1])
+ if polchar > 15 then
+ toolong = 1
+ end
+end
+
+function policy_warn() -- display status and warning messages at the top of the page
+ if toolong == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: this policy's name is " .. polchar .. " characters exceeding the maximum of 15!</strong></font>"
+ else
+ return ""
+ end
+end
+
+function cbi_add_member(field)
+ uci.cursor():foreach("mwan3", "member",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+-- ------ policy configuration ------ --
+
+dsp = require "luci.dispatcher"
+arg[1] = arg[1] or ""
+
+toolong = 0
+policy_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Policy Configuration - " .. arg[1]),
+ translate(policy_warn()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "policy")
+
+
+mwan_policy = m5:section(NamedSection, arg[1], "policy", "")
+ mwan_policy.addremove = false
+ mwan_policy.dynamic = false
+
+
+use_member = mwan_policy:option(DynamicList, "use_member", translate("Member used"))
+ cbi_add_member(use_member)
+
+
+-- ------ currently configured members ------ --
+
+mwan_member = m5:section(TypedSection, "member", translate("Currently Configured Members"))
+ mwan_member.addremove = false
+ mwan_member.dynamic = false
+ mwan_member.sortable = false
+ mwan_member.template = "cbi/tblsection"
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_rule.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_rule.lua
new file mode 100644
index 000000000..efae81b2a
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_rule.lua
@@ -0,0 +1,109 @@
+-- ------ extra functions ------ --
+
+function rule_check() -- determine if rules needs a proper protocol configured
+ uci.cursor():foreach("mwan3", "rule",
+ function (section)
+ local sport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".src_port"))
+ local dport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".dest_port"))
+ if sport ~= "" or dport ~= "" then -- ports configured
+ local proto = ut.trim(sys.exec("uci get -p /var/state mwan3." .. section[".name"] .. ".proto"))
+ if proto == "" or proto == "all" then -- no or improper protocol
+ err_proto_list = err_proto_list .. section[".name"] .. " "
+ end
+ end
+ end
+ )
+end
+
+function rule_warn() -- display warning messages at the top of the page
+ if err_proto_list ~= " " then
+ return "<font color=\"ff0000\"><strong>WARNING: some rules have a port configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
+ else
+ return ""
+ end
+end
+
+-- ------ rule configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+
+err_proto = 0
+err_proto_list = " "
+rule_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Traffic Rule Configuration"),
+ translate(rule_warn()))
+ m5:append(Template("mwan3/mwan3_config_css"))
+
+
+mwan_rule = m5:section(TypedSection, "rule", translate("Traffic Rules"),
+ translate("Rules specify which traffic will use a particular MWAN3 policy based on IP address, port or protocol<br />" ..
+ "Rules are matched from top to bottom. Rules below a matching rule are ignored. Traffic not matching any rule is routed using the main routing table<br />" ..
+ "Traffic destined for known (other than default) networks is handled by the main routing table. Traffic matching a rule, but all WAN interfaces for that policy are down will be blackholed<br />" ..
+ "Names may contain characters A-Z, a-z, 0-9, _ and no spaces<br />" ..
+ "Rules may not share the same name as configured interfaces, members or policies"))
+ mwan_rule.addremove = true
+ mwan_rule.anonymous = false
+ mwan_rule.dynamic = false
+ mwan_rule.sectionhead = "Rule"
+ mwan_rule.sortable = true
+ mwan_rule.template = "cbi/tblsection"
+ mwan_rule.extedit = dsp.build_url("admin", "network", "mwan3", "configuration", "rule", "%s")
+ function mwan_rule.create(self, section)
+ TypedSection.create(self, section)
+ m5.uci:save("mwan3")
+ luci.http.redirect(dsp.build_url("admin", "network", "mwan3", "configuration", "rule", section))
+ end
+
+
+src_ip = mwan_rule:option(DummyValue, "src_ip", translate("Source address"))
+ src_ip.rawhtml = true
+ function src_ip.cfgvalue(self, s)
+ return self.map:get(s, "src_ip") or "&#8212;"
+ end
+
+src_port = mwan_rule:option(DummyValue, "src_port", translate("Source port"))
+ src_port.rawhtml = true
+ function src_port.cfgvalue(self, s)
+ return self.map:get(s, "src_port") or "&#8212;"
+ end
+
+dest_ip = mwan_rule:option(DummyValue, "dest_ip", translate("Destination address"))
+ dest_ip.rawhtml = true
+ function dest_ip.cfgvalue(self, s)
+ return self.map:get(s, "dest_ip") or "&#8212;"
+ end
+
+dest_port = mwan_rule:option(DummyValue, "dest_port", translate("Destination port"))
+ dest_port.rawhtml = true
+ function dest_port.cfgvalue(self, s)
+ return self.map:get(s, "dest_port") or "&#8212;"
+ end
+
+proto = mwan_rule:option(DummyValue, "proto", translate("Protocol"))
+ proto.rawhtml = true
+ function proto.cfgvalue(self, s)
+ return self.map:get(s, "proto") or "all"
+ end
+
+use_policy = mwan_rule:option(DummyValue, "use_policy", translate("Policy assigned"))
+ use_policy.rawhtml = true
+ function use_policy.cfgvalue(self, s)
+ return self.map:get(s, "use_policy") or "&#8212;"
+ end
+
+errors = mwan_rule:option(DummyValue, "errors", translate("Errors"))
+ errors.rawhtml = true
+ function errors.cfgvalue(self, s)
+ if not string.find(err_proto_list, " " .. s .. " ") then
+ return ""
+ else
+ return "<span title=\"No protocol specified\"><img src=\"/luci-static/resources/cbi/reset.gif\" alt=\"error\"></img></span>"
+ end
+ end
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_ruleconfig.lua b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_ruleconfig.lua
new file mode 100644
index 000000000..e83fa629f
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/model/cbi/mwan3/mwan3_ruleconfig.lua
@@ -0,0 +1,99 @@
+-- ------ extra functions ------ --
+
+function rule_check() -- determine if rule needs a protocol specified
+ local sport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".src_port"))
+ local dport = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".dest_port"))
+ if sport ~= "" or dport ~= "" then -- ports configured
+ local proto = ut.trim(sys.exec("uci get -p /var/state mwan3." .. arg[1] .. ".proto"))
+ if proto == "" or proto == "all" then -- no or improper protocol
+ err_proto = 1
+ end
+ end
+end
+
+function rule_warn() -- display warning message at the top of the page
+ if err_proto == 1 then
+ return "<font color=\"ff0000\"><strong>WARNING: this rule is incorrectly configured with no or improper protocol specified! Please configure a specific protocol!</strong></font>"
+ else
+ return ""
+ end
+end
+
+function cbi_add_policy(field)
+ uci.cursor():foreach("mwan3", "policy",
+ function (section)
+ field:value(section[".name"])
+ end
+ )
+end
+
+function cbi_add_protocol(field)
+ local protos = ut.trim(sys.exec("cat /etc/protocols | grep ' # ' | awk -F' ' '{print $1}' | grep -vw -e 'ip' -e 'tcp' -e 'udp' -e 'icmp' -e 'esp' | grep -v 'ipv6' | sort | tr '\n' ' '"))
+ for p in string.gmatch(protos, "%S+") do
+ field:value(p)
+ end
+end
+
+-- ------ rule configuration ------ --
+
+dsp = require "luci.dispatcher"
+sys = require "luci.sys"
+ut = require "luci.util"
+arg[1] = arg[1] or ""
+
+err_proto = 0
+rule_check()
+
+
+m5 = Map("mwan3", translate("MWAN3 Multi-WAN Rule Configuration - ") .. arg[1],
+ translate(rule_warn()))
+ m5.redirect = dsp.build_url("admin", "network", "mwan3", "configuration", "rule")
+
+
+mwan_rule = m5:section(NamedSection, arg[1], "rule", "")
+ mwan_rule.addremove = false
+ mwan_rule.dynamic = false
+
+
+src_ip = mwan_rule:option(Value, "src_ip", translate("Source address"),
+ translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
+ src_ip.datatype = ipaddr
+
+src_port = mwan_rule:option(Value, "src_port", translate("Source port"),
+ translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
+
+dest_ip = mwan_rule:option(Value, "dest_ip", translate("Destination address"),
+ translate("Supports CIDR notation (eg \"192.168.100.0/24\") without quotes"))
+ dest_ip.datatype = ipaddr
+
+dest_port = mwan_rule:option(Value, "dest_port", translate("Destination port"),
+ translate("May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or as a portrange (eg \"1024:2048\") without quotes"))
+
+proto = mwan_rule:option(Value, "proto", translate("Protocol"),
+ translate("View the contents of /etc/protocols for protocol descriptions"))
+ proto.default = "all"
+ proto.rmempty = false
+ proto:value("all")
+ proto:value("ip")
+ proto:value("tcp")
+ proto:value("udp")
+ proto:value("icmp")
+ proto:value("esp")
+ cbi_add_protocol(proto)
+
+use_policy = mwan_rule:option(Value, "use_policy", translate("Policy assigned"))
+ cbi_add_policy(use_policy)
+ use_policy:value("unreachable")
+ use_policy:value("default")
+
+
+-- ------ currently configured policies ------ --
+
+mwan_policy = m5:section(TypedSection, "policy", translate("Currently Configured Policies"))
+ mwan_policy.addremove = false
+ mwan_policy.dynamic = false
+ mwan_policy.sortable = false
+ mwan_policy.template = "cbi/tblsection"
+
+
+return m5
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/admin_status/index/mwan3.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/admin_status/index/mwan3.htm
new file mode 100644
index 000000000..f510f158c
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/admin_status/index/mwan3.htm
@@ -0,0 +1 @@
+<%+mwan3/mwan3_status%>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_diagnostics.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_diagnostics.htm
new file mode 100644
index 000000000..6d9abcbed
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_diagnostics.htm
@@ -0,0 +1,134 @@
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<%
+ local uci = require "luci.model.uci"
+
+ str = ""
+ uci.cursor():foreach("mwan3", "interface",
+ function (section)
+ str = str .. section[".name"] .. " "
+ end
+ )
+%>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ var stxhr = new XHR();
+
+ function update_status(tool, alt)
+ {
+ var iface = document.getElementById('mwan3iface').value;
+ var output = document.getElementById('diag_output');
+
+ if (tool == "service")
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
+ "Waiting for MWAN3 to " + alt + "..."
+ ;
+ }
+ else
+ {
+ output.innerHTML =
+ '<img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="padding: 20px; vertical-align: middle;" /> ' +
+ "Waiting for diagnostic results..."
+ ;
+ }
+
+ output.parentNode.style.display = 'block';
+ output.style.display = 'inline';
+
+ stxhr.get('<%=luci.dispatcher.build_url("admin", "network", "mwan3", "advanced")%>/diag_display' + '/' + iface + '/' + tool + '/' + alt, null,
+ function(x, st)
+ {
+ if (st.diagres)
+ {
+ output.innerHTML = String.format('<pre id="diag_output_css">%h</pre>', st.diagres[0].diagresult);
+ }
+ else
+ {
+ var temp = '';
+ var ncint = 'No diagnostic results returned';
+ temp = String.format(
+ '<pre id="diag_output_css"><strong>%s</strong></pre>',
+ ncint
+ );
+ output.innerHTML = temp;
+ }
+ }
+ );
+ }
+//]]></script>
+
+<div id="mwan3_diagnostics" class="cbi-map">
+ <fieldset id="diag_select" class="cbi-section">
+ <legend><%:MWAN3 Interface Diagnostics%></legend>
+ <select id="mwan3iface">
+ <% for z in str:gmatch("[^ ]+") do -%><option value="<%=z%>"><%=z%></option><%- end %>
+ </select>
+ <div id="buttoncss">
+ <input type="button" value="<%:Ping default gateway%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'gateway')" />
+ <input type="button" value="<%:Ping tracking IP%>" class="cbi-button cbi-button-apply" onclick="update_status('ping', 'track_ip')" />
+ <input type="button" value="<%:Check IP rules%>" class="cbi-button cbi-button-apply" onclick="update_status('rulechk', null)" />
+ <input type="button" value="<%:Check routing table%>" class="cbi-button cbi-button-apply" onclick="update_status('routechk', null)" />
+ <input type="button" value="<%:Hotplug ifup%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifup')" />
+ <input type="button" value="<%:Hotplug ifdown%>" class="cbi-button cbi-button-apply" onclick="update_status('hotplug', 'ifdown')" />
+ </div>
+ </fieldset>
+ <fieldset id="diag_select" class="cbi-section">
+ <legend><%:MWAN3 Service Control%></legend>
+ <div id="buttoncss">
+ <input type="button" value="<%:Restart MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'restart')" />
+ <input type="button" value="<%:Stop MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'stop')" />
+ <input type="button" value="<%:Start MWAN3%>" class="cbi-button cbi-button-apply" onclick="update_status('service', 'start')" />
+ </div>
+ </fieldset>
+ <fieldset class="cbi-section" style="display:none">
+ <legend><%:Diagnostic Results%></legend>
+ <div id="diag_output"></div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan3_diagnostics {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #diag_select {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwan3iface {
+ float: left;
+ margin: 8px 20px 0px 0px;
+ }
+ #buttoncss {
+ display: table;
+ float: left;
+ text-align: left;
+ }
+ .cbi-button {
+ margin: 8px 20px 0px 0px;
+ min-width: 153px;
+ }
+ #diag_output_css {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_hotplug.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_hotplug.htm
new file mode 100644
index 000000000..e90942b91
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_hotplug.htm
@@ -0,0 +1,23 @@
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_mwan3.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_mwan3.htm
new file mode 100644
index 000000000..d11bdd7d8
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_mwan3.htm
@@ -0,0 +1,23 @@
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_network.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_network.htm
new file mode 100644
index 000000000..59dd4fa0e
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_network.htm
@@ -0,0 +1,23 @@
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin: 0px 0px 0px 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ .cbi-section-node {
+ margin-top: 20px;
+ }
+ .cbi-section {
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+</style>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_troubleshoot.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_troubleshoot.htm
new file mode 100644
index 000000000..1a92ebd02
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_adv_troubleshoot.htm
@@ -0,0 +1,77 @@
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/hotplug")%>"><%:Hotplug Script%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/mwan3")%>"><%:MWAN3 Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/network")%>"><%:Network Config%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/diag")%>"><%:Diagnostics%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/advanced/tshoot")%>"><%:Troubleshooting%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "advanced", "tshoot_display")%>', null,
+ function(x, st)
+ {
+ var tx = document.getElementById('mwan3_tshoot_text');
+ if (st.mw3ver)
+ {
+ var temp = '';
+ var mwanvers = 'Software versions : <br /><br />';
+ var mwan3cnfg = '<br /><br />Output of &#34;cat /etc/config/mwan3&#34; : <br /><br />';
+ var netcnfg = '<br /><br />Output of &#34;cat /etc/config/network&#34; : <br /><br />';
+ var ifcnfg = '<br /><br />Output of &#34;ifconfig&#34; : <br /><br />';
+ var iproute = '<br /><br />Output of &#34;route -n&#34; : <br /><br />';
+ var iprulesh = '<br /><br />Output of &#34;ip rule show&#34; : <br /><br />';
+ var routelisttbl = '<br /><br />Output of &#34;ip route list table 1-250&#34; : <br /><br />';
+ var firewalldef = '<br /><br />Firewall default output policy (must be ACCEPT) : <br /><br />';
+ var iptable = '<br /><br />Output of &#34;iptables -L -t mangle -v -n&#34; : <br /><br />';
+
+ temp = String.format(
+ '<pre><span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s<span class="tsht">%s</span>%s</pre>',
+ mwanvers, st.mw3ver[0].mwan3v, mwan3cnfg, st.mwan3config[0].mwn3cfg, netcnfg, st.netconfig[0].netcfg, ifcnfg, st.ifconfig[0].ifcfg, iproute, st.rtshow[0].iprtshow, iprulesh, st.iprule[0].rule, routelisttbl, st.routelist[0].iprtlist, firewalldef, st.fidef[0].firedef, iptable, st.iptables[0].iptbls
+ );
+ tx.innerHTML = temp;
+ }
+ else
+ {
+ var temp = '';
+ var terror = 'Error collecting troubleshooting information';
+ temp = String.format(
+ '<strong>%s</strong>',
+ terror
+ );
+ tx.innerHTML = temp;
+ }
+ }
+ );
+//]]></script>
+
+<div id="tshoot_div">
+ <fieldset class="cbi-section">
+ <legend><%:Troubleshooting Data%></legend>
+ <div id="mwan3_tshoot_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #tshoot_div {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #mwan3_tshoot_text {
+ padding: 20px;
+ text-align: left;
+ }
+ .tsht {
+ background-color: rgb(78, 186, 241);
+ }
+</style>
+
+<%+footer%>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_config_css.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_config_css.htm
new file mode 100644
index 000000000..303fa2094
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_config_css.htm
@@ -0,0 +1,34 @@
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ table td { /*cells showing the configuration values*/
+ padding: 0px;
+ text-align: center;
+ vertical-align: middle;
+ }
+ table th { /*column for configuration section name*/
+ padding: 0px;
+ text-align: center;
+ vertical-align: middle;
+ }
+ table tbody th { /*column for configuration section name*/
+ padding: 0px;
+ vertical-align: middle;
+ }
+ .cbi-section-node table div { /*rows*/
+ padding-top: 5px;
+ }
+ table.cbi-section-table td.cbi-section-table-cell { /*sort buttons column*/
+ text-align: center;
+ }
+ .cbi-section h3 {
+ color: rgb(85, 85, 85);
+ font-family: Trebuchet MS,Verdana,sans-serif;
+ font-style: italic;
+ font-weight: normal;
+ }
+</style>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_detail.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_detail.htm
new file mode 100644
index 000000000..920a20bda
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_detail.htm
@@ -0,0 +1,62 @@
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview")%>"><%:Interface Status%></a></li>
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview/over_detail")%>"><%:Detailed Status%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "detail_status")%>', null,
+ function(x, st)
+ {
+ var tx = document.getElementById('mwan3_detail_text');
+ if (st.mwan3dst)
+ {
+ var temp = '';
+ temp = String.format(
+ '<pre>%s</pre>',
+ st.mwan3dst[0].detailstat
+ );
+ tx.innerHTML = temp;
+ }
+ else
+ {
+ var temp = '';
+ var nslg = 'No detailed status information available';
+ temp = String.format(
+ '<strong>%s</strong>',
+ nslg
+ );
+ tx.innerHTML = temp;
+ }
+ }
+ );
+//]]></script>
+
+<div id="mwan3_detail_status">
+ <fieldset class="cbi-section">
+ <legend><%:MWAN3 Multi-WAN Detailed Status%></legend>
+ <div id="mwan3_detail_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan3_detail_status {
+ border: 1px dotted #555555;
+ background-color: #FFFFFF;
+ padding: 20px;
+ }
+ #mwan3_detail_text {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_interface.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_interface.htm
new file mode 100644
index 000000000..2e846a71e
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_over_interface.htm
@@ -0,0 +1,146 @@
+<%+header%>
+
+<ul class="cbi-tabmenu">
+ <li class="cbi-tab"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview")%>"><%:Interface Status%></a></li>
+ <li class="cbi-tab-disabled"><a href="<%=luci.dispatcher.build_url("admin/network/mwan3/overview/over_detail")%>"><%:Detailed Status%></a></li>
+</ul>
+
+<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "iface_status")%>', null,
+ function(x, st)
+ {
+ var tx = document.getElementById('mwan3_status_text');
+ if (st.wans)
+ {
+ var temp = '';
+
+ for( var i = 0; i < st.wans.length; i++ )
+ {
+ var stat = '';
+ var cssc = '';
+
+ switch (st.wans[i].status)
+ {
+ case 'on':
+ stat = 'Online (tracking active)';
+ cssc = 'wanon';
+ break;
+
+ case 'nm':
+ stat = 'Online (tracking off)';
+ cssc = 'wanon';
+ break;
+
+ case 'off':
+ stat = 'Offline';
+ cssc = 'wanoff';
+ break;
+
+ case 'ne':
+ stat = 'Disabled';
+ cssc = 'wanoff';
+ break;
+ }
+
+ temp += String.format(
+ '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
+ cssc, st.wans[i].name, st.wans[i].link, st.wans[i].ifname, stat
+ );
+ }
+ tx.innerHTML = temp;
+ }
+ else
+ {
+ var temp = '';
+ var ncint = 'No MWAN3 interfaces found';
+ temp = String.format(
+ '<strong>%s</strong>',
+ ncint
+ );
+ tx.innerHTML = temp;
+ }
+
+ var tx = document.getElementById('mwan3_statuslog_text');
+ if (st.mwan3log)
+ {
+ var temp = '';
+ var mwan3lg = 'Last 50 MWAN3 systemlog entries. Newest entries sorted at the top :';
+
+ temp = String.format(
+ '<pre>%s<br /><br />%s</pre>',
+ mwan3lg, st.mwan3log[0].mwanlog
+ );
+ tx.innerHTML = temp;
+ }
+ else
+ {
+ var temp = '';
+ var nslg = 'No MWAN3 systemlog history found';
+ temp = String.format(
+ '<strong>%s</strong>',
+ nslg
+ );
+ tx.innerHTML = temp;
+ }
+ }
+ );
+//]]></script>
+
+<div id="mwan3_interface_status">
+ <fieldset id="interface_field" class="cbi-section">
+ <legend><%:MWAN3 Multi-WAN Interface Live Status%></legend>
+ <div id="mwan3_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+ <fieldset class="cbi-section">
+ <legend><%:MWAN3 Multi-WAN Interface Systemlog%></legend>
+ <div id="mwan3_statuslog_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+ </fieldset>
+</div>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: none;
+ margin-left: 30px;
+ padding-right: 30px;
+ width: auto;
+ }
+ #mwan3_interface_status {
+ background-color: #FFFFFF;
+ border: 1px dotted #555555;
+ padding: 20px;
+ }
+ #interface_field {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwan3_status_text {
+ display: table;
+ font-size: 14px;
+ margin: auto;
+ max-width: 1044px;
+ min-width: 246px;
+ width: 100%;
+ }
+ .wanon {
+ background-color: rgb(144, 240, 144);
+ }
+ .wanoff {
+ background-color: rgb(240, 144, 144);
+ }
+ .wanon, .wanoff {
+ border-radius: 60px;
+ box-shadow: 0px 2px 5px -3px;
+ float: left;
+ margin: 8px 3px 0px 3px;
+ min-height: 30px;
+ min-width: 235px;
+ padding: 5px 10px 8px 10px;
+ text-align: center;
+ }
+ #mwan3_statuslog_text {
+ padding: 20px;
+ text-align: left;
+ }
+</style>
+
+<%+footer%>
diff --git a/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_status.htm b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_status.htm
new file mode 100644
index 000000000..9315a850c
--- /dev/null
+++ b/net/mwan3-luci/files/usr/lib/lua/luci/view/mwan3/mwan3_status.htm
@@ -0,0 +1,95 @@
+<script type="text/javascript">//<![CDATA[
+ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "network", "mwan3", "overview", "iface_status")%>', null,
+ function(x, st)
+ {
+ var tx = document.getElementById('mwan3_status_text');
+ if (st.wans)
+ {
+ var temp = '';
+
+ for( var i = 0; i < st.wans.length; i++ )
+ {
+ var stat = '';
+ var cssc = '';
+
+ switch (st.wans[i].status)
+ {
+ case 'on':
+ stat = 'Online (tracking active)';
+ cssc = 'wanon';
+ break;
+
+ case 'nm':
+ stat = 'Online (tracking off)';
+ cssc = 'wanon';
+ break;
+
+ case 'off':
+ stat = 'Offline';
+ cssc = 'wanoff';
+ break;
+
+ case 'ne':
+ stat = 'Disabled';
+ cssc = 'wanoff';
+ break;
+ }
+
+ temp += String.format(
+ '<span class="%s"><strong>%s (<a href="%q">%s</a>)</strong><br />%s</span>',
+ cssc, st.wans[i].name, st.wans[i].link, st.wans[i].ifname, stat
+ );
+ }
+ tx.innerHTML = temp;
+ }
+ else
+ {
+ var temp = '';
+ var ncint = 'No MWAN3 interfaces found';
+ temp += String.format(
+ '<strong>%s</strong>',
+ ncint
+ );
+ tx.innerHTML = temp;
+ }
+ }
+ );
+//]]></script>
+
+<fieldset id="interface_field" class="cbi-section">
+ <legend><%:MWAN3 Multi-WAN Interface Live Status%></legend>
+ <div id="mwan3_status_text"><img src="<%=resource%>/icons/loading.gif" alt="<%:Loading%>" style="vertical-align:middle" /> Collecting data...</div>
+</fieldset>
+
+<style type="text/css">
+ .container { /*container for entire page. fixes bootstrap theme's ridiculously small page width*/
+ max-width: 1044px;
+ }
+ #interface_field {
+ padding: 12px 20px 20px 20px;
+ }
+ #mwan3_status_text {
+ display: table;
+ font-size: 14px;
+ margin: auto;
+ max-width: 1044px;
+ min-width: 246px;
+ width: 100%;
+ }
+ .wanon {
+ background-color: rgb(144, 240, 144);
+ }
+ .wanoff {
+ background-color: rgb(240, 144, 144);
+ }
+ .wanon, .wanoff {
+ border-radius: 60px;
+ box-shadow: 0px 2px 5px -3px;
+ float: left;
+ margin: 8px 3px 0px 3px;
+ min-height: 30px;
+ min-width: 235px;
+ padding: 5px 10px 8px 10px;
+ text-align: center;
+ }
+</style>
diff --git a/net/mwan3/Makefile b/net/mwan3/Makefile
new file mode 100644
index 000000000..49c8d592d
--- /dev/null
+++ b/net/mwan3/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2006-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:=mwan3
+PKG_VERSION:=1.4
+PKG_RELEASE:=22
+PKG_MAINTAINER:=Jeroen Louwes <jeroen.louwes@gmail.com>
+PKG_LICENSE:=GPLv2
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mwan3
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Routing and Redirection
+ DEPENDS:=+ip +iptables +iptables-mod-conntrack-extra +iptables-mod-ipopt
+ TITLE:=Multiwan hotplug script with connection tracking support
+ MAINTAINER:=Jeroen Louwes <jeroen.louwes@gmail.com>
+ PKGARCH:=all
+endef
+
+define Package/mwan3/description
+ Hotplug script which makes configuration of multiple WAN interfaces simple and manageable. With loadbalancing/failover support for up to 250 wan interfaces, connection tracking and an easy to manage traffic ruleset.
+endef
+
+define Package/mwan3/conffiles
+ /etc/config/mwan3
+endef
+
+define Build/Compile
+endef
+
+define Package/mwan3/install
+ $(CP) ./files/* $(1)
+endef
+
+define Package/mwan3/postinst
+ [ -n "$${IPKG_INSTROOT}" ] || /etc/init.d/mwan3 enable
+ exit 0
+endef
+
+$(eval $(call BuildPackage,mwan3))
diff --git a/net/mwan3/files/etc/config/mwan3 b/net/mwan3/files/etc/config/mwan3
new file mode 100644
index 000000000..53f2f9832
--- /dev/null
+++ b/net/mwan3/files/etc/config/mwan3
@@ -0,0 +1,79 @@
+
+config interface 'wan'
+ option enabled '1'
+ list track_ip '8.8.4.4'
+ list track_ip '8.8.8.8'
+ list track_ip '208.67.222.222'
+ list track_ip '208.67.220.220'
+ option reliability '2'
+ option count '1'
+ option timeout '2'
+ option interval '5'
+ option down '3'
+ option up '8'
+
+config interface 'wan2'
+ option enabled '0'
+ list track_ip '8.8.8.8'
+ list track_ip '208.67.220.220'
+ option reliability '1'
+ option count '1'
+ option timeout '2'
+ option interval '5'
+ option down '3'
+ option up '8'
+
+config member 'wan_m1_w3'
+ option interface 'wan'
+ option metric '1'
+ option weight '3'
+
+config member 'wan_m2_w3'
+ option interface 'wan'
+ option metric '2'
+ option weight '3'
+
+config member 'wan2_m1_w2'
+ option interface 'wan2'
+ option metric '1'
+ option weight '2'
+
+config member 'wan2_m2_w2'
+ option interface 'wan2'
+ option metric '2'
+ option weight '2'
+
+config policy 'wan_only'
+ list use_member 'wan_m1_w3'
+
+config policy 'wan2_only'
+ list use_member 'wan2_m1_w2'
+
+config policy 'balanced'
+ list use_member 'wan_m1_w3'
+ list use_member 'wan2_m1_w2'
+
+config policy 'wan_wan2'
+ list use_member 'wan_m1_w3'
+ list use_member 'wan2_m2_w2'
+
+config policy 'wan2_wan'
+ list use_member 'wan_m2_w3'
+ list use_member 'wan2_m1_w2'
+
+config rule 'sticky_even'
+ option src_ip '0.0.0.0/0.0.0.1'
+ option dest_port '443'
+ option proto 'tcp'
+ option use_policy 'wan_wan2'
+
+config rule 'sticky_odd'
+ option src_ip '0.0.0.1/0.0.0.1'
+ option dest_port '443'
+ option proto 'tcp'
+ option use_policy 'wan2_wan'
+
+config rule 'default_rule'
+ option dest_ip '0.0.0.0/0'
+ option use_policy 'balanced'
+
diff --git a/net/mwan3/files/etc/hotplug.d/iface/15-mwan3 b/net/mwan3/files/etc/hotplug.d/iface/15-mwan3
new file mode 100644
index 000000000..fe1375df8
--- /dev/null
+++ b/net/mwan3/files/etc/hotplug.d/iface/15-mwan3
@@ -0,0 +1,328 @@
+#!/bin/sh
+
+mwan3_get_iface_id()
+{
+ let iface_count++
+ [ "$1" == "$INTERFACE" ] && iface_id=$iface_count
+}
+
+mwan3_get_route_args()
+{
+ route_args=$(ip -4 route list dev $DEVICE default | head -1 | sed '/.*via \([^ ]*\) .*$/!d;s//\1/;q' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}')
+ [ -n "$route_args" ] && route_args="via $route_args"
+ route_args="nexthop $route_args dev $DEVICE"
+}
+
+mwan3_set_general_iptables()
+{
+ if ! iptables -S mwan3_ifaces -t mangle &> /dev/null; then
+ iptables -N mwan3_ifaces -t mangle
+ fi
+
+ if ! iptables -S mwan3_rules -t mangle &> /dev/null; then
+ iptables -N mwan3_rules -t mangle
+ fi
+
+ if ! iptables -S mwan3_connected -t mangle &> /dev/null; then
+ iptables -N mwan3_connected -t mangle
+ fi
+
+ if ! iptables -S mwan3_hook -t mangle &> /dev/null; then
+ iptables -N mwan3_hook -t mangle
+ iptables -A mwan3_hook -t mangle -j CONNMARK --restore-mark --nfmask 0xff00 --ctmask 0xff00
+ iptables -A mwan3_hook -t mangle -m mark --mark 0x0/0xff00 -j mwan3_ifaces
+ iptables -A mwan3_hook -t mangle -m mark --mark 0x0/0xff00 -j mwan3_connected
+ iptables -A mwan3_hook -t mangle -m mark --mark 0x0/0xff00 -j mwan3_rules
+ iptables -A mwan3_hook -t mangle -j CONNMARK --save-mark --nfmask 0xff00 --ctmask 0xff00
+ fi
+
+ if ! iptables -S mwan3_track_hook -t mangle &> /dev/null; then
+ iptables -N mwan3_track_hook -t mangle
+ fi
+
+ if ! iptables -S PREROUTING -t mangle | grep mwan3_hook &> /dev/null; then
+ iptables -A PREROUTING -t mangle -j mwan3_hook
+ fi
+
+ if ! iptables -S OUTPUT -t mangle | grep mwan3_hook &> /dev/null; then
+ iptables -A OUTPUT -t mangle -j mwan3_hook
+ fi
+
+ if ! iptables -S OUTPUT -t mangle | grep mwan3_track_hook &> /dev/null; then
+ iptables -A OUTPUT -t mangle -j mwan3_track_hook
+ fi
+
+ iptables -F mwan3_rules -t mangle
+}
+
+mwan3_set_connected_iptables()
+{
+ local connected_networks
+
+ if iptables -S mwan3_connected -t mangle &> /dev/null; then
+ iptables -F mwan3_connected -t mangle
+
+ for connected_networks in $(ip -4 route | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
+ iptables -A mwan3_connected -t mangle -d $connected_networks -m mark --mark 0x0/0xff00 -j MARK --set-xmark 0xff00/0xff00
+ done
+
+ iptables -I mwan3_connected -t mangle -d 224.0.0.0/3 -m mark --mark 0x0/0xff00 -j MARK --set-xmark 0xff00/0xff00
+ iptables -I mwan3_connected -t mangle -d 127.0.0.0/8 -m mark --mark 0x0/0xff00 -j MARK --set-xmark 0xff00/0xff00
+ fi
+}
+
+mwan3_set_iface_iptables()
+{
+ local local_net local_nets
+
+ local_net=$(ip -4 route list dev $DEVICE scope link | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}')
+
+ if ! iptables -S mwan3_iface_$INTERFACE -t mangle &> /dev/null; then
+ iptables -N mwan3_iface_$INTERFACE -t mangle
+ fi
+
+ iptables -F mwan3_iface_$INTERFACE -t mangle
+ iptables -D mwan3_ifaces -t mangle -i $DEVICE -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE &> /dev/null
+
+ if [ $ACTION == "ifup" ]; then
+ if [ -n "$local_net" ]; then
+ for local_nets in $local_net ; do
+ if [ $ACTION == "ifup" ]; then
+ iptables -I mwan3_iface_$INTERFACE -t mangle -s $local_net -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE" -j MARK --set-xmark 0xff00/0xff00
+ fi
+ done
+ fi
+
+ iptables -A mwan3_iface_$INTERFACE -t mangle -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE" -j MARK --set-xmark $(($iface_id*256))/0xff00
+ iptables -A mwan3_ifaces -t mangle -i $DEVICE -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE
+ fi
+
+ if [ $ACTION == "ifdown" ]; then
+ iptables -X mwan3_iface_$INTERFACE -t mangle
+ fi
+}
+
+mwan3_set_iface_route()
+{
+ ip -4 route flush table $iface_id
+ [ $ACTION == "ifup" ] && ip -4 route add table $iface_id default $route_args
+}
+
+mwan3_set_iface_rules()
+{
+ while [ -n "$(ip -4 rule list | awk '$1 == "'$(($iface_id+1000)):'"')" ]; do
+ ip -4 rule del pref $(($iface_id+1000))
+ done
+
+ while [ -n "$(ip -4 rule list | awk '$1 == "'$(($iface_id+2000)):'"')" ]; do
+ ip -4 rule del pref $(($iface_id+2000))
+ done
+
+ while [ -n "$(ip -4 rule list | awk '$1 == "2254:"')" ]; do
+ ip -4 rule del pref 2254
+ done
+
+ [ $ACTION == "ifup" ] && ip -4 rule add pref $(($iface_id+1000)) iif $DEVICE lookup main
+ [ $ACTION == "ifup" ] && ip -4 rule add pref $(($iface_id+2000)) fwmark $(($iface_id*256))/0xff00 lookup $iface_id
+ ip rule add pref 2254 fwmark 0xfe00/0xff00 unreachable
+}
+
+mwan3_track()
+{
+ local track_ip track_ips reliability count timeout interval down up
+
+ mwan3_list_track_ips()
+ {
+ track_ips="$1 $track_ips"
+ }
+ config_list_foreach $INTERFACE track_ip mwan3_list_track_ips
+
+ if [ -n "$track_ips" ]; then
+ config_get reliability $INTERFACE reliability 1
+ config_get count $INTERFACE count 1
+ config_get timeout $INTERFACE timeout 4
+ config_get interval $INTERFACE interval 10
+ config_get down $INTERFACE down 5
+ config_get up $INTERFACE up 5
+
+ if ! iptables -S mwan3_track_$INTERFACE -t mangle &> /dev/null; then
+ iptables -N mwan3_track_$INTERFACE -t mangle
+ iptables -A mwan3_track_hook -t mangle -p icmp -m icmp --icmp-type 8 -m length --length 32 -j mwan3_track_$INTERFACE
+ fi
+
+ iptables -F mwan3_track_$INTERFACE -t mangle
+
+ for track_ip in $track_ips; do
+ iptables -A mwan3_track_$INTERFACE -t mangle -d $track_ip -j MARK --set-xmark 0xff00/0xff00
+ done
+
+ [ -x /usr/sbin/mwan3track ] && /usr/sbin/mwan3track $INTERFACE $DEVICE $reliability $count $timeout $interval $down $up $track_ips &
+ else
+ iptables -D mwan3_track_hook -t mangle -p icmp -m icmp --icmp-type 8 -m length --length 32 -j mwan3_track_$INTERFACE &> /dev/null
+ iptables -F mwan3_track_$INTERFACE -t mangle &> /dev/null
+ iptables -X mwan3_track_$INTERFACE -t mangle &> /dev/null
+ fi
+}
+
+mwan3_set_policy()
+{
+ local iface_count iface_id metric probability weight
+
+ config_get INTERFACE $1 interface
+ config_get metric $1 metric 1
+ config_get weight $1 weight 1
+
+ [ -n "$INTERFACE" ] || return 0
+
+ config_foreach mwan3_get_iface_id interface
+
+ [ -n "$iface_id" ] || return 0
+
+ if iptables -S mwan3_iface_$INTERFACE -t mangle &> /dev/null; then
+ if [ "$metric" -lt "$lowest_metric" ]; then
+
+ total_weight=$weight
+ iptables -F mwan3_policy_$policy -t mangle
+ iptables -A mwan3_policy_$policy -t mangle -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE $weight $weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
+
+ lowest_metric=$metric
+
+ elif [ "$metric" -eq "$lowest_metric" ]; then
+
+ total_weight=$(($total_weight+$weight))
+ probability=$(($weight*1000/$total_weight))
+
+ if [ "$probability" -lt 10 ]; then
+ probability="0.00$probability"
+ elif [ $probability -lt 100 ]; then
+ probability="0.0$probability"
+ elif [ $probability -lt 1000 ]; then
+ probability="0.$probability"
+ else
+ probability="1"
+ fi
+
+ probability="-m statistic --mode random --probability $probability"
+
+ iptables -I mwan3_policy_$policy -t mangle -m mark --mark 0x0/0xff00 $probability -m comment --comment "$INTERFACE $weight $total_weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
+ fi
+ fi
+}
+
+mwan3_set_policies_iptables()
+{
+ local lowest_metric policy total_weight
+
+ policy=$1
+
+ if [ "$policy" != $(echo "$policy" | cut -c1-15) ]; then
+ logger -t mwan3 -p warn "Policy $policy exceeds max of 15 chars. Not setting policy" && return 0
+ fi
+
+ if ! iptables -S mwan3_policy_$policy -t mangle &> /dev/null; then
+ iptables -N mwan3_policy_$policy -t mangle
+ fi
+
+ iptables -F mwan3_policy_$policy -t mangle
+ iptables -A mwan3_policy_$policy -t mangle -m mark --mark 0x0/0xff00 -m comment --comment "unreachable" -j MARK --set-xmark 0xfe00/0xff00
+
+ lowest_metric=256
+ total_weight=0
+
+ config_list_foreach $policy use_member mwan3_set_policy
+
+ iptables -X $policy -t mangle &> /dev/null
+}
+
+mwan3_set_user_rules_iptables()
+{
+ local proto src_ip src_port dest_ip dest_port use_policy
+
+ config_get proto $1 proto all
+ config_get src_ip $1 src_ip 0.0.0.0/0
+ config_get src_port $1 src_port 0:65535
+ config_get dest_ip $1 dest_ip 0.0.0.0/0
+ config_get dest_port $1 dest_port 0:65535
+ config_get use_policy $1 use_policy
+
+ if [ -n "$use_policy" ]; then
+ if [ "$use_policy" == "default" ]; then
+ use_policy="MARK --set-xmark 0xff00/0xff00"
+ elif [ "$use_policy" == "unreachable" ]; then
+ use_policy="MARK --set-xmark 0xfe00/0xff00"
+ else
+ use_policy="mwan3_policy_$use_policy"
+ fi
+
+ case $proto in
+ tcp|udp)
+ iptables -A mwan3_rules -t mangle -p $proto -s $src_ip -d $dest_ip -m multiport --sports $src_port -m multiport --dports $dest_port -m mark --mark 0/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
+ ;;
+ *)
+ iptables -A mwan3_rules -t mangle -p $proto -s $src_ip -d $dest_ip -m mark --mark 0/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
+ ;;
+ esac
+ fi
+}
+
+mwan3_ifupdown()
+{
+ local counter enabled iface_count iface_id route_args wan_metric
+
+ [ -n "$DEVICE" ] || exit 0
+ [ -n "$INTERFACE" ] || exit 0
+ [ "$(uci get -P /var/state mwan3.$INTERFACE 2> /dev/null)" == "interface" ] || return 0
+
+ config_load mwan3
+ config_get enabled $INTERFACE enabled 0
+
+ counter=0
+
+ if [ $ACTION == "ifup" ]; then
+ [ "$enabled" -eq 1 ] || exit 0
+
+ while [ -z "$(ip -4 route list dev $DEVICE default | head -1)" -a "$counter" -lt 10 ]; do
+ sleep 1
+ let counter++
+ if [ "$counter" -ge 10 ]; then
+ logger -t mwan3 -p warn "Could not find gateway for interface $INTERFACE ($DEVICE)" && exit 0
+ fi
+ done
+
+ mwan3_get_route_args
+ fi
+
+ while [ "$(pgrep -f -o hotplug-call)" -ne $$ -a "$counter" -lt 60 ]; do
+ sleep 1
+ let counter++
+ if [ "$counter" -ge 60 ]; then
+ logger -t mwan3 -p warn "Timeout waiting for older hotplug processes to finish. $ACTION interface $INTERFACE ($DEVICE) aborted" && exit 0
+ fi
+ done
+
+ config_foreach mwan3_get_iface_id interface
+
+ [ -n "$iface_id" ] || exit 0
+ [ "$iface_count" -le 250 ] || exit 0
+ unset iface_count
+ unset counter
+
+ logger -t mwan3 -p notice "$ACTION interface $INTERFACE ($DEVICE)"
+
+ mwan3_set_general_iptables
+ mwan3_set_iface_iptables
+ mwan3_set_iface_route
+ mwan3_set_iface_rules
+
+ [ $ACTION == "ifup" ] && mwan3_track
+
+ config_foreach mwan3_set_policies_iptables policy
+ config_foreach mwan3_set_user_rules_iptables rule
+}
+
+case "$ACTION" in
+ ifup|ifdown)
+ mwan3_ifupdown
+ mwan3_set_connected_iptables
+ ;;
+esac
diff --git a/net/mwan3/files/etc/init.d/mwan3 b/net/mwan3/files/etc/init.d/mwan3
new file mode 100755
index 000000000..44af759ed
--- /dev/null
+++ b/net/mwan3/files/etc/init.d/mwan3
@@ -0,0 +1,20 @@
+#!/bin/sh /etc/rc.common
+START=99
+
+start() {
+ /usr/sbin/mwan3 start
+}
+
+stop() {
+ /usr/sbin/mwan3 stop
+}
+
+restart() {
+ stop
+ start
+}
+
+boot() {
+ # Don't start on boot, mwan3 is started by hotplug event.
+ return 0
+}
diff --git a/net/mwan3/files/usr/sbin/mwan3 b/net/mwan3/files/usr/sbin/mwan3
new file mode 100755
index 000000000..7d274d430
--- /dev/null
+++ b/net/mwan3/files/usr/sbin/mwan3
@@ -0,0 +1,208 @@
+#!/bin/sh /etc/rc.common
+
+. /lib/network/config.sh
+
+extra_help() {
+ cat <<EOF
+
+ ifup <iface> Start service on interface
+ ifdown <iface> Stop service on interface
+ interfaces Show interfaces status
+ policies Show policies status
+ rules Show rules status
+ status Show all status
+EOF
+}
+
+EXTRA_COMMANDS="ifdown ifup interfaces policies rules status"
+EXTRA_HELP="$(extra_help)"
+
+
+ifdown()
+{
+ if [ -z "$1" ]; then
+ echo "Error: Expecting interface. Usage: mwan3 ifdown <interface>" && exit 0
+ fi
+
+ if [ -n "$2" ]; then
+ echo "Error: Too many arguments. Usage: mwan3 ifdown <interface>" && exit 0
+ fi
+
+ local device
+
+ device=$(uci get -p /var/state network.$1.ifname) &> /dev/null
+
+ if [ -e /var/run/mwan3track-$1.pid ] ; then
+ kill $(cat /var/run/mwan3track-$1.pid)
+ rm /var/run/mwan3track-$1.pid
+ fi
+
+ if [ -n "$device" ] ; then
+ ACTION=ifdown INTERFACE=$1 DEVICE=$device /sbin/hotplug-call iface
+ fi
+}
+
+ifup()
+{
+ config_load mwan3
+
+ if [ -z "$1" ]; then
+ echo "Expecting interface. Usage: mwan3 ifup <interface>" && exit 0
+ fi
+
+ if [ -n "$2" ]; then
+ echo "Too many arguments. Usage: mwan3 ifup <interface>" && exit 0
+ fi
+
+ local device enabled
+
+ config_get enabled "$1" enabled 0
+
+ device=$(uci get -p /var/state network.$1.ifname) &> /dev/null
+
+ if [ -n "$device" ] ; then
+ [ "$enabled" -eq 1 ] && ACTION=ifup INTERFACE=$1 DEVICE=$device /sbin/hotplug-call iface
+ fi
+}
+
+interfaces()
+{
+ config_load mwan3
+
+ local device enabled iface_id tracking
+
+ echo "Interface status:"
+
+ check_iface_status()
+ {
+ device=$(uci get -p /var/state network.$1.ifname) &> /dev/null
+
+ if [ -z "$device" ]; then
+ echo "Interface $1 is unknown"
+ return 0
+ fi
+
+ config_get enabled "$1" enabled 0
+ let iface_id++
+
+ if [ -n "$(ps -w | grep mwan3track | grep -v grep | sed '/.*\/usr\/sbin\/mwan3track \([^ ]*\) .*$/!d;s//\1/' | awk '$1 == ("'$1'")')" ]; then
+ tracking="active"
+ else
+ tracking="down"
+ fi
+
+ if [ -n "$(ip rule | awk '$5 == ("'$device'")')" -a -n "$(iptables -S mwan3_iface_$1 -t mangle 2> /dev/null)" -a -n "$(ip -4 route list table $iface_id default dev $device 2> /dev/null)" ]; then
+ if [ -n "$(uci get -p /var/state mwan3.$1.track_ip 2> /dev/null)" ]; then
+ echo "Interface $1 is online (tracking $tracking)"
+ else
+ echo "Interface $1 is online"
+ fi
+ elif [ -n "$(ip rule | awk '$5 == ("'$device'")')" -o -n "$(iptables -S mwan3_iface_$1 -t mangle 2> /dev/null)" -o -n "$(ip -4 route list table $iface_id default dev $device 2> /dev/null)" ]; then
+ echo "Interface $1 error"
+ else
+ if [ "$enabled" -eq 1 ]; then
+ if [ -n "$(uci get -p /var/state mwan3.$1.track_ip 2> /dev/null)" ]; then
+ echo "Interface $1 is offline (tracking $tracking)"
+ else
+ echo "Interface $1 is offline"
+ fi
+ else
+ echo "Interface $1 is disabled"
+ fi
+ fi
+ }
+ config_foreach check_iface_status interface
+ echo -e
+}
+
+policies()
+{
+ local percent policy share total_weight weight iface
+
+ for policy in $(iptables -S -t mangle | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
+ echo "Policy $policy:" | sed 's/mwan3_policy_//g'
+
+ for iface in $(iptables -S $policy -t mangle | cut -s -d'"' -f2 | awk '{print $1}'); do
+ [ -n "$total_weight" ] || total_weight=$(iptables -S $policy -t mangle | grep "$iface " | cut -s -d'"' -f2 | awk '{print $3}')
+ done
+
+ if [ ! -z "${total_weight##*[!0-9]*}" ]; then
+ for iface in $(iptables -S $policy -t mangle | cut -s -d'"' -f2 | awk '{print $1}'); do
+ weight=$(iptables -S $policy -t mangle | grep "$iface " | cut -s -d'"' -f2 | awk '{print $2}')
+ percent=$(($weight*100/$total_weight))
+ echo " $iface ($percent%)"
+ done
+ else
+ echo " $(iptables -S $policy -t mangle | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
+ fi
+
+ echo -e
+
+ unset iface
+ unset total_weight
+ done
+}
+rules()
+{
+ if [ -n "$(iptables -S mwan3_connected -t mangle 2> /dev/null)" ]; then
+ echo "Known networks:"
+ echo "destination policy hits" | awk '{ printf "%-19s%-19s%-9s%s\n",$1,$2,$3}'
+ echo "------------------------------------------------"
+ iptables -L mwan3_connected -t mangle -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_//g' | awk '{printf "%-19s%-19s%-9s%s\n",$9,"default",$1}'
+ echo -e
+ fi
+
+ if [ -n "$(iptables -S mwan3_rules -t mangle 2> /dev/null)" ]; then
+ echo "Active rules:"
+ echo "source destination proto src-port dest-port policy hits" | awk '{ printf "%-19s%-19s%-7s%-14s%-14s%-16s%-9s%s\n",$1,$2,$3,$4,$5,$6,$7}'
+ echo "---------------------------------------------------------------------------------------------------"
+ iptables -L mwan3_rules -t mangle -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_//g' | awk '{ printf "%-19s%-19s%-7s%-14s%-14s%-16s%-9s%s\n",$8,$9,$4,$12,$15,$3,$1}'
+ echo -e
+ fi
+}
+
+status()
+{
+ interfaces
+ policies
+ rules
+}
+
+start()
+{
+ config_load mwan3
+ config_foreach ifup interface
+}
+
+stop()
+{
+ local route rule table
+
+ killall mwan3track &> /dev/null
+ rm /var/run/mwan3track-* &> /dev/null
+
+ for route in $(ip route list table all | sed 's/.*table \([^ ]*\) .*/\1/' | awk '{print $1}' | awk '{for(i=1;i<=NF;i++) if($i+0>0) if($i+0<255) {print;break}}'); do
+ ip -4 route flush table $route &> /dev/null
+ done
+
+ for rule in $(ip -4 rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
+ ip -4 rule del pref $rule &> /dev/null
+ done
+
+ iptables -D PREROUTING -t mangle -j mwan3_hook &> /dev/null
+ iptables -D OUTPUT -t mangle -j mwan3_hook &> /dev/null
+ iptables -D OUTPUT -t mangle -j mwan3_track_hook &> /dev/null
+
+ for table in $(iptables -S -t mangle | awk '{print $2}' | grep mwan3 | sort -u); do
+ iptables -F $table -t mangle &> /dev/null
+ done
+
+ for table in $(iptables -S -t mangle | awk '{print $2}' | grep mwan3 | sort -u); do
+ iptables -X $table -t mangle &> /dev/null
+ done
+}
+
+restart() {
+ stop
+ start
+}
diff --git a/net/mwan3/files/usr/sbin/mwan3track b/net/mwan3/files/usr/sbin/mwan3track
new file mode 100755
index 000000000..c4d25e99d
--- /dev/null
+++ b/net/mwan3/files/usr/sbin/mwan3track
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+[ -z "$9" ] && echo "Error: should not be started manually" && exit 0
+
+if [ -e /var/run/mwan3track-$1.pid ] ; then
+ kill $(cat /var/run/mwan3track-$1.pid) &> /dev/null
+ rm /var/run/mwan3track-$1.pid &> /dev/null
+fi
+
+echo "$$" > /var/run/mwan3track-$1.pid
+
+score=$(($7+$8))
+track_ips=$(echo $* | cut -d ' ' -f 9-99)
+host_up_count=0
+lost=0
+
+while true; do
+
+ for track_ip in $track_ips; do
+ ping -I $2 -c $4 -W $5 -s 4 -q $track_ip &> /dev/null
+ if [ $? -eq 0 ]; then
+ let host_up_count++
+ else
+ let lost++
+ fi
+ done
+
+ if [ $host_up_count -lt $3 ]; then
+ let score--
+
+ if [ $score -lt $8 ]; then score=0 ; fi
+ if [ $score -eq $8 ]; then
+
+ logger -t mwan3track -p notice "Interface $1 ($2) is offline"
+ env -i ACTION=ifdown INTERFACE=$1 DEVICE=$2 /sbin/hotplug-call iface
+ score=0
+
+ fi
+
+ else
+
+ if [ $score -lt $(($7+$8)) ] && [ $lost -gt 0 ]; then
+
+ logger -t mwan3track -p info "Lost $(($lost*$4)) ping(s) on interface $1 ($2)"
+
+ fi
+
+ let score++
+ lost=0
+
+ if [ $score -gt $8 ]; then score=$(($7+$8)); fi
+ if [ $score -eq $8 ]; then
+
+ logger -t mwan3track -p notice "Interface $1 ($2) is online"
+ env -i ACTION=ifup INTERFACE=$1 DEVICE=$2 /sbin/hotplug-call iface
+ rm /var/run/mwan3track-$1.pid
+ exit 0
+ fi
+ fi
+
+ host_up_count=0
+ sleep $6
+done
+
+exit 1
diff --git a/net/netatalk/Makefile b/net/netatalk/Makefile
new file mode 100644
index 000000000..8729053c9
--- /dev/null
+++ b/net/netatalk/Makefile
@@ -0,0 +1,86 @@
+#
+# Copyright (C) 2009-2013 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:=netatalk
+PKG_VERSION:=2.2.4
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@SF/netatalk
+PKG_MD5SUM:=40753a32340c24e4ec395aeb55ef056e
+
+PKG_BUILD_PARALLEL:=1
+PKG_INSTALL:=1
+PKG_FIXUP:=autoreconf
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/netatalk
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Filesystem
+ DEPENDS:=+attr +libdb47 +libgcrypt +libopenssl $(LIBRPC_DEPENDS)
+ TITLE:=netatalk
+ URL:=http://netatalk.sourceforge.net
+ MAINTAINER:=W. Michael Petullo <mike@flyn.org>
+endef
+
+define Package/netatalk/decription
+ Netatalk is a freely-available Open Source AFP fileserver.
+ It also provides a kernel level implementation of the AppleTalk
+ Protocol Suite.
+endef
+
+define Package/netatalk/conffiles
+/etc/netatalk/afpd.conf
+endef
+
+TARGET_CFLAGS += -std=gnu99
+TARGET_LDFLAGS += $(LIBRPC)
+
+CONFIGURE_ARGS += \
+ --disable-afs \
+ --enable-hfs \
+ --disable-debugging \
+ --disable-shell-check \
+ --disable-timelord \
+ --disable-a2boot \
+ --disable-cups \
+ --disable-tcp-wrappers \
+ --with-cnid-default-backend=dbd \
+ --with-bdb="$(STAGING_DIR)/usr/" \
+ --with-libgcrypt-dir="$(STAGING_DIR)/usr" \
+ --with-ssl-dir="$(STAGING_DIR)/usr" \
+ --with-uams-path="/usr/lib/uams" \
+ --without-acls \
+ --without-pam \
+ --disable-admin-group \
+ --disable-srvloc \
+ --disable-zeroconf \
+ $(if $(CONFIG_SHADOW_PASSWORDS),--with-shadow,--without-shadow) \
+ --without-ldap
+
+define Package/netatalk/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_DIR) $(1)/usr/lib/uams
+ $(INSTALL_DIR) $(1)/etc/netatalk
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(CP) $(PKG_INSTALL_DIR)/usr/bin/afppasswd $(1)/usr/bin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/afpd $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/cnid_dbd $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/cnid_metad $(1)/usr/sbin/
+ $(CP) $(PKG_INSTALL_DIR)/usr/lib/uams/*.so $(1)/usr/lib/uams/
+ $(CP) ./files/AppleVolumes.default $(1)/etc/netatalk/
+ $(CP) $(PKG_INSTALL_DIR)/etc/netatalk/AppleVolumes.system $(1)/etc/netatalk/
+ $(INSTALL_CONF) ./files/afpd.conf $(1)/etc/netatalk/
+ $(INSTALL_BIN) ./files/afpd.init $(1)/etc/init.d/afpd
+endef
+
+$(eval $(call BuildPackage,netatalk))
diff --git a/net/netatalk/files/AppleVolumes.default b/net/netatalk/files/AppleVolumes.default
new file mode 100644
index 000000000..5835163a5
--- /dev/null
+++ b/net/netatalk/files/AppleVolumes.default
@@ -0,0 +1,2 @@
+-
+/tmp Temp allow:root,nobody cnidscheme:dbd
diff --git a/net/netatalk/files/afpd.conf b/net/netatalk/files/afpd.conf
new file mode 100644
index 000000000..097e954e5
--- /dev/null
+++ b/net/netatalk/files/afpd.conf
@@ -0,0 +1 @@
+- -noddp -uampath /usr/lib/uams -uamlist uams_guest.so,uams_passwd.so,uams_dhx_passwd.so,uams_randnum.so,uams_dhx2.so -passwdfile /etc/netatalk/afppasswd -savepassword -passwdminlen 0 -nosetpassword -defaultvol /etc/netatalk/AppleVolumes.default -systemvol /etc/netatalk/AppleVolumes.system -nouservol -guestname "nobody" -sleep 1 -icon
diff --git a/net/netatalk/files/afpd.init b/net/netatalk/files/afpd.init
new file mode 100644
index 000000000..8b1333984
--- /dev/null
+++ b/net/netatalk/files/afpd.init
@@ -0,0 +1,23 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2010-2012 OpenWrt.org
+
+START=70
+
+MAXCONS="7"
+
+start()
+{
+ service_start /usr/sbin/cnid_metad
+ service_start /usr/sbin/afpd -c ${MAXCONS}
+}
+
+stop()
+{
+ service_stop /usr/sbin/afpd
+ service_stop /usr/sbin/cnid_metad
+}
+
+reload()
+{
+ service_reload /usr/sbin/afpd
+}
diff --git a/net/netatalk/patches/001-automake-compat.patch b/net/netatalk/patches/001-automake-compat.patch
new file mode 100644
index 000000000..e56b08650
--- /dev/null
+++ b/net/netatalk/patches/001-automake-compat.patch
@@ -0,0 +1,9 @@
+--- a/macros/iconv.m4
++++ b/macros/iconv.m4
+@@ -114,6 +114,5 @@ int main() {
+
+ CFLAGS="$savedcflags"
+ LDFLAGS="$savedldflags"
+- CPPFLAGS="$saved_CPPFLAGS"
+
+ ])
diff --git a/net/nginx/Makefile b/net/nginx/Makefile
index 89a7ce99e..e93326e52 100644
--- a/net/nginx/Makefile
+++ b/net/nginx/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=nginx
PKG_VERSION:=1.4.7
-PKG_RELEASE:=1
+PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://nginx.org/download/
diff --git a/net/nginx/patches/400-nginx-1.4.x_proxy_protocol_patch_v2.patch b/net/nginx/patches/400-nginx-1.4.x_proxy_protocol_patch_v2.patch
index 52c1ce7ff..ba63834e8 100644
--- a/net/nginx/patches/400-nginx-1.4.x_proxy_protocol_patch_v2.patch
+++ b/net/nginx/patches/400-nginx-1.4.x_proxy_protocol_patch_v2.patch
@@ -882,17 +882,6 @@ Index: nginx-1.4.7/src/http/ngx_http_request.c
#if (NGX_HTTP_SSL)
-@@ -1291,6 +1368,10 @@ ngx_http_read_request_header(ngx_http_re
- c = r->connection;
- rev = c->read;
-
-+fprintf(stderr, "DEBUG: pos: %p, last: %p, start: %p, end: %p\n",
-+ r->header_in->pos, r->header_in->last, r->header_in->start,
-+ r->header_in->end);
-+
- n = r->header_in->last - r->header_in->pos;
-
- if (n > 0) {
Index: nginx-1.4.7/src/http/ngx_http_upstream.c
===================================================================
--- nginx-1.4.7.orig/src/http/ngx_http_upstream.c
diff --git a/net/ocserv/files/ocserv.init b/net/ocserv/files/ocserv.init
index d3e7f83a0..612262087 100644
--- a/net/ocserv/files/ocserv.init
+++ b/net/ocserv/files/ocserv.init
@@ -4,30 +4,6 @@ SERVICE_USE_PID=1
START=50
-setup_firewall() {
- local port fw
- config_get port $1 port
- test -z "$port" && return
-
- config_get fwport $1 fwport
- test "$fwport" = "$port" && return
-
- logger -t ocserv "opening port $port..."
- #can we remove the old rule?
- uci add firewall rule
- uci set firewall.@rule[-1].src=wan
- uci set firewall.@rule[-1].name="ocserv-ext-port"
- uci set firewall.@rule[-1].target=ACCEPT
- uci set firewall.@rule[-1].proto=tcpudp
- uci set firewall.@rule[-1].dest_port=$port
- uci commit firewall
-
- uci set ocserv.config.fwport="$port"
- uci commit ocserv
-
- /etc/init.d/firewall restart
-}
-
setup_config() {
config_get port $1 port "4443"
config_get max_clients $1 max_clients "8"
@@ -170,8 +146,6 @@ start() {
chmod 600 /var/etc/ocpasswd
config_foreach setup_users ocservusers
- setup_firewall config
-
service_start /usr/sbin/ocserv -c /var/etc/ocserv.conf
}
diff --git a/net/p910nd/Makefile b/net/p910nd/Makefile
new file mode 100644
index 000000000..d07ee1ac3
--- /dev/null
+++ b/net/p910nd/Makefile
@@ -0,0 +1,59 @@
+#
+# Copyright (C) 2009-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:=p910nd
+PKG_VERSION:=0.97
+PKG_RELEASE:=4
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=@SF/p910nd
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=COPYING
+PKG_MD5SUM:=69461a6c54dca0b13ecad5b83864b43e
+PKG_MAINTAINER:=Philipp Kerling <pkerling@casix.org>
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/p910nd
+ SECTION:=net
+ CATEGORY:=Network
+ SUBMENU:=Printing
+ TITLE:=A small non-spooling printer server
+ URL:=http://p910nd.sourceforge.net
+endef
+
+define Package/p910nd/conffiles
+/etc/config/p910nd
+endef
+
+define Package/p910nd/description
+ p910nd is a small daemon that copies any data received on
+ the port it is listening on to the corresponding printer
+ port. It is primarily intended for diskless Linux hosts
+ running as printer drivers but there is no reason why it
+ could not be used on diskful hosts. Port 9100 is copied
+ to /dev/lp0, 9101 to /dev/lp1 and 9102 to /dev/lp2. The
+ default is port 9100 to /dev/lp0.
+endef
+
+MAKE_FLAGS += \
+ CFLAGS="$(TARGET_CFLAGS) -DLOCKFILE_DIR=\"\\\"/tmp\"\\\""
+
+define Package/p910nd/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(CP) $(PKG_INSTALL_DIR)/usr/sbin/p910nd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_DATA) ./files/p910nd.config $(1)/etc/config/p910nd
+ $(INSTALL_DIR) $(1)/etc/init.d
+ $(INSTALL_BIN) ./files/p910nd.init $(1)/etc/init.d/p910nd
+endef
+
+$(eval $(call BuildPackage,p910nd))
diff --git a/net/p910nd/files/p910nd.config b/net/p910nd/files/p910nd.config
new file mode 100644
index 000000000..d5090359b
--- /dev/null
+++ b/net/p910nd/files/p910nd.config
@@ -0,0 +1,5 @@
+config p910nd
+ option device /dev/usb/lp0
+ option port 0
+ option bidirectional 1
+ option enabled 0
diff --git a/net/p910nd/files/p910nd.init b/net/p910nd/files/p910nd.init
new file mode 100644
index 000000000..8757551bf
--- /dev/null
+++ b/net/p910nd/files/p910nd.init
@@ -0,0 +1,51 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2007 OpenWrt.org
+START=50
+
+append_bool() {
+ local section="$1"
+ local option="$2"
+ local value="$3"
+ local _val
+ config_get_bool _val "$section" "$option" '0'
+ [ "$_val" -gt 0 ] && append args "$3"
+}
+
+append_string() {
+ local section="$1"
+ local option="$2"
+ local value="$3"
+ local _val
+ config_get _val "$section" "$option"
+ [ -n "$_val" ] && append args "$3$_val"
+}
+
+start_service() {
+ local section="$1"
+ args=""
+
+ append_bool "$section" bidirectional "-b"
+ append_string "$section" device "-f "
+ append_string "$section" bind "-i "
+ append_string "$section" port ""
+ config_get_bool "enabled" "$section" "enabled" '1'
+ [ "$enabled" -gt 0 ] && /usr/sbin/p910nd $args
+}
+
+stop_service() {
+ local section="$1"
+ config_get port "$section" port
+
+ PID_F=/var/run/p910${port}d.pid
+ [ -f $PID_F ] && kill $(cat $PID_F)
+}
+
+start() {
+ config_load "p910nd"
+ config_foreach start_service p910nd
+}
+
+stop() {
+ config_load "p910nd"
+ config_foreach stop_service p910nd
+}
diff --git a/net/radsecproxy/Makefile b/net/radsecproxy/Makefile
new file mode 100644
index 000000000..b36503aa1
--- /dev/null
+++ b/net/radsecproxy/Makefile
@@ -0,0 +1,57 @@
+#
+# Copyright (C) 2008-2012 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:=radsecproxy
+PKG_VERSION:=1.6.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://software.uninett.no/radsecproxy/
+PKG_MD5SUM:=f74f82a7ae2cdf2b1d9d271a5c360617
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/radsecproxy
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+libopenssl +libpthread
+ TITLE:=radsecproxy
+ URL:=http://software.uninett.no/radsecproxy
+ MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
+endef
+
+define Package/radsecproxy/description
+ A generic radius proxy for UDP/TLS (RadSec)
+endef
+
+CONFIGURE_ARGS+= \
+ --with-ssl="$(STAGING_DIR)/usr"
+
+#TARGET_CFLAGS += -ansi
+#TARGET_CFLAGS += -std=c99
+TARGET_CFLAGS += -Wno-long-long
+
+
+define Package/radsecproxy/install
+ $(INSTALL_DIR) $(1)/usr/sbin/
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/radsecproxy $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/
+ $(CP) $(PKG_BUILD_DIR)/radsecproxy.conf-example $(1)/etc/radsecproxy.conf
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) ./files/radsecproxy.init $(1)/etc/init.d/radsecproxy
+endef
+
+define Package/radsecproxy/conffiles
+/etc/radsecproxy.conf
+endef
+
+$(eval $(call BuildPackage,radsecproxy))
+
diff --git a/net/radsecproxy/files/radsecproxy.init b/net/radsecproxy/files/radsecproxy.init
new file mode 100644
index 000000000..39bdc6e4b
--- /dev/null
+++ b/net/radsecproxy/files/radsecproxy.init
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2011 OpenWrt.org
+
+START=70
+
+USE_PROCD=1
+PROG=/usr/sbin/radsecproxy
+CONFFILE=/etc/radsecproxy.conf
+
+start_service() {
+ procd_open_instance
+ procd_set_param command $PROG -f -c $CONFFILE
+ procd_set_param file $CONFFILE
+ procd_set_param respawn
+ procd_close_instance
+}
diff --git a/net/radsecproxy/patches/100-missing-return.patch b/net/radsecproxy/patches/100-missing-return.patch
new file mode 100644
index 000000000..871fc6e10
--- /dev/null
+++ b/net/radsecproxy/patches/100-missing-return.patch
@@ -0,0 +1,58 @@
+--- a/dtls.c
++++ b/dtls.c
+@@ -523,6 +523,7 @@ void *udpdtlsserverrd(void *arg) {
+ free(params);
+ cacheexpire(sessioncache, &lastexpiry);
+ }
++ return NULL;
+ }
+
+ int dtlsconnect(struct server *server, struct timeval *when, int timeout, char *text) {
+@@ -642,6 +643,7 @@ void *udpdtlsclientrd(void *arg) {
+ if (udp2bio(s, conf->servers->rbios, cnt))
+ debug(DBG_DBG, "radudpget: got DTLS in UDP from %s", addr2string((struct sockaddr *)&from));
+ }
++ return NULL;
+ }
+
+ void *dtlsclientrd(void *arg) {
+--- a/radsecproxy.c
++++ b/radsecproxy.c
+@@ -3203,6 +3203,8 @@ void *sighandler(void *arg) {
+ debug(DBG_WARN, "sighandler: ignoring signal %d", sig);
+ }
+ }
++
++ return NULL;
+ }
+
+ int createpidfile(const char *pidfile) {
+@@ -3289,6 +3291,8 @@ int radsecproxy_main(int argc, char **ar
+ /* just hang around doing nothing, anything to do here? */
+ for (;;)
+ sleep(1000);
++
++ return 0;
+ }
+
+ /* Local Variables: */
+--- a/udp.c
++++ b/udp.c
+@@ -266,6 +266,8 @@ void *udpclientrd(void *arg) {
+ buf = radudpget(*s, NULL, &server, NULL);
+ replyh(server, buf);
+ }
++
++ return NULL;
+ }
+
+ void *udpserverrd(void *arg) {
+@@ -310,6 +312,8 @@ void *udpserverwr(void *arg) {
+ debug(DBG_DBG, "udpserverwr: refcount %d", reply->refcount);
+ freerq(reply);
+ }
++
++ return NULL;
+ }
+
+ void addclientudp(struct client *client) {
diff --git a/net/radsecproxy/patches/200-logdest-on-foreground.patch b/net/radsecproxy/patches/200-logdest-on-foreground.patch
new file mode 100644
index 000000000..6678448ac
--- /dev/null
+++ b/net/radsecproxy/patches/200-logdest-on-foreground.patch
@@ -0,0 +1,31 @@
+diff --git a/radsecproxy.c b/radsecproxy.c
+index 563c4a8..9fa076d 100644
+--- a/radsecproxy.c
++++ b/radsecproxy.c
+@@ -3382,18 +3382,16 @@ int radsecproxy_main(int argc, char **argv) {
+ options.loglevel = loglevel;
+ else if (options.loglevel)
+ debug_set_level(options.loglevel);
+- if (!foreground) {
+- debug_set_destination(options.logdestination
+- ? options.logdestination
+- : "x-syslog:///", LOG_TYPE_DEBUG);
++ debug_set_destination(options.logdestination
++ ? options.logdestination
++ : "x-syslog:///", LOG_TYPE_DEBUG);
+ #if defined(WANT_FTICKS)
+- if (options.ftickssyslogfacility) {
+- debug_set_destination(options.ftickssyslogfacility,
+- LOG_TYPE_FTICKS);
+- free(options.ftickssyslogfacility);
+- }
+-#endif
++ if (options.ftickssyslogfacility) {
++ debug_set_destination(options.ftickssyslogfacility,
++ LOG_TYPE_FTICKS);
++ free(options.ftickssyslogfacility);
+ }
++#endif
+ free(options.logdestination);
+
+ if (!list_first(clconfs))
diff --git a/net/rsync/Makefile b/net/rsync/Makefile
index e73aebca3..6d6d201b6 100644
--- a/net/rsync/Makefile
+++ b/net/rsync/Makefile
@@ -17,6 +17,7 @@ PKG_MD5SUM:=43bd6676f0b404326eee2d63be3cdcfe
PKG_LICENSE:=GPL-3.0
PKG_LICENSE_FILES:=COPYING
PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=GPL-3.0
PKG_INSTALL:=1
PKG_BUILD_PARALLEL:=1
diff --git a/net/sslh/Makefile b/net/sslh/Makefile
index a3a6cb4bd..043342fa7 100644
--- a/net/sslh/Makefile
+++ b/net/sslh/Makefile
@@ -13,7 +13,7 @@ PKG_RELEASE:=2
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=http://rutschle.net/tech/
-PKG_MD5SUM:=1e85b84eb82a96b81de9b1e637a3e795
+PKG_MD5SUM:=c6e7d1cb0adb15f6efe480e36d98c560
include $(INCLUDE_DIR)/package.mk
diff --git a/net/tgt/Makefile b/net/tgt/Makefile
index f94af51ac..8efa9e72a 100644
--- a/net/tgt/Makefile
+++ b/net/tgt/Makefile
@@ -18,6 +18,7 @@ PKG_SOURCE_VERSION:=$(PKG_REV)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_REV).tar.gz
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=GPL-2.0
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_SOURCE_SUBDIR)
diff --git a/net/tinc/Makefile b/net/tinc/Makefile
new file mode 100644
index 000000000..dc1bbbb7b
--- /dev/null
+++ b/net/tinc/Makefile
@@ -0,0 +1,60 @@
+#
+# Copyright (C) 2007-2013 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:=tinc
+PKG_VERSION:=1.0.24
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.tinc-vpn.org/packages
+PKG_MD5SUM:=14a91eb2e85bdc0451a815612521b708
+
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/tinc
+ SECTION:=net
+ CATEGORY:=Network
+ DEPENDS:=+liblzo +libopenssl +kmod-tun
+ TITLE:=VPN tunneling daemon
+ URL:=http://www.tinc-vpn.org/
+ MAINTAINER:=Toke Høiland-Jørgensen <toke@toke.dk>
+ SUBMENU:=VPN
+endef
+
+define Package/tinc/description
+ tinc is a Virtual Private Network (VPN) daemon that uses tunnelling and
+ encryption to create a secure private network between hosts on the Internet.
+endef
+
+TARGET_CFLAGS += -std=gnu99
+
+CONFIGURE_ARGS += \
+ --with-kernel="$(LINUX_DIR)" \
+ --with-zlib="$(STAGING_DIR)/usr" \
+ --with-lzo-include="$(STAGING_DIR)/usr/include/lzo"
+
+define Package/tinc/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/tincd $(1)/usr/sbin/
+ $(INSTALL_DIR) $(1)/etc/init.d/
+ $(INSTALL_BIN) files/$(PKG_NAME).init $(1)/etc/init.d/$(PKG_NAME)
+ $(INSTALL_DIR) $(1)/etc/config
+ $(INSTALL_CONF) files/$(PKG_NAME).config $(1)/etc/config/$(PKG_NAME)
+ $(INSTALL_DIR) $(1)/etc/tinc
+ $(INSTALL_DIR) $(1)/lib/upgrade/keep.d
+ $(INSTALL_DATA) files/tinc.upgrade $(1)/lib/upgrade/keep.d/tinc
+endef
+
+define Package/tinc/conffiles
+/etc/config/tinc
+endef
+
+$(eval $(call BuildPackage,tinc))
diff --git a/net/tinc/files/tinc.config b/net/tinc/files/tinc.config
new file mode 100644
index 000000000..18940781a
--- /dev/null
+++ b/net/tinc/files/tinc.config
@@ -0,0 +1,56 @@
+config tinc-net NETNAME
+ option enabled 0
+
+ ## Daemon Configuration (cmd arguments)
+ #option generate_keys 0
+ #option key_size 2048
+ #option logfile /tmp/log/tinc.NETNAME.log
+ #option debug 3
+
+ ## Server Configuration (tinc.conf)
+ #option AddressFamily any
+ #option BindToAddress 127.0.0.1
+ #option BindToInterface lo
+
+ #list ConnectTo peer1
+
+ #option DirectOnly 0
+ #option Forwarding internal
+ #option GraphDumpFile /tmp/log/tinc.NETNAME.dot
+ #option Hostnames 0
+ #option IffOneQueue 0
+ #option Interface NETNAME
+ #option KeyExpire 3600
+ #option MACExpire 600
+ #option MaxTimeout 900
+ #option Mode router
+
+ option Name NODENAME
+
+ #option PingInterval 60
+ #option PingTimeout 5
+ #option PriorityInheritance 0
+ #option PrivateKeyFile /etc/tinc/NETNAME/rsa_key.priv
+ #option ProcessPriority normal
+ #option ReplayWindow 16
+ #option StrictSubnets 0
+ #option TunnelServer 0
+ #option UDPRcvBuf x
+ #option UDPSndBuf x
+
+config tinc-host NODENAME
+ option enabled 0
+
+ option net NETNAME
+
+ #list Address example.com
+ #option Cipher blowfish
+ #option ClampMSS yes
+ #option Compression 0
+ #option Digest sha1
+ #option IndirectData 0
+ #option MACLength 4
+ #option PMTU 1514
+ #option PMTUDiscovery yes
+ #option Port 655
+ #option Subnet 192.168.1.0/24
diff --git a/net/tinc/files/tinc.init b/net/tinc/files/tinc.init
new file mode 100644
index 000000000..b24bc682e
--- /dev/null
+++ b/net/tinc/files/tinc.init
@@ -0,0 +1,241 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2011 OpenWrt.org
+# Copyright (C) 2011 Linus Lüssing
+# Based on Jo-Philipp Wich's OpenVPN init script
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+
+START=42
+
+SERVICE_USE_PID=1
+
+BIN=/usr/sbin/tincd
+EXTRA_COMMANDS="up down"
+
+LIST_SEP="
+"
+TMP_TINC="/tmp/tinc"
+
+append_param() {
+ local v="$1"
+ case "$v" in
+ *_*_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;;
+ *_*_*) v=${v%%_*}-${v#*_}; v=${v%%_*}-${v#*_} ;;
+ *_*) v=${v%%_*}-${v#*_} ;;
+ esac
+ ARGS="$ARGS --$v"
+ return 0
+}
+
+append_conf_bools() {
+ local p; local v; local s="$1"; local f="$2"; shift; shift
+ for p in $*; do
+ config_get_bool v "$s" "$p"
+ [ "$v" == 1 ] && echo "$p = yes" >> "$f"
+ [ "$v" == 0 ] && echo "$p = no" >> "$f"
+ done
+}
+
+append_params() {
+ local p; local v; local s="$1"; shift
+ for p in $*; do
+ config_get v "$s" "$p"
+ IFS="$LIST_SEP"
+ for v in $v; do
+ [ -n "$v" ] && append_param "$p" && ARGS="$ARGS=$v"
+ done
+ unset IFS
+ done
+}
+
+append_conf_params() {
+ local p; local v; local s="$1"; local f="$2"; shift; shift
+ for p in $*; do
+ config_get v "$s" "$p"
+ IFS="$LIST_SEP"
+ for v in $v; do
+ # Look up OpenWRT interface names
+ [ "$p" = "BindToInterface" ] && {
+ local ifname=$(uci -P /var/state get network.$v.ifname 2>&-)
+ [ -n "$ifname" ] && v="$ifname"
+ }
+
+ [ -n "$v" ] && echo "$p = $v" >> "$f"
+ done
+ unset IFS
+ done
+}
+
+section_enabled() {
+ config_get_bool enabled "$1" 'enabled' 0
+ [ $enabled -gt 0 ]
+}
+
+prepare_host() {
+ local s="$1"
+ local n
+
+ # net disabled?
+ config_get n "$s" net
+ section_enabled "$n" || return 1
+
+ if [ "$#" = "2" ]; then
+ [ "$2" != "$n" ] && return 1
+ fi
+
+ # host disabled?
+ section_enabled "$s" || {
+ [ -f "$TMP_TINC/$n/hosts/$s" ] && rm "$TMP_TINC/$n/hosts/$s"
+ return 1
+ }
+
+ [ ! -f "/etc/tinc/$n/hosts/$s" ] && {
+ echo -n "tinc: Warning, public key for $s for network $n "
+ echo -n "missing in /etc/tinc/$n/hosts/$s, "
+ echo "skipping configuration of $s"
+ return 1
+ }
+
+ # append flags
+ append_conf_bools "$s" "$TMP_TINC/$n/hosts/$s" \
+ ClampMSS IndirectData PMTUDiscovery TCPOnly
+
+ # append params
+ append_conf_params "$s" "$TMP_TINC/$n/hosts/$s" \
+ Address Cipher Compression Digest MACLength PMTU \
+ Port PublicKey PublicKeyFile Subnet
+}
+
+check_gen_own_key() {
+ local s="$1"; local n; local k
+
+ config_get n "$s" Name
+ config_get_bool k "$s" generate_keys 0
+ [ "$k" == 0 ] && return 0
+
+ ([ -z "$n" ] || [ -f "$TMP_TINC/$s/hosts/$n" ] || [ -f "$TMP_TINC/$s/rsa_key.priv" ]) && \
+ return 0
+ [ ! -d "$TMP_TINC/$s/hosts" ] && mkdir -p "$TMP_TINC/$s/hosts"
+
+ config_get k "$s" key_size
+ if [ -z "$k" ]; then
+ $BIN -c "$TMP_TINC/$s" --generate-keys </dev/null
+ else
+ $BIN -c "$TMP_TINC/$s" "--generate-keys=$k" </dev/null
+ fi
+
+ [ ! -d "/etc/tinc/$s/hosts" ] && mkdir -p "/etc/tinc/$s/hosts"
+ cp "$TMP_TINC/$s/rsa_key.priv" "/etc/tinc/$s/"
+ [ -n "$n" ] && cp "$TMP_TINC/$s/hosts/$n" "/etc/tinc/$s/hosts/"
+}
+
+prepare_net() {
+ local s="$1"
+ local n
+
+ section_enabled "$s" || return 1
+
+ # rm old config
+ rm -rf "$TMP_TINC/$s/"
+
+ [ ! -d "$TMP_TINC/$s" ] && mkdir -p "$TMP_TINC/$s"
+ [ -d "/etc/tinc/$s" ] && cp -r "/etc/tinc/$s" "$TMP_TINC/"
+
+ # append flags
+ append_conf_bools "$s" "$TMP_TINC/$s/tinc.conf" \
+ DecrementTTL DirectOnly Hostnames IffOneQueue \
+ LocalDiscovery PriorityInheritance StrictSubnets TunnelServer \
+ ClampMSS IndirectData PMTUDiscovery TCPOnly
+
+ # append params
+ append_conf_params "$s" "$TMP_TINC/$s/tinc.conf" \
+ AddressFamily BindToAddress ConnectTo BindToInterface \
+ Broadcast Device DeviceType Forwarding \
+ GraphDumpFile Interface KeyExpire MACExpire \
+ MaxTimeout Mode Name PingInterval PingTimeout \
+ PrivateKey PrivateKeyFile ProcessPriority ReplayWindow \
+ UDPRcvBuf UDPSndBuf \
+ Address Cipher Compression Digest MACLength PMTU \
+ Port PublicKey PublicKeyFile Subnet
+
+ check_gen_own_key "$s" && return 0
+}
+
+start_instance() {
+ local s="$1"
+
+ section_enabled "$s" || return 1
+
+ ARGS=""
+
+ # append params
+ append_params "$s" logfile debug
+
+ SERVICE_PID_FILE="/var/run/tinc.$s.pid"
+ service_start $BIN -c "$TMP_TINC/$s" -n $s $ARGS --pidfile="$SERVICE_PID_FILE"
+}
+
+stop_instance() {
+ local s="$1"
+
+ section_enabled "$s" || return 1
+
+ SERVICE_PID_FILE="/var/run/tinc.$s.pid"
+ service_stop $BIN
+ # rm old config
+ rm -rf "$TMP_TINC/$s/"
+}
+
+reload_instance() {
+ local s="$1"
+
+ section_enabled "$s" || return 1
+
+ SERVICE_PID_FILE="/var/run/tinc.$s.pid"
+ service_reload $BIN
+}
+
+start() {
+ config_load 'tinc'
+
+ config_foreach prepare_net 'tinc-net'
+ config_foreach prepare_host 'tinc-host'
+
+ config_foreach start_instance 'tinc-net'
+}
+
+stop() {
+ config_load 'tinc'
+ config_foreach stop_instance 'tinc-net'
+}
+
+reload() {
+ config_load 'tinc'
+ config_foreach reload_instance 'tinc-net'
+}
+
+up() {
+ local exists
+ local instance
+ config_load 'tinc'
+ for instance in "$@"; do
+ config_get exists "$instance" 'TYPE'
+ if [ "$exists" == "tinc-net" ]; then
+ prepare_net "$instance"
+ config_foreach prepare_host 'tinc-host' "$instance"
+ start_instance "$instance"
+ fi
+ done
+}
+
+down() {
+ local exists
+ local instance
+ config_load 'tinc'
+ for instance in "$@"; do
+ config_get exists "$instance" 'TYPE'
+ if [ "$exists" == "tinc-net" ]; then
+ stop_instance "$instance"
+ fi
+ done
+}
diff --git a/net/tinc/files/tinc.upgrade b/net/tinc/files/tinc.upgrade
new file mode 100644
index 000000000..13f5d8049
--- /dev/null
+++ b/net/tinc/files/tinc.upgrade
@@ -0,0 +1 @@
+/etc/tinc/
diff --git a/net/vsftpd/Makefile b/net/vsftpd/Makefile
index e1a4de017..a5c55ad06 100644
--- a/net/vsftpd/Makefile
+++ b/net/vsftpd/Makefile
@@ -14,6 +14,7 @@ PKG_RELEASE:=4
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://security.appspot.com/downloads/
PKG_MD5SUM:=8b00c749719089401315bd3c44dddbb2
+PKG_LICENSE:=GPLv2
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)
diff --git a/net/wget/Makefile b/net/wget/Makefile
index a791c06dd..c03dffcb3 100644
--- a/net/wget/Makefile
+++ b/net/wget/Makefile
@@ -15,6 +15,7 @@ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@GNU/$(PKG_NAME)
PKG_MD5SUM:=7a279d5ac5594919124d5526e7143e28
PKG_MAINTAINER:=Maxim Storchak <m.storchak@gmail.com>
+PKG_LICENSE:=GPL-3.0+
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(BUILD_VARIANT)/$(PKG_NAME)-$(PKG_VERSION)