diff --git a/.gitignore b/.gitignore index 2b6cabec..ab2b03cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ *~ -/build +/lede /output /site -/openwrt +/tmp /packages -/modules.local diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 824362d7..1c827fb2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -46,24 +46,8 @@ fix some bug, detail in the remaining commit message exactly how it could be triggered and what you did to fix it. If in question, have a glance at the existing commit messages to get the idea. -Squash commits --------------- -Most changes are trivial enough to fit in one single commit in order to not -clutter the history. While developing a new feature, you are free to use -multiple commits, but if your feature is to be merged, reduce the number of -commits to a minimum. Even huge feature introductions like the 802.11s mesh -(commit [2a93c58]) fit into a single commit. - -If you developed your change in multiple smaller commits, you can easily -[squash] those before opening the pull request. While discussing, it is okay to -do your changes using `git commit --amend` and force-push them to your head of -the pull request. This way, your change always consists of only one commit and -can be merged in the instant everybody is content with the whole thing. - [packages]: http://gluon.readthedocs.org/en/latest/user/site.html#packages [#gluon]: https://webirc.hackint.org/#gluon [mailing list]: mailto:gluon@luebeck.freifunk.net [list of rejected features]: https://github.com/freifunk-gluon/gluon/issues?q=label%3Arejected -[2a93c58]: https://github.com/freifunk-gluon/gluon/commit/2a93c580428d10724116b0d2d1238e2745715a14 -[squash]: https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Squashing-Commits diff --git a/LICENSE b/LICENSE index 81ed5a23..a9adc369 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ The code of Project Gluon may be distributed under the following terms, unless noted otherwise in individual files or subtrees. -Copyright (c) 2013, Project Gluon +Copyright (c) 2013-2017, Project Gluon All rights reserved. Redistribution and use in source and binary forms, with or without @@ -25,10 +25,10 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -OpenWrt is licensed under the terms of the GNU General Public License Version 2, -which can be found under openwrt/LICENSE after the openwrt submodule has been -obtained. This applies to the following submodules: - * openwrt +LEDE and OpenWrt are licensed under the terms of the GNU General Public License +Version 2, which can be found at lede/LICENSE after the lede repository has been +obtained. This applies to the following repositories: + * lede * packages/openwrt * packages/routing * packages/luci diff --git a/Makefile b/Makefile index 90ea36f3..9593fd91 100644 --- a/Makefile +++ b/Makefile @@ -4,489 +4,180 @@ LC_ALL:=C LANG:=C export LC_ALL LANG -export SHELL:=/usr/bin/env bash -GLUONPATH ?= $(PATH) -export GLUONPATH := $(GLUONPATH) +# initialize (possibly already user set) directory variables +GLUON_SITEDIR ?= site +GLUON_TMPDIR ?= tmp +GLUON_OUTPUTDIR ?= output -empty:= -space:= $(empty) $(empty) +GLUON_IMAGEDIR ?= $(GLUON_OUTPUTDIR)/images +GLUON_PACKAGEDIR ?= $(GLUON_OUTPUTDIR)/packages -GLUONMAKE_EARLY = PATH=$(GLUONPATH) $(SUBMAKE) -C $(GLUON_ORIGOPENWRTDIR) -f $(GLUONDIR)/Makefile GLUON_TOOLS=0 QUILT= -GLUONMAKE = PATH=$(GLUONPATH) $(SUBMAKE) -C $(GLUON_OPENWRTDIR) -f $(GLUONDIR)/Makefile +# check for spaces & resolve possibly relative paths +define mkabspath + ifneq (1,$(words [$($(1))])) + $$(error $(1) must not contain spaces) + endif + override $(1) := $(abspath $($(1))) +endef -ifneq ($(OPENWRT_BUILD),1) +$(eval $(call mkabspath,GLUON_SITEDIR)) +$(eval $(call mkabspath,GLUON_TMPDIR)) +$(eval $(call mkabspath,GLUON_OUTPUTDIR)) +$(eval $(call mkabspath,GLUON_IMAGEDIR)) +$(eval $(call mkabspath,GLUON_PACKAGEDIR)) -GLUONDIR:=${CURDIR} +export GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR DEVICES -include $(GLUONDIR)/include/gluon.mk -TOPDIR:=$(GLUON_ORIGOPENWRTDIR) -export TOPDIR +$(GLUON_SITEDIR)/site.mk: + $(error No site configuration was found. Please check out a site configuration to $(GLUON_SITEDIR)) + +include $(GLUON_SITEDIR)/site.mk + +GLUON_RELEASE ?= $(error GLUON_RELEASE not set. GLUON_RELEASE can be set in site.mk or on the command line) + +GLUON_MULTIDOMAIN ?= 0 +GLUON_WLAN_MESH ?= 11s +GLUON_DEBUG ?= 0 + +export GLUON_RELEASE GLUON_REGION GLUON_MULTIDOMAIN GLUON_WLAN_MESH GLUON_DEBUG + +show-release: + @echo '$(GLUON_RELEASE)' update: FORCE - $(GLUONDIR)/scripts/update.sh - $(GLUONDIR)/scripts/patch.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/patch.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/feeds.sh update-patches: FORCE - $(GLUONDIR)/scripts/update.sh - $(GLUONDIR)/scripts/update-patches.sh - $(GLUONDIR)/scripts/patch.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/update-patches.sh + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/patch.sh --include $(TOPDIR)/include/host.mk - -_SINGLE=export MAKEFLAGS=$(space); - -override OPENWRT_BUILD=1 -override GLUON_TOOLS=1 -GREP_OPTIONS= -export OPENWRT_BUILD GLUON_TOOLS GREP_OPTIONS - --include $(TOPDIR)/include/debug.mk --include $(TOPDIR)/include/depends.mk -include $(GLUONDIR)/include/toplevel.mk +update-feeds: FORCE + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/feeds.sh -include $(GLUONDIR)/targets/targets.mk +GLUON_TARGETS := + +define GluonTarget +gluon_target := $(1)$$(if $(2),-$(2)) +GLUON_TARGETS += $$(gluon_target) +GLUON_TARGET_$$(gluon_target)_BOARD := $(1) +GLUON_TARGET_$$(gluon_target)_SUBTARGET := $(if $(3),$(3),$(2)) +endef + +include targets/targets.mk -CheckTarget := [ -n '$(GLUON_TARGET)' -a -n '$(GLUON_TARGET_$(GLUON_TARGET)_BOARD)' ] \ - || (echo -e 'Please set GLUON_TARGET to a valid target. Gluon supports the following targets:$(subst $(space),\n * ,$(GLUON_TARGETS))'; false) +LEDEMAKE = $(MAKE) -C lede + +BOARD := $(GLUON_TARGET_$(GLUON_TARGET)_BOARD) +SUBTARGET := $(GLUON_TARGET_$(GLUON_TARGET)_SUBTARGET) + +GLUON_CONFIG_VARS := \ + GLUON_SITEDIR='$(GLUON_SITEDIR)' \ + GLUON_RELEASE='$(GLUON_RELEASE)' \ + GLUON_BRANCH='$(GLUON_BRANCH)' \ + GLUON_LANGS='$(GLUON_LANGS)' \ + BOARD='$(BOARD)' \ + SUBTARGET='$(SUBTARGET)' + +LEDE_TARGET := $(BOARD)$(if $(SUBTARGET),-$(SUBTARGET)) + +export LEDE_TARGET -CheckExternal := test -d $(GLUON_ORIGOPENWRTDIR) || (echo 'You don'"'"'t seem to have obtained the external repositories needed by Gluon; please call `make update` first!'; false) +CheckTarget := [ '$(LEDE_TARGET)' ] \ + || (echo 'Please set GLUON_TARGET to a valid target. Gluon supports the following targets:'; $(foreach target,$(GLUON_TARGETS),echo ' * $(target)';) false) + +CheckExternal := test -d lede || (echo 'You don'"'"'t seem to have obtained the external repositories needed by Gluon; please call `make update` first!'; false) + +define CheckSite + @GLUON_SITEDIR='$(GLUON_SITEDIR)' GLUON_SITE_CONFIG='$(1).conf' $(LUA) scripts/site_config.lua \ + || (echo 'Your site configuration ($(1).conf) did not pass validation.'; false) + +endef + +list-targets: FORCE + @$(foreach target,$(GLUON_TARGETS),echo '$(target)';) -create-key: FORCE - @$(CheckExternal) - +@$(GLUONMAKE_EARLY) create-key +GLUON_FEATURE_PACKAGES := $(shell scripts/features.sh '$(GLUON_FEATURES)' || echo '__ERROR__') +ifneq ($(filter __ERROR__,$(GLUON_FEATURE_PACKAGES)),) +$(error Error while evaluating GLUON_FEATURES) +endif -prepare-target: FORCE + +GLUON_PACKAGES := +define merge_packages + $(foreach pkg,$(1), + GLUON_PACKAGES := $$(strip $$(filter-out -$$(patsubst -%,%,$(pkg)) $$(patsubst -%,%,$(pkg)),$$(GLUON_PACKAGES)) $(pkg)) + ) +endef +$(eval $(call merge_packages,$(GLUON_FEATURE_PACKAGES) $(GLUON_SITE_PACKAGES))) + +config: FORCE @$(CheckExternal) @$(CheckTarget) - +@$(GLUONMAKE_EARLY) prepare-target + + @$(GLUON_CONFIG_VARS) \ + scripts/target_config.sh '$(GLUON_TARGET)' '$(GLUON_PACKAGES)' \ + > lede/.config + +@$(LEDEMAKE) defconfig + + @$(GLUON_CONFIG_VARS) \ + scripts/target_config_check.sh '$(GLUON_TARGET)' '$(GLUON_PACKAGES)' + + +LUA := lede/staging_dir/hostpkg/bin/lua + +$(LUA): + @$(CheckExternal) + + +@[ -e lede/.config ] || $(LEDEMAKE) defconfig + +@$(LEDEMAKE) tools/install + +@$(LEDEMAKE) package/lua/host/install + +prepare-target: config $(LUA) ; all: prepare-target - +@$(GLUONMAKE) build-key - +@$(GLUONMAKE) prepare - +@$(GLUONMAKE) images - +@$(GLUONMAKE) modules + $(foreach conf,site $(patsubst $(GLUON_SITEDIR)/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)),$(call CheckSite,$(conf))) -prepare: prepare-target - +@$(GLUONMAKE) build-key - +@$(GLUONMAKE) $@ + @scripts/clean_output.sh + +@$(LEDEMAKE) + @GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/copy_output.sh '$(GLUON_TARGET)' -clean download images modules: FORCE - @$(CheckExternal) - @$(CheckTarget) - +@$(GLUONMAKE_EARLY) maybe-prepare-target - +@$(GLUONMAKE) build-key - +@$(GLUONMAKE) $@ +clean download: config + +@$(LEDEMAKE) $@ -toolchain/% package/% target/% image/%: FORCE - @$(CheckExternal) - @$(CheckTarget) - +@$(GLUONMAKE_EARLY) maybe-prepare-target - +@$(GLUONMAKE) build-key - +@$(GLUONMAKE) $@ +dirclean: FORCE + +@[ -e lede/.config ] || $(LEDEMAKE) defconfig + +@$(LEDEMAKE) dirclean + @rm -rf $(GLUON_TMPDIR) $(GLUON_OUTPUTDIR) -manifest: FORCE - @[ -n '$(GLUON_BRANCH)' ] || (echo 'Please set GLUON_BRANCH to create a manifest.'; false) +manifest: $(LUA) FORCE + @[ '$(GLUON_BRANCH)' ] || (echo 'Please set GLUON_BRANCH to create a manifest.'; false) @echo '$(GLUON_PRIORITY)' | grep -qE '^([0-9]*\.)?[0-9]+$$' || (echo 'Please specify a numeric value for GLUON_PRIORITY to create a manifest.'; false) @$(CheckExternal) - ( \ + @( \ echo 'BRANCH=$(GLUON_BRANCH)' && \ - echo 'DATE=$(shell $(GLUON_ORIGOPENWRTDIR)/staging_dir/host/bin/lua $(GLUONDIR)/scripts/rfc3339date.lua)' && \ + echo "DATE=$$($(LUA) scripts/rfc3339date.lua)" && \ echo 'PRIORITY=$(GLUON_PRIORITY)' && \ - echo \ - ) > $(GLUON_BUILDDIR)/$(GLUON_BRANCH).manifest.tmp - - +($(foreach GLUON_TARGET,$(GLUON_TARGETS), \ - ( [ ! -e $(BOARD_BUILDDIR)/prepared ] || ( $(GLUONMAKE) manifest GLUON_TARGET='$(GLUON_TARGET)' V=s$(OPENWRT_VERBOSE) ) ) && \ - ) :) - - mkdir -p $(GLUON_IMAGEDIR)/sysupgrade - mv $(GLUON_BUILDDIR)/$(GLUON_BRANCH).manifest.tmp $(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_BRANCH).manifest - -dirclean : FORCE - for dir in build_dir dl staging_dir tmp; do \ - rm -rf $(GLUON_ORIGOPENWRTDIR)/$$dir; \ - done - rm -rf $(GLUON_BUILDDIR) $(GLUON_OUTPUTDIR) - -else - -TOPDIR=${CURDIR} -export TOPDIR - -include rules.mk - -include $(GLUONDIR)/include/gluon.mk - -include $(INCLUDE_DIR)/host.mk -include $(INCLUDE_DIR)/depends.mk -include $(INCLUDE_DIR)/subdir.mk - -include package/Makefile -include tools/Makefile -include toolchain/Makefile -include target/Makefile - - -PROFILES := -PROFILE_PACKAGES := - -define Profile - $(eval $(call Profile/Default)) - $(eval $(call Profile/$(1))) -endef - -define GluonProfile -PROFILES += $(1) -PROFILE_PACKAGES += $(filter-out -%,$(2) $(GLUON_$(1)_SITE_PACKAGES)) -GLUON_$(1)_PROFILE := $(if $(3),$(3),$(1)) -GLUON_$(1)_DEFAULT_PACKAGES := $(2) -GLUON_$(1)_FACTORY_SUFFIX := -squashfs-factory -GLUON_$(1)_SYSUPGRADE_SUFFIX := -squashfs-sysupgrade -GLUON_$(1)_FACTORY_EXT := .bin -GLUON_$(1)_SYSUPGRADE_EXT := .bin -GLUON_$(1)_MODELS := -endef - -define GluonProfileFactorySuffix -GLUON_$(1)_FACTORY_SUFFIX := $(2) -GLUON_$(1)_FACTORY_EXT := $(3) -endef - -define GluonProfileSysupgradeSuffix -GLUON_$(1)_SYSUPGRADE_SUFFIX := $(2) -GLUON_$(1)_SYSUPGRADE_EXT := $(3) -endef - -define GluonModel -GLUON_$(1)_MODELS += $(3) -GLUON_$(1)_MODEL_$(3) := $(2) -GLUON_$(1)_MODEL_$(3)_ALIASES := -endef - -define GluonModelAlias -GLUON_$(1)_MODEL_$(2)_ALIASES += $(3) -endef - - -export SHA512SUM := $(GLUONDIR)/scripts/sha512sum.sh - - -prereq: FORCE - +$(NO_TRACE_MAKE) prereq - -prepare-tmpinfo: FORCE - @+$(MAKE) -r -s staging_dir/host/.prereq-build OPENWRT_BUILD= QUIET=0 - mkdir -p tmp/info - $(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET="packageinfo" SCAN_DIR="package" SCAN_NAME="package" SCAN_DEPS="$(TOPDIR)/include/package*.mk $(TOPDIR)/overlay/*/*.mk" SCAN_EXTRA="" - $(_SINGLE)$(NO_TRACE_MAKE) -j1 -r -s -f include/scan.mk SCAN_TARGET="targetinfo" SCAN_DIR="target/linux" SCAN_NAME="target" SCAN_DEPS="profiles/*.mk $(TOPDIR)/include/kernel*.mk $(TOPDIR)/include/target.mk" SCAN_DEPTH=2 SCAN_EXTRA="" SCAN_MAKEOPTS="TARGET_BUILD=1" - for type in package target; do \ - f=tmp/.$${type}info; t=tmp/.config-$${type}.in; \ - [ "$$t" -nt "$$f" ] || ./scripts/metadata.pl $${type}_config "$$f" > "$$t" || { rm -f "$$t"; echo "Failed to build $$t"; false; break; }; \ - done - [ tmp/.config-feeds.in -nt tmp/.packagefeeds ] || ./scripts/feeds feed_config > tmp/.config-feeds.in - ./scripts/metadata.pl package_mk tmp/.packageinfo > tmp/.packagedeps || { rm -f tmp/.packagedeps; false; } - ./scripts/metadata.pl package_feeds tmp/.packageinfo > tmp/.packagefeeds || { rm -f tmp/.packagefeeds; false; } - touch $(TOPDIR)/tmp/.build - -feeds: FORCE - rm -rf $(TOPDIR)/package/feeds - mkdir $(TOPDIR)/package/feeds - [ ! -f $(GLUON_SITEDIR)/modules ] || . $(GLUON_SITEDIR)/modules && for feed in $$GLUON_SITE_FEEDS; do ln -s ../../../packages/$$feed $(TOPDIR)/package/feeds/$$feed; done - ln -s ../../../package $(TOPDIR)/package/feeds/gluon - . $(GLUONDIR)/modules && for feed in $$GLUON_FEEDS; do ln -s ../../../packages/$$feed $(TOPDIR)/package/feeds/module_$$feed; done - +$(GLUONMAKE_EARLY) prepare-tmpinfo - -gluon-tools: FORCE - +$(GLUONMAKE_EARLY) tools/patch/install - +$(GLUONMAKE_EARLY) tools/sed/install - +$(GLUONMAKE_EARLY) tools/cmake/install - +$(GLUONMAKE_EARLY) package/lua/host/install package/usign/host/install - - - -early_prepared_stamp := $(GLUON_BUILDDIR)/prepared_$(shell \ - ( \ - $(SHA512SUM) $(GLUONDIR)/modules; \ - [ ! -r $(GLUON_SITEDIR)/modules ] || $(SHA512SUM) $(GLUON_SITEDIR)/modules \ - ) | $(SHA512SUM) ) - -prepare-early: FORCE - for dir in build_dir dl staging_dir; do \ - mkdir -p $(GLUON_ORIGOPENWRTDIR)/$$dir; \ - done - - +$(GLUONMAKE_EARLY) feeds - +$(GLUONMAKE_EARLY) gluon-tools - - mkdir -p $$(dirname $(early_prepared_stamp)) - touch $(early_prepared_stamp) - -$(early_prepared_stamp): - rm -f $(GLUON_BUILDDIR)/prepared_* - +$(GLUONMAKE_EARLY) prepare-early - -$(GLUON_OPKG_KEY): $(early_prepared_stamp) FORCE - [ -s $(GLUON_OPKG_KEY) -a -s $(GLUON_OPKG_KEY).pub ] || \ - ( mkdir -p $$(dirname $(GLUON_OPKG_KEY)) && $(STAGING_DIR_HOST)/bin/usign -G -s $(GLUON_OPKG_KEY) -p $(GLUON_OPKG_KEY).pub -c "Gluon opkg key" ) - -$(GLUON_OPKG_KEY).pub: $(GLUON_OPKG_KEY) - -create-key: $(GLUON_OPKG_KEY).pub - -include $(GLUONDIR)/targets/targets.mk - -ifneq ($(GLUON_TARGET),) - -include $(GLUONDIR)/targets/$(GLUON_TARGET)/profiles.mk - -BOARD := $(GLUON_TARGET_$(GLUON_TARGET)_BOARD) -override SUBTARGET := $(GLUON_TARGET_$(GLUON_TARGET)_SUBTARGET) - -target_prepared_stamp := $(BOARD_BUILDDIR)/target-prepared -gluon_prepared_stamp := $(BOARD_BUILDDIR)/prepared - -PREPARED_RELEASE = $$(cat $(gluon_prepared_stamp)) -IMAGE_PREFIX = gluon-$(GLUON_SITE_CODE)-$(PREPARED_RELEASE) -MODULE_PREFIX = gluon-$(GLUON_SITE_CODE)-$(PREPARED_RELEASE) - - -include $(INCLUDE_DIR)/target.mk - -build-key: FORCE - rm -f $(BUILD_KEY) $(BUILD_KEY).pub - cp $(GLUON_OPKG_KEY) $(BUILD_KEY) - cp $(GLUON_OPKG_KEY).pub $(BUILD_KEY).pub - -config: FORCE - +$(NO_TRACE_MAKE) scripts/config/conf OPENWRT_BUILD= QUIET=0 - +$(GLUONMAKE) prepare-tmpinfo - ( \ - cat $(GLUONDIR)/include/config; \ - echo 'CONFIG_TARGET_$(GLUON_TARGET_$(GLUON_TARGET)_BOARD)=y'; \ - $(if $(GLUON_TARGET_$(GLUON_TARGET)_SUBTARGET), \ - echo 'CONFIG_TARGET_$(GLUON_TARGET_$(GLUON_TARGET)_BOARD)_$(GLUON_TARGET_$(GLUON_TARGET)_SUBTARGET)=y'; \ - ) \ - cat $(GLUONDIR)/targets/$(GLUON_TARGET)/config 2>/dev/null; \ - echo 'CONFIG_BUILD_SUFFIX="gluon-$(GLUON_TARGET)"'; \ - echo '$(patsubst %,CONFIG_PACKAGE_%=m,$(sort $(filter-out -%,$(GLUON_DEFAULT_PACKAGES) $(GLUON_SITE_PACKAGES) $(PROFILE_PACKAGES))))' \ - | sed -e 's/ /\n/g'; \ - echo '$(patsubst %,CONFIG_LUCI_LANG_%=y,$(GLUON_LANGS))' \ - | sed -e 's/ /\n/g'; \ - ) > $(BOARD_BUILDDIR)/config.tmp - scripts/config/conf --defconfig=$(BOARD_BUILDDIR)/config.tmp Config.in - +$(SUBMAKE) tools/install - -prepare-target: $(GLUON_OPKG_KEY).pub - rm $(GLUON_OPENWRTDIR)/tmp || true - mkdir -p $(GLUON_OPENWRTDIR)/tmp - - for link in build_dir config Config.in dl include Makefile package rules.mk scripts staging_dir target toolchain tools; do \ - ln -sf $(GLUON_ORIGOPENWRTDIR)/$$link $(GLUON_OPENWRTDIR); \ - done - - +$(GLUONMAKE) config - touch $(target_prepared_stamp) - -$(target_prepared_stamp): - +$(GLUONMAKE_EARLY) prepare-target - -maybe-prepare-target: $(target_prepared_stamp) - +$(GLUONMAKE_EARLY) $(GLUON_OPKG_KEY).pub - -$(BUILD_DIR)/.prepared: Makefile - @mkdir -p $$(dirname $@) - @touch $@ - -$(toolchain/stamp-install): $(tools/stamp-install) -$(package/stamp-compile): $(package/stamp-cleanup) - - -clean: FORCE - +$(SUBMAKE) clean - rm -f $(gluon_prepared_stamp) - - -download: FORCE - +$(SUBMAKE) tools/download - +$(SUBMAKE) toolchain/download - +$(SUBMAKE) package/download - +$(SUBMAKE) target/download - -toolchain: $(toolchain/stamp-install) $(tools/stamp-install) - -include $(INCLUDE_DIR)/kernel.mk - -kernel: FORCE - +$(NO_TRACE_MAKE) -C $(TOPDIR)/target/linux/$(BOARD) $(LINUX_DIR)/.image TARGET_BUILD=1 - +$(NO_TRACE_MAKE) -C $(TOPDIR)/target/linux/$(BOARD) $(LINUX_DIR)/.modules TARGET_BUILD=1 - -packages: $(package/stamp-compile) - $(_SINGLE)$(SUBMAKE) -r package/index - -prepare-image: FORCE - rm -rf $(BOARD_KDIR) - mkdir -p $(BOARD_KDIR) - -cp $(KERNEL_BUILD_DIR)/* $(BOARD_KDIR)/ - +$(SUBMAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image image_prepare KDIR="$(BOARD_KDIR)" - -prepare: FORCE - @$(STAGING_DIR_HOST)/bin/lua $(GLUONDIR)/scripts/site_config.lua \ - || (echo 'Your site configuration did not pass validation.'; false) - - mkdir -p $(GLUON_IMAGEDIR) $(BOARD_BUILDDIR) - echo 'src packages file:../openwrt/bin/$(BOARD)/packages' > $(BOARD_BUILDDIR)/opkg.conf - - +$(GLUONMAKE) toolchain - +$(GLUONMAKE) kernel - +$(GLUONMAKE) packages - +$(GLUONMAKE) prepare-image - - echo "$(GLUON_RELEASE)" > $(gluon_prepared_stamp) - -$(gluon_prepared_stamp): - +$(GLUONMAKE) prepare - -modules: FORCE $(gluon_prepared_stamp) - -rm -f $(GLUON_MODULEDIR)/*/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic)/* - -rmdir -p $(GLUON_MODULEDIR)/*/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic) - mkdir -p $(GLUON_MODULEDIR)/$(MODULE_PREFIX)/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic) - cp $(PACKAGE_DIR)/kmod-*.ipk $(GLUON_MODULEDIR)/$(MODULE_PREFIX)/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic) - - $(_SINGLE)$(SUBMAKE) -r package/index PACKAGE_DIR=$(GLUON_MODULEDIR)/$(MODULE_PREFIX)/$(BOARD)/$(if $(SUBTARGET),$(SUBTARGET),generic) - - -include $(INCLUDE_DIR)/package-ipkg.mk - -# override variables from rules.mk -PACKAGE_DIR = $(GLUON_OPENWRTDIR)/bin/$(BOARD)/packages - -PROFILE_BUILDDIR = $(BOARD_BUILDDIR)/profiles/$(PROFILE) -PROFILE_KDIR = $(PROFILE_BUILDDIR)/kernel -BIN_DIR = $(PROFILE_BUILDDIR)/images - -TARGET_DIR = $(PROFILE_BUILDDIR)/root - -OPKG:= \ - IPKG_TMP="$(TMP_DIR)/ipkgtmp" \ - IPKG_INSTROOT="$(TARGET_DIR)" \ - IPKG_CONF_DIR="$(TMP_DIR)" \ - IPKG_OFFLINE_ROOT="$(TARGET_DIR)" \ - $(STAGING_DIR_HOST)/bin/opkg \ - -f $(BOARD_BUILDDIR)/opkg.conf \ - --cache $(TMP_DIR)/dl \ - --offline-root $(TARGET_DIR) \ - --force-postinstall \ - --add-dest root:/ \ - --add-arch all:100 \ - --add-arch $(ARCH_PACKAGES):200 - -EnableInitscript = ! grep -q '\#!/bin/sh /etc/rc.common' $(1) || bash ./etc/rc.common $(1) enable - - -enable_initscripts: FORCE - cd $(TARGET_DIR) && ( export IPKG_INSTROOT=$(TARGET_DIR); \ - $(foreach script,$(wildcard $(TARGET_DIR)/etc/init.d/*), \ - $(call EnableInitscript,$(script)); \ + echo && \ + $(foreach GLUON_TARGET,$(GLUON_TARGETS), \ + GLUON_SITEDIR='$(GLUON_SITEDIR)' scripts/generate_manifest.sh '$(GLUON_TARGET)' && \ ) : \ - ) + ) > 'tmp/$(GLUON_BRANCH).manifest.tmp' + @mkdir -p '$(GLUON_IMAGEDIR)/sysupgrade' + @mv 'tmp/$(GLUON_BRANCH).manifest.tmp' '$(GLUON_IMAGEDIR)/sysupgrade/$(GLUON_BRANCH).manifest' -# Generate package list -$(eval $(call merge-lists,INSTALL_PACKAGES,DEFAULT_PACKAGES GLUON_DEFAULT_PACKAGES GLUON_SITE_PACKAGES GLUON_$(PROFILE)_DEFAULT_PACKAGES GLUON_$(PROFILE)_SITE_PACKAGES)) +FORCE: ; -package_install: FORCE - $(OPKG) update - $(OPKG) install $(PACKAGE_DIR)/base-files_*.ipk $(PACKAGE_DIR)/libc_*.ipk - $(OPKG) install $(PACKAGE_DIR)/kernel_*.ipk - - $(OPKG) install $(INSTALL_PACKAGES) - +$(GLUONMAKE) enable_initscripts - - rm -f $(TARGET_DIR)/usr/lib/opkg/lists/* $(TARGET_DIR)/tmp/opkg.lock - -# Remove opkg database when opkg is not intalled - if [ ! -x $(TARGET_DIR)/bin/opkg ]; then rm -rf $(TARGET_DIR)/usr/lib/opkg; fi - - -include $(INCLUDE_DIR)/version.mk - -opkg_config: FORCE - for d in base packages luci routing telephony management; do \ - echo "src/gz %n_$$d %U/$$d"; \ - done > $(TARGET_DIR)/etc/opkg/distfeeds.conf - $(VERSION_SED) $(TARGET_DIR)/etc/opkg/distfeeds.conf - - -image: FORCE - rm -rf $(TARGET_DIR) $(BIN_DIR) $(PROFILE_KDIR) - mkdir -p $(TARGET_DIR) $(BIN_DIR) $(TARGET_DIR)/tmp $(GLUON_IMAGEDIR)/factory $(GLUON_IMAGEDIR)/sysupgrade - cp -r $(BOARD_KDIR) $(PROFILE_KDIR) - - +$(GLUONMAKE) package_install - +$(GLUONMAKE) opkg_config - - $(call Image/mkfs/prepare) - $(_SINGLE)$(NO_TRACE_MAKE) -C $(TOPDIR)/target/linux/$(BOARD)/image install TARGET_BUILD=1 IMG_PREFIX=gluon \ - PROFILE="$(GLUON_$(PROFILE)_PROFILE)" KDIR="$(PROFILE_KDIR)" TARGET_DIR="$(TARGET_DIR)" BIN_DIR="$(BIN_DIR)" TMP_DIR="$(TMP_DIR)" - - $(foreach model,$(GLUON_$(PROFILE)_MODELS), \ - $(if $(GLUON_$(PROFILE)_SYSUPGRADE_EXT), \ - rm -f $(GLUON_IMAGEDIR)/sysupgrade/gluon-*-$(model)-sysupgrade$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) && \ - cp $(BIN_DIR)/gluon-$(GLUON_$(PROFILE)_MODEL_$(model))$(GLUON_$(PROFILE)_SYSUPGRADE_SUFFIX)$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) $(GLUON_IMAGEDIR)/sysupgrade/$(IMAGE_PREFIX)-$(model)-sysupgrade$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) && \ - ) \ - $(if $(GLUON_$(PROFILE)_FACTORY_EXT), \ - rm -f $(GLUON_IMAGEDIR)/factory/gluon-*-$(model)$(GLUON_$(PROFILE)_FACTORY_EXT) && \ - cp $(BIN_DIR)/gluon-$(GLUON_$(PROFILE)_MODEL_$(model))$(GLUON_$(PROFILE)_FACTORY_SUFFIX)$(GLUON_$(PROFILE)_FACTORY_EXT) $(GLUON_IMAGEDIR)/factory/$(IMAGE_PREFIX)-$(model)$(GLUON_$(PROFILE)_FACTORY_EXT) && \ - ) \ - \ - $(foreach alias,$(GLUON_$(PROFILE)_MODEL_$(model)_ALIASES), \ - $(if $(GLUON_$(PROFILE)_SYSUPGRADE_EXT), \ - rm -f $(GLUON_IMAGEDIR)/sysupgrade/gluon-*-$(alias)-sysupgrade$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) && \ - ln -s $(IMAGE_PREFIX)-$(model)-sysupgrade$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) $(GLUON_IMAGEDIR)/sysupgrade/$(IMAGE_PREFIX)-$(alias)-sysupgrade$(GLUON_$(PROFILE)_SYSUPGRADE_EXT) && \ - ) \ - $(if $(GLUON_$(PROFILE)_FACTORY_EXT), \ - rm -f $(GLUON_IMAGEDIR)/factory/gluon-*-$(alias)$(GLUON_$(PROFILE)_FACTORY_EXT) && \ - ln -s $(IMAGE_PREFIX)-$(model)$(GLUON_$(PROFILE)_FACTORY_EXT) $(GLUON_IMAGEDIR)/factory/$(IMAGE_PREFIX)-$(alias)$(GLUON_$(PROFILE)_FACTORY_EXT) && \ - ) \ - ) \ - ) : - - -image/%: $(gluon_prepared_stamp) - +$(GLUONMAKE) image PROFILE="$(patsubst image/%,%,$@)" V=s$(OPENWRT_VERBOSE) - -call_image/%: FORCE - +$(GLUONMAKE) $(patsubst call_image/%,image/%,$@) - -images: $(patsubst %,call_image/%,$(PROFILES)) ; - -manifest: FORCE - ( \ - cd $(GLUON_IMAGEDIR)/sysupgrade; \ - $(foreach profile,$(PROFILES), \ - $(if $(GLUON_$(profile)_SYSUPGRADE_EXT), \ - $(foreach model,$(GLUON_$(profile)_MODELS), \ - file="$(IMAGE_PREFIX)-$(model)-sysupgrade$(GLUON_$(profile)_SYSUPGRADE_EXT)"; \ - [ -e "$$file" ] && echo '$(model)' "$(PREPARED_RELEASE)" "$$($(SHA512SUM) "$$file")" "$$file"; \ - \ - $(foreach alias,$(GLUON_$(profile)_MODEL_$(model)_ALIASES), \ - file="$(IMAGE_PREFIX)-$(alias)-sysupgrade$(GLUON_$(profile)_SYSUPGRADE_EXT)"; \ - [ -e "$$file" ] && echo '$(alias)' "$(PREPARED_RELEASE)" "$$($(SHA512SUM) "$$file")" "$$file"; \ - ) \ - ) \ - ) \ - ) : \ - ) >> $(GLUON_BUILDDIR)/$(GLUON_BRANCH).manifest.tmp - -.PHONY: all create-key prepare images modules clean gluon-tools manifest - -endif -endif +.PHONY: FORCE +.NOTPARALLEL: diff --git a/README.md b/README.md index 3ef1f420..e5ac6029 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ Documentation (incomplete at this time, contribute if you can!) may be found at -http://gluon.readthedocs.org/. +https://gluon.readthedocs.org/. If you're new to Gluon and ready to get your feet wet, have a look at the -[Getting Started Guide](http://gluon.readthedocs.org/en/latest/user/getting_started.html). +[Getting Started Guide](https://gluon.readthedocs.org/en/latest/user/getting_started.html). -**Gluon IRC channel: `#gluon` in [hackint](http://hackint.org/)** +**Gluon IRC channel: `#gluon` in [hackint](https://hackint.org/)** ## Issues & Feature requests @@ -18,8 +18,8 @@ the future development of Gluon. ## Use a release! Please refrain from using the `master` branch for anything else but development purposes! -Use the most recent release instead. You can list all relaseses by running `git branch -a` -and switch to one by running `git checkout v2016.1.5 && make update`. +Use the most recent release instead. You can list all releases by running `git tag` +and switch to one by running `git checkout v2018.1 && make update`. If you're using the autoupdater, do not autoupdate nodes with anything but releases. If you upgrade using random master commits the nodes *will break* eventually. @@ -28,11 +28,11 @@ If you upgrade using random master commits the nodes *will break* eventually. To subscribe to the list, send a message to: - gluon-subscribe@luebeck.freifunk.net + gluon+subscribe@luebeck.freifunk.net To remove your address from the list, just send a message to the address in the `List-Unsubscribe` header of any list message. If you haven't changed addresses since subscribing, you can also send a message to: - gluon-unsubscribe@luebeck.freifunk.net + gluon+unsubscribe@luebeck.freifunk.net diff --git a/contrib/i18n-scan.pl b/contrib/i18n-scan.pl new file mode 100755 index 00000000..29abefcc --- /dev/null +++ b/contrib/i18n-scan.pl @@ -0,0 +1,128 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Text::Balanced qw(extract_bracketed extract_delimited extract_tagged); + +@ARGV >= 1 || die "Usage: $0 \n"; + + +my %stringtable; + +sub dec_lua_str +{ + my $s = shift; + $s =~ s/[\s\n]+/ /g; + $s =~ s/\\n/\n/g; + $s =~ s/\\t/\t/g; + $s =~ s/\\(.)/$1/g; + $s =~ s/^ //; + $s =~ s/ $//; + return $s; +} + +sub dec_tpl_str +{ + my $s = shift; + $s =~ s/-$//; + $s =~ s/[\s\n]+/ /g; + $s =~ s/^ //; + $s =~ s/ $//; + $s =~ s/\\/\\\\/g; + return $s; +} + + +if( open F, "find @ARGV -type f '(' -name '*.html' -o -name '*.lua' ')' |" ) +{ + while( defined( my $file = readline F ) ) + { + chomp $file; + + if( open S, "< $file" ) + { + local $/ = undef; + my $raw = ; + close S; + + + my $text = $raw; + + while( $text =~ s/ ^ .*? (?:translate|translatef|_) [\n\s]* \( /(/sgx ) + { + ( my $code, $text ) = extract_bracketed($text, q{('")}); + + $code =~ s/\\\n/ /g; + $code =~ s/^\([\n\s]*//; + $code =~ s/[\n\s]*\)$//; + + my $res = ""; + my $sub = ""; + + if( $code =~ /^['"]/ ) + { + while( defined $sub ) + { + ( $sub, $code ) = extract_delimited($code, q{'"}, q{\s*(?:\.\.\s*)?}); + + if( defined $sub && length($sub) > 2 ) + { + $res .= substr $sub, 1, length($sub) - 2; + } + else + { + undef $sub; + } + } + } + elsif( $code =~ /^(\[=*\[)/ ) + { + my $stag = quotemeta $1; + my $etag = $stag; + $etag =~ s/\[/]/g; + + ( $res ) = extract_tagged($code, $stag, $etag); + + $res =~ s/^$stag//; + $res =~ s/$etag$//; + } + + $res = dec_lua_str($res); + $stringtable{$res}++ if $res; + } + + + $text = $raw; + + while( $text =~ s/ ^ .*? <% -? [:_] /<%/sgx ) + { + ( my $code, $text ) = extract_tagged($text, '<%', '%>'); + + if( defined $code ) + { + $code = dec_tpl_str(substr $code, 2, length($code) - 4); + $stringtable{$code}++; + } + } + } + } + + close F; +} + + +if( open C, "| msgcat -" ) +{ + printf C "msgid \"\"\nmsgstr \"Content-Type: text/plain; charset=UTF-8\"\n\n"; + + foreach my $key ( sort keys %stringtable ) + { + if( length $key ) + { + $key =~ s/"/\\"/g; + printf C "msgid \"%s\"\nmsgstr \"\"\n\n", $key; + } + } + + close C; +} diff --git a/contrib/lsupgrade.sh b/contrib/lsupgrade.sh index 7fe11299..eca7a852 100755 --- a/contrib/lsupgrade.sh +++ b/contrib/lsupgrade.sh @@ -2,10 +2,11 @@ # Script to list all upgrade scripts in a clear manner # Limitations: -# * Does only show scripts of packages whose `files' directory represent the whole image filesystem (which are all Gluon packages) +# * Does only show scripts of packages whose `files'/`luasrc' directories represent the whole image filesystem (which are all Gluon packages) -SUFFIX=files/lib/gluon/upgrade +SUFFIX1=files/lib/gluon/upgrade +SUFFIX2=luasrc/lib/gluon/upgrade shopt -s nullglob @@ -35,8 +36,11 @@ find ./package packages -name Makefile | while read makefile; do dirname="$(dirname "$dir" | cut -d/ -f 3-)" package="$(basename "$dir")" - for file in "${SUFFIX}"/*; do - echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX})" + for file in "${SUFFIX1}"/*; do + echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX1})" + done + for file in "${SUFFIX2}"/*; do + echo "${GREEN}$(basename "${file}")${RESET}" "(${BLUE}${repo}${RESET}/${dirname}${dirname:+/}${RED}${package}${RESET}/${SUFFIX2})" done popd >/dev/null done | sort diff --git a/contrib/sign.sh b/contrib/sign.sh index 0923b2dc..57b08490 100755 --- a/contrib/sign.sh +++ b/contrib/sign.sh @@ -15,7 +15,7 @@ The script may be performed multiple times to the same document to indicate an approval by multiple developers. See also - * edcsautils on https://github.com/tcatm/ecdsautils + * ecdsautils on https://github.com/tcatm/ecdsautils EOHELP exit 1 diff --git a/docs/conf.py b/docs/conf.py index fd329bda..d035119b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,16 +47,16 @@ master_doc = 'index' # General information about the project. project = 'Gluon' -copyright = '2015-2016, Project Gluon' +copyright = '2015-2018, Project Gluon' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '2016.1+' +version = '2018.1' # The full version, including alpha/beta/rc tags. -release = '2016.1+' +release = '2018.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/dev/basics.rst b/docs/dev/basics.rst index 7e7d9f58..2f4d1d89 100644 --- a/docs/dev/basics.rst +++ b/docs/dev/basics.rst @@ -34,21 +34,7 @@ rerun `patches`; the resulting branch will be called `patched`, while the commit specified in `modules` can be refered to by the branch `base`. -:: - - make unpatch - -sets the repositories to the `base` branch, - -:: - - make patch - -re-applies the patches by resetting the `patched` branch to `base` and calling `git am` -for the patch files. Calling `make` or a similar command after calling `make unpatch` -is generally not a good idea. - -After new patches have been commited on top of the patched branch (or existing commits +After new patches have been commited on top of the `patched` branch (or existing commits since the base commit have been edited or removed), the patch directories can be regenerated using @@ -61,3 +47,19 @@ and you can try rebasing it onto the new `base` branch yourself and after that c Always call `make update-patches` after making changes to a module repository as `make update` will overwrite your commits, making `git reflog` the only way to recover them! + +Development Guidelines +---------------------- +lua should be used instead of sh whenever sensible. The following criteria +should be considered: + +- Is the script doing more than just executing external commands? if so, use lua +- Is the script parsing/editing json-data? If so, use lua for speed +- When using sh, use jsonfilter instead of json_* functions for speed + +Code formatting may sound like a topic for the pedantic, however it helps if +the code in the project is formatted in the same way. The following rules +apply: + +- use tabs instead of spaces +- trailing whitespaces must be eliminated diff --git a/docs/dev/configmode.rst b/docs/dev/configmode.rst deleted file mode 100644 index 9a174d4c..00000000 --- a/docs/dev/configmode.rst +++ /dev/null @@ -1,92 +0,0 @@ -Config Mode -=========== - -As of 2014.4 `gluon-config-mode` consists of several modules. - -gluon-config-mode-core - This modules provides the core functionality for the config mode. - All modules must depend on it. - -gluon-config-mode-hostname - Provides a hostname field. - -gluon-config-mode-autoupdater - Informs whether the autoupdater is enabled. - -gluon-config-mode-mesh-vpn - Allows toggling of mesh-vpn-fastd and setting a bandwidth limit. - -gluon-config-mode-geo-location - Enables the user to set the geographical location of the node. - -gluon-config-mode-contact-info - Adds a field where the user can provide contact information. - -In order to get a config mode close to the one found in 2014.3.x you may add -these modules to your `site.mk`: -gluon-config-mode-hostname, -gluon-config-mode-autoupdater, -gluon-config-mode-mesh-vpn, -gluon-config-mode-geo-location, -gluon-config-mode-contact-info - -Writing Config Mode Modules -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Config mode modules are located at `/lib/gluon/config-mode/wizard` and -`/lib/gluon/config-mode/reboot`. Modules are named like `0000-name.lua` and -are executed in lexical order. If you take the standard set of modules, the -order is, for wizard modules: - - - 0050-autoupdater-info - - 0100-hostname - - 0300-mesh-vpn - - 0400-geo-location - - 0500-contact-info - -While for reboot modules it is: - - - 0100-mesh-vpn - - 0900-msg-reboot - -Wizards -------- - -Wizard modules return a UCI section. A simple module capable of changing the -hostname might look like this:: - - local cbi = require "luci.cbi" - local uci = luci.model.uci.cursor() - - local M = {} - - function M.section(form) - local s = form:section(cbi.SimpleSection, nil, nil) - local o = s:option(cbi.Value, "_hostname", "Hostname") - o.value = uci:get_first("system", "system", "hostname") - o.rmempty = false - o.datatype = "hostname" - end - - function M.handle(data) - uci:set("system", uci:get_first("system", "system"), "hostname", data._hostname) - uci:save("system") - uci:commit("system") - end - - return M - -Reboot page ------------ - -Reboot modules return a function that will be called when the page is to be -rendered or nil (i.e. the module is skipped):: - - if no_hello_world_today then - return nil - else - return function () - luci.template.render_string("Hello World!") - end - end - diff --git a/docs/dev/hardware.rst b/docs/dev/hardware.rst index 7f04d93d..aa0462a1 100644 --- a/docs/dev/hardware.rst +++ b/docs/dev/hardware.rst @@ -7,78 +7,138 @@ Hardware requirements --------------------- Having an ath9k (or ath10k) based WLAN adapter is highly recommended, although other chipsets may also work. VAP (multiple SSID) support -is a requirement. At the moment, Gluon's scripts can't handle devices -without WLAN adapters (although such environments may also be interesting, -e.g. for automated testing in virtual machines). +is a requirement. + .. _hardware-adding-profiles: Adding profiles --------------- -The vast majority of devices with ath9k WLAN uses the ar71xx target of OpenWrt. -If the hardware you want to add support for is also ar71xx, adding a new profile -is enough. +The vast majority of devices with ath9k WLAN is based on the ar71xx target of LEDE. +If the hardware you want to add support for is ar71xx, adding a new profile +is sufficient. -Profiles are defined in ``targets/-/profiles.mk``. There are two macros -used to define which images are generated: ``GluonProfile`` and ``GluonModel``. The following examples -are taken from ``profiles.mk`` of the ``ar71xx-generic`` target:: +Profiles are defined in ``targets/*`` in a shell-based DSL (so common shell +command syntax like ``if`` can be used). - $(eval $(call GluonProfile,TLWR1043)) - $(eval $(call GluonModel,TLWR1043,tl-wr1043nd-v1-squashfs,tp-link-tl-wr1043n-nd-v1)) - $(eval $(call GluonModel,TLWR1043,tl-wr1043nd-v2-squashfs,tp-link-tl-wr1043n-nd-v2)) +The ``device`` command is used to define an image build for a device. It takes +two or three parameters. -The ``GluonProfile`` macro takes at least one parameter, the profile name as it is -defined in the Makefiles of OpenWrt (``openwrt/target/linux///profiles/*`` -and ``openwrt/target/linux//image/Makefile``). If the target you are on doesn't define -profiles (e.g. on x86), just add a single profile called ``Generic`` or similar. - -It may optionally take a second parameter which defines additional packages to include for the profile -(e.g. ath10k). The additional packages defined in ``openwrt/target/linux///profiles/*`` -aren't used. - -The ``GluonModel`` macro takes three parameters: The profile name, the suffix of the image file -generated by OpenWrt (without the file extension), and the final image name of the Gluon image. -The final image name must be the same that is returned by the following command. - -:: +The first parameter defines the Gluon profile name, which is used to refer to the +device and is part of the generated image name. The profile name must be same as +the output of the following command (on the target device), so the autoupdater +can work:: lua -e 'print(require("platform_info").get_image_name())' +While porting Gluon to a new device, it might happen that the profile name is un- +known. Best practise is to generate an image first by using an arbitrary value +and then executing the lua command on the device and use its output from then on. -This is just so the autoupdater can work. The command has to be executed _on_ the target (eg. the hardware router with a flashed image). So you'll first have to build an image with a guessed name, and afterwards build a new, correctly named image. On targets which aren't supported by the autoupdater, -``require("platform_info").get_image_name()`` will just return ``nil`` and the final image name -may be defined arbitrarily. +The second parameter defines the name of the image files generated by LEDE. Usually, +it is also the LEDE profile name; for devices that still use the old image build +code, a third parameter with the LEDE profile name can be passed. The profile names +can be found in the image Makefiles in ``lede/target/linux//image/Makefile``. + +Examples:: + + device tp-link-tl-wr1043n-nd-v1 tl-wr1043nd-v1 + device alfa-network-hornet-ub hornet-ub HORNETUB + +Suffixes and extensions +''''''''''''''''''''''' + +By default, image files are expected to have the extension ``.bin``. In addition, +the images generated by LEDE have a suffix before the extension that defaults to +``-squashfs-factory`` and ``-squashfs-sysupgrade``. + +This can be changed using the ``factory`` and ``sysupgrade`` commands, either at +the top of the file to set the defaults for all images, or for a single image. There +are three forms with 0 to 2 arguments (all work with ``sysupgrade`` as well):: + + factory SUFFIX .EXT + factory .EXT + factory + +When only an extension is given, the default suffix is retained. When no arguments +are given, this signals that no factory (or sysupgrade) image exists. + +Aliases +''''''' + +Sometimes multiple models use the same LEDE images. In this case, the ``alias`` +command can be used to create symlinks and additional entries in the autoupdater +manifest for the alternative models. + +Standalone images +''''''''''''''''' + +On targets without *per-device rootfs* support in LEDE, the commands described above +can't be used. Instead, ``factory_image`` and ``sysupgrade_image`` are used:: + + factory_image PROFILE IMAGE .EXT + sysupgrade_image PROFILE IMAGE .EXT + +Again, the profile name must match the value printed by the aforementioned Lua +command. The image name must match the part between the target name and the extension +as generated by LEDE and is to be omitted when no such part exists. + +Packages +'''''''' + +The ``packages`` command takes an arbitrary number of arguments. Each argument +defines an additional package to include in the images in addition to the default +package sets defined by LEDE. When a package name is prefixed by a minus sign, the +packages are excluded instead. + +The ``packages`` command may be used at the top of a target definition to modify +the default package list for all images, or just for a single device (when the +target supports *per-default rootfs*). + + +Configuration +''''''''''''' + +The ``config`` command allows to add arbitary target-specific LEDE configuration +to be emitted to ``.config``. + +Notes +''''' On devices with multiple WLAN adapters, care must also be taken that the primary MAC address is configured correctly. ``/lib/gluon/core/sysconfig/primary_mac`` should contain the MAC address which can be found on a label on most hardware; if it does not, ``/lib/gluon/upgrade/010-primary-mac`` in ``gluon-core`` might need a fix. (There have also been cases in which the address was incorrect -even on devices with only one WLAN adapter, in these cases an OpenWrt bug was the cause). +even on devices with only one WLAN adapter, in these cases a LEDE bug was the cause). + Adding support for new hardware targets --------------------------------------- + Adding a new target is much more complex than adding a new profile. There are two basic steps required for adding a new target: -Adjust packages -''''''''''''''' -One package that definitely needs adjustments for every new target added is ``lua-platform-info``. Just -start with a copy of an existing platform info script, adjust it for the new target, and add the new target -to the list of supported targets in the package Makefile. +Package adjustments +''''''''''''''''''' -On many targets, Gluon's network setup scripts (mainly in the packages ``gluon-core`` and ``gluon-mesh-batman-adv-core``) +One package that may need adjustments for new targets is ``libplatforminfo`` (to be found in +`packages/gluon/libs/libplatforminfo `_). +If the new platform works fine with the definitions found in ``default.c``, nothing needs to be done. Otherwise, +create a definition for the added target or subtarget, either by symlinking one of the files in the ``templates`` +directory, or adding a new source file. + +On many targets, Gluon's network setup scripts (mainly in the package ``gluon-core``) won't run correctly without some adjustments, so better double check that everything is fine there (and the files ``primary_mac``, ``lan_ifname`` and ``wan_ifname`` in ``/lib/gluon/core/sysconfig/`` contain sensible values). -Add support to the build system -''''''''''''''''''''''''''''''' -A directory for the new target must be created under ``targets``, and it must be added -to ``targets/targets.mk``. In the new target directory, the following files must be created: +Build system support +'''''''''''''''''''' -* profiles.mk -* config (optional) - -For ``profiles.mk``, see :ref:`hardware-adding-profiles`. -The file ``config`` can be used to add additional, target-specific options to the OpenWrt config. +A definition for the new target must be created under ``targets``, and it must be added +to ``targets/targets.mk``. The ``GluonTarget`` macro takes one to three arguments: +the target name, the Gluon subtarget name (if the target has subtargets), and the +LEDE subtarget name (if it differs from the Gluon subtarget). The third argument +can be used to define multiple Gluon targets with different configuration for the +same LEDE target, like it is done for the ``ar71xx-tiny`` target. After this, is should be sufficient to call ``make GLUON_TARGET=`` to build the images for the new target. diff --git a/docs/dev/i18n.rst b/docs/dev/i18n.rst deleted file mode 100644 index b51bfdee..00000000 --- a/docs/dev/i18n.rst +++ /dev/null @@ -1,88 +0,0 @@ -Internationalization support -============================ - -General guidelines ------------------- - -* All config mode packages must be fully translatable, with complete English and German texts. -* All new expert mode packages be fully translatable. English texts are required, German texts recommended. -* Existing expert mode packages should be made translatable as soon as possible. -* The "message IDs" (which are the arguments to the ``translate`` function) should be the - English texts. - -i18n support in LuCI --------------------- - -Internationalization support can be found in the ``luci.i18n`` package. -Strings are translated using the ``i18n.translate`` and ``i18n.translatef`` functions -(``translate`` for static strings, ``translatef`` for printf-like formatted string). - -Example from the ``gluon-config-mode-geo-location`` package:: - - local i18n = require "luci.i18n" - o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map")) - -Adding translation templates to Gluon packages ----------------------------------------------- - -The i18n support is based on the standard gettext system. For each translatable package, -a translation template with extension ``.pot`` can be created using the ``i18n-scan.pl`` -script from the LuCI repository:: - - cd package/gluon-config-mode-geo-location - mkdir i18n - cd i18n - ../../../packages/luci/build/i18n-scan.pl ../files > gluon-config-mode-geo-location.pot - -The entries in the template can be reordered after the generation if desirable. Lots of standard -translations like "Cancel" are already available in the LuCI base translation file (see -``packages/luci/po/templates/base.pot``) and can be removed from the template. - -In addition, some additions to the Makefile must be made. Instead of OpenWrt's default package.mk, -the Gluon version ``$(GLUONDIR)/include/package.mk`` must be used. The i18n files must be installed -and PKG_CONFIG_DEPENDS must be added:: - - ... - include $(GLUONDIR)/include/package.mk - - PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - ... - define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-geo-location,i18n) - endef - - define Package/gluon-config-mode-geo-location/install - ... - $(call GluonInstallI18N,gluon-config-mode-geo-location,$(1)) - endef - ... - - -Adding translations -------------------- - -A new translation file for a template can be added using the ``msginit`` command:: - - cd package/gluon-config-mode-geo-location/i18n - msginit -l de - -This will create the file ``de.po`` in which the translations can be added. - -The translation file can be updated to a new template version using the ``msgmerge`` command:: - - msgmerge -U de.po gluon-config-mode-geo-location.pot - -After the merge, the translation file should be checked for "fuzzy matched" entries where -the original English texts have changed. All entries from the the translation file should be -translated in the ``.po`` file (or removed from it, so the original English texts are displayed -instead). - -Adding support for new languages --------------------------------- - -A list of all languages supported by LuCI can be found in the ``packages/luci/luci.mk`` file after -Gluon's dependencies have been downloaded using ``make update``. Adding translations for these -languages is straightforward using the ``msginit`` command. - -For other languages, support must be added tu LuCI first, which constitutes completely translating -the ``base.pot``. Please contact the upstream LuCI maintainers if you'd like to do this. diff --git a/docs/dev/mac_addresses.rst b/docs/dev/mac_addresses.rst new file mode 100644 index 00000000..b221a302 --- /dev/null +++ b/docs/dev/mac_addresses.rst @@ -0,0 +1,18 @@ +MAC addresses +============= + +Many devices don't have enough unique MAC addresses assigned by the vendor +(in batman-adv, each mesh interface needs an own MAC address that must be unique +mesh-wide). + +Gluon tries to solve this issue by using a hash of the primary MAC address as a +45 bit MAC address prefix. The resulting 8 addresses are used as follows: + +* 0: client0; WAN +* 1: mesh0 +* 2: ibss0 +* 3: wan_radio0 (private WLAN); batman-adv primary address +* 4: client1; LAN +* 5: mesh1 +* 6: ibss1 +* 7: wan_radio1 (private WLAN); mesh VPN diff --git a/docs/dev/packages.rst b/docs/dev/packages.rst new file mode 100644 index 00000000..f89e83d4 --- /dev/null +++ b/docs/dev/packages.rst @@ -0,0 +1,114 @@ +Package development +################### + +Gluon packages are OpenWrt packages and follow the same rules described at https://openwrt.org/docs/guide-developer/packages. + + +Gluon package makefiles +======================= + +As many packages share the same or a similar structure, Gluon provides a ``package/gluon.mk`` that +can be included for common definitions. This file replaces OpenWrt's ``$(INCLUDE_DIR)/package.mk``; +it is usually included as ``include ../gluon.mk`` from Gluon core packages, or as +``include $(TOPDIR)../package/gluon.mk`` from feeds. + +Provided macros +*************** + +* *GluonBuildI18N* (arguments: **) + + Converts the *.po* files for all enabled languages from the given source directory to + the binary *.lmo* format and stores them in ``$(PKG_BUILD_DIR)/i18n``. + +* *GluonInstallI18N* + + Install *.lmo* files from ``$(PKG_BUILD_DIR)/i18n`` to ``/lib/gluon/web/i18n`` in the + package install directory. + +* *GluonSrcDiet* (arguments: **, **) + + Copies a directory tree, processing all files in it using *LuaSrcDiet*. The directory + tree should only contain Lua files. + +* *GluonCheckSite* (arguments: **) + + Intended to be used in a package postinst script. It will use the passed Lua + snippet to verify package-specific site configuration. + +* *BuildPackageGluon* (replaces *BuildPackage*) + + Extends the *Package/* definition with common defaults, sets the package + install script to the common *Gluon/Build/Install*, and automatically creates + a postinst script using *GluonCheckSite* if a ``check_site.lua`` is found in the + package directory. + +Default build steps +******************* + +These defaults greatly reduce the boilerplate in each package, but they can also +be confusing because of the many implicit behaviors depending on files in the +package directory. If any part of *Gluon/Build/Compile* or *Gluon/Build/Install* +does not work as intended for a package, the compile and install steps can +always be replaced or extended. + +*Build/Compile* is set to *Gluon/Build/Compile* by default, which will + +* run OpenWrt standard default commands (*Build/Compile/Default*) if a ``src/Makefile`` + or ``src/CMakeLists.txt`` is found +* run *GluonSrcDiet* on all files in the ``luasrc`` directory +* run *GluonBuildI18N* if a ``i18n`` directory is found + +*Package/* defaults to *Gluon/Build/Install* for packages defined using +*BuildPackageGluon*, which will + +* copy all files from ``$(PKG_INSTALL_DIR)`` into the package if ``$(PKG_INSTALL)`` is 1 +* copy all files from ``files`` into the package +* copy all Lua files built from ``luasrc`` into the package +* installs ``$(PKG_BUILD_DIR)/respondd.so`` to ``/usr/lib/respondd/$(PKG_NAME).so`` if ``src/respondd.c`` exists +* installs compiled i18n *.lmo* files + +Feature flags +============= + +Feature flags provide a convenient way to define package selections without +making it necessary to list each package explicitly. + +The main feature flag definition file is ``package/features``, but each package +feed can provide additional defintions in a file called ``features`` at the root +of the feed repository. + +Each flag *$flag* without any explicit definition will simply include the package +with the name *gluon-$flag* by default. The feature definition file can modify +the package selection in two ways: + +* The *nodefault* function suppresses default of including the *gluon-$flag* + package +* The *packages* function adds a list of packages (or removes, when package + names are prepended with minus signs) when a given logical expression + is satisfied + +Example:: + + nodefault 'web-wizard' + + packages 'web-wizard' \ + 'gluon-config-mode-hostname' \ + 'gluon-config-mode-geo-location' \ + 'gluon-config-mode-contact-info' + + packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \ + 'gluon-config-mode-mesh-vpn' + +This will + +* disable the inclusion of a (non-existent) package called *gluon-web-wizard* +* enable three config mode packages when the *web-wizard* feature is enabled +* enable *gluon-config-mode-mesh-vpn* when both *web-wizard* and one + of *mesh-vpn-fastd* and *mesh-vpn-tunneldigger* are enabled + +Supported syntax elements of logical expressions are: + +* \& (and) +* \| (or) +* \! (not) +* parentheses diff --git a/docs/dev/site_library.rst b/docs/dev/site_library.rst new file mode 100644 index 00000000..991e3cb5 --- /dev/null +++ b/docs/dev/site_library.rst @@ -0,0 +1,36 @@ +gluon.site library +================== + +The *gluon.site* library allows convenient access to the site configuration +from Lua scripts. Example: + +.. code-block:: lua + + local site = require 'gluon.site' + print(site.wifi24.ap.ssid()) + +The *site* object in this example does not directly represent the *site.conf* data structure; +instead, it is wrapped in a way that makes it more convenient to access deeply nested elements. +To access the the underlying values, they must be unwrapped using the function call notation +(the ``()`` after ``site.wifi24.ap.ssid`` in the example). + +The wrapper objects have two advantages over simple Lua tables: + +* Accessing non-existing values is never an error: ``site.wifi24.ap.ssid()`` will simply + return *nil* if ``site.wifi24`` or ``site.wifi24.ap`` do not exist +* Default values: A default value can be passed to the unwrapping function call: + + .. code-block:: lua + + print(site.wifi24.ap.ssid('Default')) + + will return *'Default'* instead of *nil* when the value is unset. + + Note that *nil* values and unset values are equivalent in Lua. + +A simple way to access the whole site configuration as a simple table +is to unwrap the top-level site object: + +.. code-block:: lua + + local site_table = site() diff --git a/docs/dev/upgrade.rst b/docs/dev/upgrade.rst index 28377235..2c18604d 100644 --- a/docs/dev/upgrade.rst +++ b/docs/dev/upgrade.rst @@ -6,7 +6,7 @@ Basics After each sysupgrade (including the initial installation), Gluon will execute all scripts under ``/lib/gluon/upgrade``. These scripts' filenames usually begin with a 3-digit number -specifying the order of execution. +specifying the order of execution. Note that the script files need to be executable. To get an overview of the ordering of all scripts of all packages, the helper script ``contrib/lsupgrade.sh`` in the Gluon repository can be used, which will print all upgrade scripts' filenames and directories. If executed @@ -16,17 +16,15 @@ Best practices -------------- * Most upgrade scripts are written in Lua. This allows using lots of helper functions provided - by LuCi and Gluon, e.g. to access the site configuration or edit UCI configuration files. + by Gluon, e.g. to access the site configuration or edit UCI configuration files. * Whenever possible, scripts shouldn't check if they are running for the first time, but just edit configuration - files to achive a valid configuration (without overwriting configuration changes made by the user where desirable). + files to achieve a valid configuration (without overwriting configuration changes made by the user where desirable). This allows using the same code to create the initial configuration and upgrade configurations on upgrades. * If it is unavoidable to run different code during the initial installation, the ``sysconfig.gluon_version`` variable can be checked. This variable is ``nil`` during the initial installation and contains the previously install Gluon - version otherwise. The package ``gluon-legacy`` (which is responsible for upgrades from the old firmwares of - Hamburg/Kiel/Lübeck) uses the special value ``legacy``; other packages should handle this value just as any other - string. + version otherwise. Script ordering --------------- diff --git a/docs/dev/wan.rst b/docs/dev/wan.rst index a430df31..9742bf2b 100644 --- a/docs/dev/wan.rst +++ b/docs/dev/wan.rst @@ -46,4 +46,4 @@ so the WAN DNS servers aren't leaked to the primary DNS daemon. *libpacketmark* is used to make the secondary DNS daemon send its requests over the WAN interface. The package ``gluon-mesh-vpn-fastd`` provides an iptables rule which will redirect all DNS requests from processes running -with the primary group ``gluon-fastd`` to ``127.0.0.1:54``, thus making fastd use the secondary DNS daemon. +with the primary group ``gluon-mesh-vpn`` to ``127.0.0.1:54``, thus making fastd use the secondary DNS daemon. diff --git a/docs/dev/web/config-mode.rst b/docs/dev/web/config-mode.rst new file mode 100644 index 00000000..9c0c2430 --- /dev/null +++ b/docs/dev/web/config-mode.rst @@ -0,0 +1,82 @@ +Config Mode +=========== + +The `Config Mode` consists of several modules that provide a range of different +condiguration options: + +gluon-config-mode-core + This modules provides the core functionality for the config mode. + All modules must depend on it. + +gluon-config-mode-hostname + Provides a hostname field. + +gluon-config-mode-autoupdater + Informs whether the autoupdater is enabled. + +gluon-config-mode-mesh-vpn + Allows toggling of mesh-vpn-fastd and setting a bandwidth limit. + +gluon-config-mode-geo-location + Enables the user to set the geographical location of the node. + +gluon-config-mode-contact-info + Adds a field where the user can provide contact information. + + +Writing Config Mode modules +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Config mode modules are located at ``/lib/gluon/config-mode/wizard`` and +``/lib/gluon/config-mode/reboot``. Modules are named like ``0000-name.lua`` and +are executed in lexical order. In the standard package set, the +order is, for wizard modules: + + - 0050-autoupdater-info + - 0100-hostname + - 0300-mesh-vpn + - 0400-geo-location + - 0500-contact-info + +The reboot module order is: + + - 0100-mesh-vpn + - 0900-msg-reboot + +All modules are run in the gluon-web model context and have access to the same +variables as "full" gluon-web modules. + +Wizards +------- + +Wizard modules must return a function that is provided with the wizard form and an +UCI cursor. The function can create configuration sections in the form: + +.. code-block:: lua + + return function(form, uci) + local s = form:section(Section) + local o = s:option(Value, "hostname", "Hostname") + o.default = uci:get_first("system", "system", "hostname") + o.datatype = "hostname" + + function o:write(data) + uci:set("system", uci:get_first("system", "system"), "hostname", data) + end + + return {'system'} + end + +The function may return a table of UCI packages to commit after the individual +fields' `write` methods have been executed. This is done to avoid committing the +packages repeatedly when multiple wizard modules modify the same package. + +Reboot page +----------- + +Reboot modules are simply executed when the reboot page is +rendered: + +.. code-block:: lua + + renderer.render_string("Hello World!") diff --git a/docs/dev/web/controller.rst b/docs/dev/web/controller.rst new file mode 100644 index 00000000..b3adb288 --- /dev/null +++ b/docs/dev/web/controller.rst @@ -0,0 +1,123 @@ +Controllers +=========== + +Controllers live in ``/lib/gluon/web/controller``. They define which pages ("routes") +exist under the ``/cgi-bin/gluon`` path, and what code is run when these pages are requested. + +Controller scripts usually start with a *package* declaration, followed by calls +to the *entry* function, which each define one route: + +.. code-block:: lua + + package 'gluon-web-admin' + + entry({"admin"}, alias("admin", "info"), _("Advanced settings"), 10) + entry({"admin", "info"}, template("admin/info"), _("Information"), 1) + +*package* defines the translation namespace for the titles of the defined +pages as well as the referenced views and models. The entry function expects 4 +arguments: + + - `path`: Components of the path to define a route for. + + The above example defines routes for the paths ``admin`` and ``admin/info``. + + - `target`: Dispatcher for the route. See the following section for details. + - `title`: Page title (also used in navigation). The underscore function is used + to mark the strings as translatable for ``i18n-scan.pl``. + + - `order`: Sort index in navigation (defaults to 100) + +Navigation indexes are automatically generated for each path level. Pages can be +hidden from the navigation by setting the `hidden` property of the node object +returned by `entry`: + +.. code-block:: lua + + entry({"hidden"}, alias("foo"), _("I'm hidden!")).hidden = true + + +Dispatchers +----------- + + - *alias* (*path*, ...): Redirects to a different page. The path components are + passed as individual arguments. + - *call* (*func*, ...): Runs a Lua function for custom request handling. The given + function is called with the HTTP object and the template renderer as first + two arguments, followed by all additional arguments passed to `call`. + - *template* (*view*): Renders the given view. See :doc:`view`. + - *model* (*name*): Displays and evaluates a form as defined by the given model. See the + :doc:`model` page for an explanation of gluon-web models. + + +.. _web-controller-http: + +The HTTP object +--------------- + +The HTTP object provides information about the HTTP requests and allows to add +data to the reply. Using it directly is rarely necessary when gluon-web +models and views are used. + +Useful functions: + + - *getenv* (*key*): Returns a value from the CGI environment passed by the webserver. + - *formvalue* (*key*): Returns a value passed in a query string or in the content + of a POST request. If multiple values with the same name have been passed, only + the first is returned. + - *formvaluetable* (*key*): Similar to *formvalue*, but returns a table of all + values for the given key. + - *status* (*code*, *message*): Writes the HTTP status to the reply. Has no effect + if a status has already been sent or non-header data has been written. + - *header* (*key*, *value*): Adds an HTTP header to the reply to be sent to to + the client. Has no effect when non-header data has already been written. + - *prepare_content* (*mime*): Sets the *Content-Type* header to the given MIME + type, potentially setting additional headers or modifying the MIME type to + accommodate browser quirks + - *write* (*data*, ...): Sends the given data to the client. If headers have not + been sent, it will be done before the data is written. + + +HTTP functions are called in method syntax, for example: + +.. code-block:: lua + + http:write('Output!') + + +.. _web-controller-template-renderer: + +The template renderer +--------------------- + +The template renderer allows to render templates (views). The most useful functions +are: + + - *render* (*view*, *scope*, *pkg*): Renders the given view, optionally passing a table + with additional variables to make available in the template. The passed package + defines the translation namespace. + - *render_string* (*str*, *scope*, *pkg*): Same as *render*, but the template is passed + directly instead of being loaded from the view directory. + +The renderer functions are called in property syntax, for example: + +.. code-block:: lua + + renderer.render('layout') + + +Differences from LuCI +--------------------- + + - Controllers must not use the *module* function to define a Lua module (*gluon-web* + will set up a proper environment for each controller itself) + - Entries are defined at top level, not inside an *index* function + - The *alias* dispatcher triggers an HTTP redirect instead of directly running + the dispatcher of the aliased route. + - The *call* dispatcher is passed a function instead of a string with a function + name. + - The *cbi* dispatcher of LuCI has been renamed to *model*. + - The HTTP POST handler support the multipart/form-data encoding only, so + ``enctype="multipart/form-data"`` must be included in all *
* HTML + elements. + - Other dispatchers like *form* are not provided. diff --git a/docs/dev/web/i18n.rst b/docs/dev/web/i18n.rst new file mode 100644 index 00000000..c85baaee --- /dev/null +++ b/docs/dev/web/i18n.rst @@ -0,0 +1,109 @@ +Internationalization support +============================ + +General guidelines +------------------ + +* All config mode packages must be fully translatable, with complete English and German texts. +* All new expert mode packages must be fully translatable. English texts are required. +* German translations are recommended. Other supported languages, especially French, are + nice-to-have, but not required. If you don't know a language well, rather leave the translation + blank, so it is obvious that there is no proper translation yet. +* Existing expert mode packages should be made translatable as soon as possible. +* The "message IDs" (which are the arguments to the *translate* function) should be the + English texts. + +i18n support in Gluon +--------------------- + +Internationalization support is available in all components (models, view and +controllers) of *gluon-web*-based packages. Strings are translated using the *translate*, +*_translate* and *translatef* functions (*translate* for static strings, *translatef* +for printf-like formatted string; *_translate* works the same as *translate*, but +will return *nil* instead of the original string when no translation is available). + +In views, the special tags ``<%:...%>`` can be used to translate the contained string. + +Example from the *gluon-config-mode-geo-location* package: + +.. code-block:: lua + + local share_location = s:option(Flag, "location", translate("Show node on the map")) + +Note that translations are *namespaced*: each package will only use its own +translation strings by default. For this purpose, the package name must by +specified in a package's controller. It is possible to access a different +translation package using the *i18n* function from models and view, which is +necessary when strings from the site configuration are used, or packages do not +have their own controller (which is the case for config mode wizard components). + +.. code-block:: lua + + local site_i18n = i18n 'gluon-site' + local msg = site_i18n._translate('gluon-config-mode:welcome') + +Adding translation templates to Gluon packages +---------------------------------------------- + +The i18n support is based on the standard gettext system. For each translatable package, +a translation template with extension ``.pot`` can be created using the *i18n-scan.pl* +script in the ``contrib`` directory: + +.. code-block:: sh + + cd package/gluon-web-mesh-vpn-fastd + mkdir i18n + cd i18n + ../../../contrib/i18n-scan.pl ../files ../luasrc > gluon-web-mesh-vpn-fastd.pot + +The same command can be run again to update the template. + +In addition, the Makefile must be adjusted. Instead of LEDE's default *package.mk*, +the Gluon version (``../gluon.mk`` for core packages) must be used. The i18n files must be installed +and PKG_CONFIG_DEPENDS must be added:: + + ... + include ../gluon.mk + + PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) + ... + define Build/Compile + $(call GluonBuildI18N,gluon-web-mesh-vpn-fastd,i18n) + endef + + define Package/gluon-web-mesh-vpn-fastd/install + ... + $(call GluonInstallI18N,gluon-web-mesh-vpn-fastd,$(1)) + endef + ... + + +Adding translations +------------------- + +A new translation file for a template can be added using the *msginit* command: + +.. code-block:: sh + + cd package/gluon-web-mesh-vpn-fastd/i18n + msginit -l de + +This will create the file *de.po* in which the translations can be added. + +The translation file can be updated to a new template version using the *msgmerge* command: + +.. code-block:: sh + + msgmerge -U de.po gluon-web-mesh-vpn-fastd.pot + +After the merge, the translation file should be checked for "fuzzy matched" entries where +the original English texts have changed. All entries from the translation file should be +translated in the *.po* file (or removed from it, so the original English texts are displayed +instead). + +Adding support for new languages +-------------------------------- + +A list of all languages supported by *gluon-web* can be found in ``package/gluon.mk``. +New languages just need to be added to *GLUON_SUPPORTED_LANGS*, and a human-readable +language name must be defined. diff --git a/docs/dev/web/model.rst b/docs/dev/web/model.rst new file mode 100644 index 00000000..6a61e3c4 --- /dev/null +++ b/docs/dev/web/model.rst @@ -0,0 +1,148 @@ +Models +====== + +Models are defined in ``/lib/gluon/web/model``. Each model defines one or more +forms to display on a page, and how the submitted form data is handled. + +Let's start with an example: + +.. code-block:: lua + + local f = Form(translate('Hostname')) + + local s = f:section(Section) + + local o = s:option(Value, 'hostname', translate('Hostname')) + o.default = uci:get_first('system', 'system', 'hostname') + function o:write(data) + uci:set('system', uci:get_first('system', 'system'), 'hostname', data) + uci:commit('system') + end + + return f + +The toplevel element of a model is always a *Form*, but it is also possible for +a model to return multiple forms, which are displayed one below the other. + +A *Form* has one or more *Sections*, and each *Section* has different types +of options. + +All of these elements have an *id*, which is used to identify them in the HTML +form and handlers. If no ID is given, numerical IDs will be assigned automatically, +but using explicitly named elements is often advisable (and it is required if a +form does not always include the same elements, i.e., some forms, sections or +options are added conditionally). IDs are hierarchical, so in the above example, +the *Value* would get the ID ``1.1.hostname`` (value *hostname* in first section +of first form). + +Classes and methods +------------------- + + - *Form* (*title*, *description*, *id*) + + - *Form:section* (*type*, *title*, *description*, *id*) + + Creates a new section of the given type (usually *Section*). + + - *Form:write* () + + Is called after the form has beed submitted (but only if the data is valid). It + is called last (after all options' *write* methods) and is usually used + to commit changed UCI packages. + + The default implementation of *write* doesn't do anything, but it can be + overridden. + + - *Section* (usually instanciated through *Form:section*) + + - *Section:option* (*type*, *id*, *title*, *description*) + + Creates a new option of the given type. Option types: + + - *Value*: simple text entry + - *TextValue*: multiline text field + - *ListValue*: radio buttons or dropdown selection + - *DynamicList*: variable number of text entry fields + - *Flag*: checkbox + +Most option types share the same properties and methods: + + - *default*: default value + - *optional*: value may be empty + - *datatype*: one of the types described in :ref:`web-model-datatypes` + + By default (when *datatype* is *nil*), all values are accepted. + + - *state*: has one of the values *FORM_NODATA*, *FORM_VALID* and *FORM_INVALID* + when read in a form handler + + An option that has not been submitted because of its dependencies will have + the state *FORM_NODATA*, *FORM_INVALID* if the submitted value is not valid + according to the set *datatype*, and *FORM_VALID* otherwise. + + - *data*: can be read in form handlers to get the submitted value + + - *depends* (*self*, *option*, *value*): adds a dependency on another option + + The option will only be shown when the passed option has the given value. This + is mainly useful when the other value is a *Flag* or *ListValue*. + + - *depends* (*self*, *deps*): adds a dependency on multiple other options + + *deps* must be a table with options as keys and values as values. The option + will only be shown when all passed options have the corresponding values. + + Multiple alternative dependencies can be added by calling *depends* repeatedly. + + - *value* (*self*, *value*, *text*): adds a choice to a *ListValue* + + - *write* (*self*, *data*): is called with the submitted value when all form data is valid. + + Does not do anything by default, but can be overridden. + +The *default* value, the *value* argument to *depends* and the output *data* always have +the same type, which is usually a string (or *nil* for optional values). Exceptions +are: + + - *Flag* uses boolean values + - *DynamicList* uses a table of strings + +Despite its name, the *datatype* setting does not affect the returned value type, +but only defines a validator the check the submitted value with. + +For a more complete example that actually makes use of most of these features, +have a look at the model of the *gluon-web-network* package. + +.. _web-model-datatypes: + +Data types +---------- + + - *integer*: an integral number + - *uinteger*: an integral number greater than or equal to zero + - *float*: a number + - *ufloat*: a number greater than or equal to zero + - *ipaddr*: an IPv4 or IPv6 address + - *ip4addr*: an IPv4 address + - *ip6addr*: an IPv6 address + - *wpakey*: a string usable as a WPA key (either between 8 and 63 characters, or 64 hex digits) + - *range* (*min*, *max*): a number in the given range (inclusive) + - *min* (*min*): a number greater than or equal to the given minimum + - *max* (*max*): a number less than or equal to the given maximum + - *irange* (*min*, *max*): an integral number in the given range (inclusive) + - *imin* (*min*): an integral number greater than or equal to the given minimum + - *imax* (*max*): an integral number less than or equal to the given maximum + - *minlength* (*min*): a string with the given minimum length + - *maxlength* (*max*): a string with the given maximum length + +Differences from LuCI +--------------------- + + - LuCI's *SimpleForm* and *SimpleSection* are called *Form* and *Section*, respectively + - Is it not possible to add options to a *Form* directly, a *Section* must always + be created explicitly + - Many of LuCI's CBI classes have been removed, most importantly the *Map* + - The *rmempty* option attribute does not exist, use *optional* instead + - Only the described data types are supported + - Form handlers work completely differently (in particular, a *Form*'s *handle* + method should usually not be overridden in *gluon-web*) diff --git a/docs/dev/web/view.rst b/docs/dev/web/view.rst new file mode 100644 index 00000000..d9cafa34 --- /dev/null +++ b/docs/dev/web/view.rst @@ -0,0 +1,55 @@ +Views +===== + +The template parser reads views from ``/lib/gluon/web/view``. Writing own view +should be avoided in favour of using :doc:`model` with their predefined views. + +Views are partial HTML pages, with additional template tags that allow +to embed Lua code and translation strings. The following tags are defined: + + - ``<%`` ... ``%>`` evaluates the enclosed Lua expression. + - ``<%=`` ... ``%>`` evaluates the enclosed Lua expression and prints its value. + - ``<%+`` ... ``%>`` includes another template. + - ``<%:`` ... ``%>`` translates the enclosed string using the loaded i18n catalog. + - ``<%_`` ... ``%>`` translates the enclosed string *without escaping HTML entities* + in the translation. This only makes sense when the i18n catalog contains HTML code. + - ``<%#`` ... ``%>`` is a comment. + +All of these also come in the whitespace-stripping variants ``<%-`` and ``-%>`` that +remove all whitespace before or after the tag. + +Complex combinations of HTML and Lua code are possible, for example: + +.. code-block:: text + +
+ <% if foo then %> + Content + <% end %> +
+ + +Variables and functions +----------------------- + +Many call sites define additional variables (for example, model templates can +access the model as *self* and a unique element ID as *id*), but the following +variables and functions should always be available for the embedded Lua code: + + - *renderer*: :ref:`web-controller-template-renderer` + - *http*: :ref:`web-controller-http` + - *request*: Table containing the path components of the current page + - *url* (*path*): returns the URL for the given path, which is passed as a table of path components. + - *attr* (*key*, *value*): Returns a string of the form ``key="value"`` + (with a leading space character before the key). + + *value* is converted to a string (tables are serialized as JSON) and HTML entities + are escaped. Returns an empty string when *value* is *nil* or *false*. + - *include* (*template*): Includes another template. + - *node* (*path*, ...): Returns the controller node for the given page (passed as + one argument per path component). + + Use ``node(unpack(request))`` to get the node for the current page. + - *pcdata* (*str*): Escapes HTML entities in the passed string. + - *urlencode* (*str*): Escapes the passed string for use in an URL. + - *translate*, *_translate*, *translatef* and *i18n*: see :doc:`i18n` diff --git a/docs/features/autoupdater.rst b/docs/features/autoupdater.rst index 8c4ca73f..5313feac 100644 --- a/docs/features/autoupdater.rst +++ b/docs/features/autoupdater.rst @@ -11,14 +11,24 @@ during development), but it can be enabled by setting the variable GLUON_BRANCH to override the default branch set in the set in the site configuration. A manifest file for the updater can be generated with `make manifest`. A signing script (using -ecdsautils) can by found in the `contrib` directory. When creating the manifest, ``GLUON_PRIORITY`` can -be set on the command line, or it can be taken from the ``site.mk``. +``ecdsautils``) can by found in the `contrib` directory. When creating the manifest, the +``PRIORITY`` value may be defined by setting ``GLUON_PRIORITY`` on the command line or in ``site.mk``. -The priority defines the maximum number of days that may pass between releasing an update and installation -of the images. The update probability will start at 0 after the release time mentioned in the manifest -and then slowly rise to 1 up to the point when the number of days given by the priority has passed. +``GLUON_PRIORITY`` defines the maximum number of days that may pass between releasing an update and installation +of the images. The update probability will start at 0 after the release time declared in the manifest file +by the variable DATE and then slowly rise up to 1 when ``GLUON_PRIORITY`` days have passed. The autoupdater checks +for updates hourly (at a random minute of the hour), but usually only updates during its run between +4am and 5am, except when the whole ``GLUON_PRIORITY`` days and another 24 hours have passed. -The priority may be an integer or a decimal fraction. +``GLUON_PRIORITY`` may be an integer or a decimal fraction. + +If ``GLUON_RELEASE`` is passed to ``make`` explicitly or it is generated dynamically +in ``site.mk``, care must be taken to pass the same ``GLUON_RELEASE`` to ``make manifest``, +as otherwise the generated manifest will be incomplete. + + +Automated nightly builds +------------------------ A fully automated nightly build could use the following commands: @@ -28,8 +38,9 @@ A fully automated nightly build could use the following commands: (cd site && git pull) make update make clean - make -j5 GLUON_TARGET=ar71xx-generic GLUON_BRANCH=experimental - make manifest GLUON_BRANCH=experimental + NUM_CORES_PLUS_ONE=$(expr $(nproc) + 1) + make -j$NUM_CORES_PLUS_ONE GLUON_TARGET=ar71xx-generic GLUON_BRANCH=experimental + make manifest GLUON_BRANCH=$GLUON_BRANCH GLUON_RELEASE=$GLUON_RELEASE contrib/sign.sh $SECRETKEY output/images/sysupgrade/experimental.manifest rm -rf /where/to/put/this/experimental @@ -70,11 +81,9 @@ These commands can be used on a node: # Force update check, even when the updater is disabled autoupdater -f - + :: - # If fallback is true the updater will perform an update only if - # the timespan given by the priority and another 24h have passed + # If fallback is true the updater will perform an update only if the timespan + # PRIORITY days (as defined in the manifest) and another 24h have passed autoupdater --fallback - - diff --git a/docs/features/dns-forwarder.rst b/docs/features/dns-forwarder.rst new file mode 100644 index 00000000..d74f9618 --- /dev/null +++ b/docs/features/dns-forwarder.rst @@ -0,0 +1,26 @@ +DNS forwarder +============= + +A Gluon node can be configured to act as a DNS forwarder. Requests for the +next-node hostname(s) can be answered locally, without querying the upstream +resolver. + +**Note:** While this reduces answer time and allows to use the next-node +hostname without upstream connectivity, this feature should not be used for +next-node hostnames that are FQDN when the zone uses DNSSEC. + +One or more upstream resolvers can be configured in the *dns.servers* setting. +When *next_node.name* is set, A and/or AAAA records for the next-node IP +addresses are placed in the dnsmasq configuration. + +:: + + dns = { + servers = { '2001:db8::1', }, + }, + + next_node = { + name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' }, + ip6 = '2001:db8:8::1', + ip4 = '198.51.100.1', + } diff --git a/docs/features/fastd_mode.gif b/docs/features/fastd_mode.gif new file mode 100644 index 00000000..9f97074f Binary files /dev/null and b/docs/features/fastd_mode.gif differ diff --git a/docs/features/monitoring.rst b/docs/features/monitoring.rst index f3d0382d..ca4ae08d 100644 --- a/docs/features/monitoring.rst +++ b/docs/features/monitoring.rst @@ -45,7 +45,7 @@ retrieve the data you'll need both a local alfred daemon and alfred-json_ installed. Please note that at least one alfred daemon is required to run as `master`. -.. _alfred-json: https://github.com/tcatm/alfred-json +.. _alfred-json: https://github.com/ffnord/alfred-json The following datatypes are used: @@ -97,7 +97,7 @@ In order to retrieve statistics data you could run: You can find more information about alfred in its README_. -.. _README: http://www.open-mesh.org/projects/alfred/repository/revisions/master/entry/README +.. _README: https://git.open-mesh.org/alfred.git/blob_plain/refs/heads/master:/README gluon-respondd ~~~~~~~~~~~~~~ diff --git a/docs/features/multidomain.rst b/docs/features/multidomain.rst new file mode 100644 index 00000000..7fa55a3f --- /dev/null +++ b/docs/features/multidomain.rst @@ -0,0 +1,272 @@ +Multidomain Support +=================== + +Preamble +-------- + +There comes a time when a mesh network grows past sensible boundaries. +As broadcast traffic grows, mesh networks experience scaling issues and +using them becomes very unpleasant. An approach to solve this follows +the well-known “divide and conquer” paradigm and splits a large network +into multiple smaller networks. These smaller networks start with a +dedicated layer 2 network each, which are interconnected via their +gateways by layer 3 routing. Gluon is already field-tested handling a +single domain and the multidomain feature allows for the reconfiguration +of key parameters that decide which domain a node participates in, +without the need of a distinct set of firmware images for each mesh domain. + +Overview +-------- + +Multidomain support allows to build a single firmware with multiple, +switchable domain configurations. The nomenclature is as follows: + +- ``site``: an aggregate over multiple domains +- ``domain``: mesh network with connectivity parameters that prevent + accidental bridging with other domains +- ``domain code``: unique domain identifier +- ``domain name``: pretty name for a domain code + +By default Gluon builds firmware with a single domain embedded into +``site.conf``. To use multiple domains, enable it in ``site.mk``: + +:: + + GLUON_MULTIDOMAIN=1 + +In the site repository, create the ``domains/`` directory, which will +hold your domain configurations. Each domain configuration file is named +after its primary ``domain_code``, additional domain codes and names are +supported. + +:: + + site/ + |-- site.conf + |-- site.mk + |-- i18n/ + |-- domains/ + |-- alpha_centauri.conf + |-- beta_centauri.conf + |-- gamma_centauri.conf + +The domain configuration ``alpha_centauri.conf`` could look like this. + +:: + + { + domain_names = { + alpha_centauri = 'Alpha Centauri' + }, + + -- more domain specific config follows below + } + +In this example “Alpha Centauri” is the user-visible ``domain_name`` for the +domain_code ``alpha_centauri``. Also note that the domain code +``alpha_centauri`` matches the filename ``alpha_centauri.conf``. + +Additional domain codes/names can be added to ``domain_names``, which +are treated as aliases for the their domain configuration. Aliases can +be used to offer more fine-grained and well-recognizable domain choices +to users. Having multiple aliases on a single domain is a helpful +precursor to splitting the domain into even smaller blocks. + +Furthermore you have to specify the ``default_domain`` in the ``site.conf``. +This domain is applied in following cases: + +- When the config mode is skipped. +- When a domain is removed in a new firmware release, the default_domain + will be chosen then. +- When a user selects a wrong domain code via uci. + +Please note, that this value is saved to uci, so changing the `default_domain` +value in the `site.conf` in a new firmware release only affects the actual +domain of a router, if and only if one of the above conditions matches. + + +Switching the domain +-------------------- + +**via commandline**: + +:: + + uci set gluon.core.domain="newdomaincode" + gluon-reconfigure + reboot + +**via config mode:** + +To allow switching the domain via config mode, ``config-mode-domain-select`` +has to be added to GLUON_FEATURES in the site.mk. + +|image0| + +Allowed site variables +---------------------- + +Internally the site variables are merged from the ``site.conf`` and the +selected ``domain.conf``, so the most variables are also allowed in +``site.conf`` and in ``domain.conf``. But there are some exceptions, +which do not make sense in a domain or site specific way. The following +sections give an overview over variables that are only usable in either +site or domain context. + +site.conf only variables +^^^^^^^^^^^^^^^^^^^^^^^^ + +- Used in as initial default values, when the firmware was just flashed + and/or the config mode is skipped, so they do not make sense in a + domain specific way: + + - authorized_keys + - default_domain + - poe_passthrough + - mesh_on_wan + - mesh_on_lan + - single_as_lan + - setup_mode.skip + - autoupdater.branch + - mesh_vpn.enabled + - mesh_vpn.pubkey_privacy + - mesh_vpn.bandwidth_limit + - mesh_vpn.bandwidth_limit.enabled + - mesh_vpn.bandwidth_limit.ingress + - mesh_vpn.bandwidth_limit.egress + +- Variables that influence the appearance of the config mode, + domain-independent because they are relevant before a domain was selected. + + - config_mode.geo_location.show_altitude + - config_mode.hostname.optional + - config_mode.remote_login + - config_mode.remote_login.show_password_form + - config_mode.remote_login.min_password_length + - hostname_prefix + - mesh_vpn.fastd.configurable + - roles.default + - roles.list + +- Specific to a firmware build itself: + + - site_code + - site_name + - autoupdater.branches.*.name + - autoupdater.branches.*.good_signatures + - autoupdater.branches.*.pubkeys + +- We simply do not see any reason, why these variables could be helpful + in a domain specific way: + + - mesh_vpn.fastd.syslog_level + - wifi*.ibss.supported_basic_rates + - wifi*.mesh.supported_basic_rates + - timezone + - regdom + +domain.conf only variables +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Obviously: + + - domain_names + + - a table of domain codes to domain names + ``domain_names = { foo = 'Foo Domain', bar = 'Bar Domain', baz = 'Baz Domain' }`` + + - hide_domain + + - prevents a domain name(s) from appearing in config mode, either + boolean or array of domain codes + + - ``true``, ``false`` + - ``{ 'foo', 'bar' }`` + +- Because each domain is considered as an own layer 2 network, these + values should be different in each domain: + + - next_node.ip4 + - next_node.ip6 + - next_node.name + - prefix6 + - prefix4 + - extra_prefixes6 + +- To prevent accidential bridging of different domains, all meshing + technologies should be seperated: + + - domain_seed (wired mesh) + + - must be a random value used to derive the vxlan id for wired meshing + + - wifi*.ibss.ssid + - wifi*.ibss.bssid + - wifi*.mesh.id + - mesh_vpn.fastd.groups.*.peers.remotes + - mesh_vpn.fastd.groups.*.peers.key + - mesh_vpn.tunneldigger.brokers + +- Clients consider WiFi networks sharing the same ESSID as if they were + the same L2 network and try to reconfirm and reuse previous + addressing. If multiple neighbouring domains shared the same ESSID, + the roaming experience of clients would degrade. + + - wifi*.ap.ssid + +- Some values should be only set in legacy domains and not in new domains. + - mesh.vxlan + + - By default, this value is `true`. It should be only set to `false` + for one legacy domain, since vxlan prevents accidental wired + merges of domains. For old domains this value is still available + to keep compatibility between all nodes in one domain. + + - next_node.mac + + - For new domains, the default value should be used, since there is + no need for a special mac (or domain specific mac). For old domains + this value is still available to keep compatibility between all + nodes in one domain. + +Example config +-------------- + +site.mk +^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/site.mk + :language: makefile + +site.conf +^^^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/site.conf + :language: lua + +domains/alpha_centauri.conf +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/domains/alpha_centauri.conf + :language: lua + +i18n/en.po +^^^^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/i18n/en.po + :language: po + +i18n/de.po +^^^^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/i18n/de.po + :language: po + +modules +^^^^^^^ + +.. literalinclude:: ../multidomain-site-example/modules + :language: makefile + + +.. |image0| image:: multidomain_configmode.gif diff --git a/docs/features/multidomain_configmode.gif b/docs/features/multidomain_configmode.gif new file mode 100644 index 00000000..494840f5 Binary files /dev/null and b/docs/features/multidomain_configmode.gif differ diff --git a/docs/features/private-wlan.rst b/docs/features/private-wlan.rst index 343cd5c3..c047f8ae 100644 --- a/docs/features/private-wlan.rst +++ b/docs/features/private-wlan.rst @@ -4,17 +4,22 @@ Private WLAN It is possible to set up a private WLAN that bridges the WAN port and is seperated from the mesh network. Please note that you should not enable ``mesh_on_wan`` simultaneously. -The private WLAN can be enabled through the config mode if the package ``gluon-luci-private-wifi`` is installed. +The private WLAN can be enabled through the config mode if the package ``gluon-web-private-wifi`` is installed. You may also enable a private WLAN using the command line:: - uci set wireless.wan_radio0=wifi-iface - uci set wireless.wan_radio0.device=radio0 - uci set wireless.wan_radio0.network=wan - uci set wireless.wan_radio0.mode=ap - uci set wireless.wan_radio0.encryption=psk2 - uci set wireless.wan_radio0.ssid="$SSID" - uci set wireless.wan_radio0.key="$KEY" - uci set wireless.wan_radio0.disabled=0 + RID=0 + SSID="privateWLANname" + KEY="yoursecret1337password" + + uci set wireless.wan_radio$RID=wifi-iface + uci set wireless.wan_radio$RID.device=radio$RID + uci set wireless.wan_radio$RID.network=wan + uci set wireless.wan_radio$RID.mode=ap + uci set wireless.wan_radio$RID.encryption=psk2 + uci set wireless.wan_radio$RID.ssid="$SSID" + uci set wireless.wan_radio$RID.key="$KEY" + uci set wireless.wan_radio$RID.disabled=0 + uci set wireless.wan_radio$RID.macaddr="$($(echo "lua -e print(require('gluon.util').generate_mac(3+4*$RID))"))" uci commit wifi diff --git a/docs/features/roles.rst b/docs/features/roles.rst index 4cbf1f29..3af09c01 100644 --- a/docs/features/roles.rst +++ b/docs/features/roles.rst @@ -2,7 +2,7 @@ Roles ===== It is possible to define a set of roles you want to distinguish at backend side. One node can own one -role which it will announce via alfred inside the mesh. This will make it easier to differentiate +role which it will announce via alfred inside the mesh. This will make it easier to differentiate nodes when parsing alfred data. E.g to count only **normal** nodes and not the gateways or servers (nodemap). A lot of things are possible. @@ -11,18 +11,20 @@ For this the section ``roles`` in ``site.conf`` is needed:: roles = { default = 'node', list = { - node = 'Normal Node', - test = 'Test Node', - backbone = 'Backbone Node', - service = 'Service Node', + 'node', + 'test', + 'backbone', + 'service', }, }, +The strings to display in the web interface are configured per language in the +``i18n/en.po``, ``i18n/de.po``, etc. files of the site repository using message IDs like +``gluon-web-node-role:role:node`` and ``gluon-web-node-role:role:backbone``. + The value of ``default`` is the role every node will initially own. This value should be part of ``list`` as well. If you want node owners to change the defined roles via config-mode you can add the package -``gluon-luci-node-role`` to your ``site.mk``. Then, you can select one of the defined roles from a dropdown list -where the right-handed value is the one which is displayed and the left-handed key the one which is configured into -the system. +``gluon-web-node-role`` to your ``site.mk``. The role is saved in ``gluon-node-info.system.role``. To change the role using command line do:: diff --git a/docs/features/vpn.rst b/docs/features/vpn.rst new file mode 100644 index 00000000..81eef151 --- /dev/null +++ b/docs/features/vpn.rst @@ -0,0 +1,57 @@ +Mesh-VPN +======== + +Gluon integrates several OSI-Layer 2 tunneling protocols to +enable interconnects between local meshes and provide +internetwork access. Available protocols currently are: + +- fastd +- L2TPv3 (via tunneldigger) + +fastd is a lightweight userspace tunneling daemon, that +implements cipher suites that are specifically designed +to work well on embedded devices. It offers encryption +and authentication. Its primary drawback are the necessary +context-switches when forwarding packets. + +L2TPv3 is an in-kernel tunneling protocol that performs well, +but offers no security properties by itself. +The brokering of the tunnel happens through tunneldigger, +its primary drawback being the lack of IPv6 support. + +fastd +----- + +Configurable Cipher +^^^^^^^^^^^^^^^^^^^ + + +From the site configuration fastd can be allowed to offer +toggleable encryption in the config mode with the intent to +increase throughput, although in practice the gain is minimal. + +**Site configuration:** + +1) Install ``gluon-web-mesh-vpn-fastd`` in ``site.mk`` +2) Set ``mesh_vpn.fastd.configurable = true`` in ``site.conf`` + +**Gateway configuration:** + +1) Prepend the ``null`` cipher in fastd's method list + + +**Config Mode:** +The resulting firmware will allow users to choose between secure (encrypted) and fast (unencrypted) transport. + +.. image:: fastd_mode.gif + +**Unix socket:** +To confirm whether the correct cipher is being used, fastds unix +socket can be interrogated, after installing for example `socat`. + +:: + + opkg update + opkg install socat + socat - UNIX-CONNECT:/var/run/fastd.mesh_vpn.socket + diff --git a/docs/features/wired-mesh.rst b/docs/features/wired-mesh.rst index 77c7d6b3..efa1977a 100644 --- a/docs/features/wired-mesh.rst +++ b/docs/features/wired-mesh.rst @@ -1,8 +1,8 @@ Wired mesh (Mesh-on-WAN/LAN) -============================ +############################ In addition to meshing over WLAN and VPN, it is also possible to -configured wired meshing over the LAN or WAN ports. This allows +configure wired meshing over the LAN or WAN ports. This allows nodes to be connected directly or over wireless bridges. Mesh-on-WAN can be enabled in addition to the mesh VPN, so multiple nodes @@ -11,55 +11,77 @@ Enabling Mesh-on-WAN should be avoided if the local network is also bridged with a WLAN access point, as meshing over batman-adv causes large amounts of multicast traffic, which will take up a lot of airtime. -Enabling Mesh-on-LAN will replace the normal "client network" function +Enabling Mesh-on-LAN replaces the normal "client network" function of the LAN ports, as client network ports may never be connected (so care must be taken to always enable Mesh-on-LAN before connecting two nodes' LAN ports). +Wired mesh encapsulation +************************ + +Since version 2018.1, Gluon supports encapsulating wired mesh traffic in +`VXLAN `_, a new standard with +usecases similar to VLANs, but a much greater ID space of 24bit; in addition, VXLAN +packets pass through VLAN-aware switches without any special configuration. + +Encapsulating mesh traffic has two advantages: + +* By using a different VXLAN ID for each site and mesh domain, accidental + wired mesh connections between nodes of different domains will be prevented. + This has special importance when nodes migrate between domains automatically, + as currently possible through different site-specific packages. +* While batman-adv traffic does not interact with non-mesh traffic in the same wired + network in any way (so Gluon nodes can mesh over existing wired networks), this is + not the case for layer 3 mesh protocols like Babel. Encapsulating the traffic allows + to distinguish mesh traffic from unrelated packets. + +As enabling VXLAN encapsulation will prevent wired mesh communication with old nodes +that do not support VXLAN yet, VXLANs can be enabled per-domain using the site configuration +setting *mesh.vxlan*. VXLAN is enabled by default in multidomain setups; in single-domain +site configurations, the *mesh.vxlan* setting is mandatory. We recommend to enable +VXLAN encapsulation in all new sites and domains. + +Non-encapsulated ("legacy") wired meshing will be removed in a future Gluon release. +We cannot give a concrete timeframe for the removal yet; a missing prerequisite is the +implementation of a robust migration path for existing deployments. + Configuration -~~~~~~~~~~~~~ +************* Both Mesh-on-WAN and Mesh-on-LAN can be configured on the "Network" page -of the *Expert Mode* (if the package ``gluon-luci-portconfig`` is installed). +of the *Advanced settings* (if the package ``gluon-web-network`` is installed). It is also possible to enable Mesh-on-WAN and Mesh-on-LAN by default by adding ``mesh_on_wan = true`` and ``mesh_on_lan = true`` to ``site.conf``. -Commandline configuration -------------------------- +Commandline +=========== -Mesh-on-WAN -........... +Enable Mesh-on-WAN:: -It's possible to enable Mesh-on-WAN like this:: + uci set network.mesh_wan.disabled=0 + uci commit network - uci set network.mesh_wan.auto=1 - uci commit +Disable Mesh-on-WAN:: -It may be disabled by running:: + uci set network.mesh_wan.disabled=1 + uci commit network - uci set network.mesh_wan.auto=0 - uci commit +Enable Mesh-on-LAN:: - -Mesh-on-LAN -........... - -Configuring Mesh-on-LAN is a bit more complicated:: - - uci set network.mesh_lan.auto=1 + uci set network.mesh_lan.disabled=0 for ifname in $(cat /lib/gluon/core/sysconfig/lan_ifname); do uci del_list network.client.ifname=$ifname done - uci commit + uci commit network -It may be disabled by running:: +Disable Mesh-on-LAN:: - uci set network.mesh_lan.auto=0 + uci set network.mesh_lan.disabled=1 for ifname in $(cat /lib/gluon/core/sysconfig/lan_ifname); do uci add_list network.client.ifname=$ifname done - uci commit + uci commit network -Please note that this configuration has changed in Gluon v2016.1. Using -the old commands on v2016.1 will break the corresponding Expert Mode -settings. +Please note that this configuration has changed in Gluon 2016.1. Using +the old commands on 2016.1 and later will break the corresponding options +in the *Advanced settings*. diff --git a/docs/features/wlan-configuration.rst b/docs/features/wlan-configuration.rst index 1c1e3e54..445b4bf1 100644 --- a/docs/features/wlan-configuration.rst +++ b/docs/features/wlan-configuration.rst @@ -13,7 +13,7 @@ Upgrade behaviour For each of these networks, the site configuration may define a `disabled` flag (by default, all configured networks are enabled). This flag is merely a default setting, on upgrades the existing setting is always retained (as this setting may have been changed -by the user). This means that is is not possible to enable or disable an existing network +by the user). This means that it is not possible to enable or disable an existing network configurations during upgrades. For the "mesh" and "ibss" networks, the default setting only has an effect if none diff --git a/docs/index.rst b/docs/index.rst index 242e96bc..b4e97793 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,10 +5,8 @@ Gluon is a modular framework for creating OpenWrt-based firmwares for wireless m Several Freifunk communities in Germany use Gluon as the foundation of their Freifunk firmwares. -User Documentation ------------------- - .. toctree:: + :caption: User Documentation :maxdepth: 2 user/getting_started @@ -16,10 +14,8 @@ User Documentation user/x86 user/faq -Features --------- - .. toctree:: + :caption: Features :maxdepth: 2 features/configmode @@ -27,40 +23,72 @@ Features features/wlan-configuration features/private-wlan features/wired-mesh + features/dns-forwarder features/monitoring + features/multidomain features/authorized-keys features/roles - -Developer Documentation ------------------------ + features/vpn .. toctree:: + :caption: Developer Documentation :maxdepth: 2 dev/basics dev/hardware + dev/packages dev/upgrade - dev/configmode dev/wan - dev/i18n - -Packages --------- + dev/mac_addresses + dev/site_library .. toctree:: + :caption: gluon-web Reference + :maxdepth: 1 + + dev/web/controller + dev/web/model + dev/web/view + dev/web/i18n + dev/web/config-mode + +.. toctree:: + :caption: Packages :maxdepth: 1 package/gluon-client-bridge - package/gluon-config-mode-geo-location + package/gluon-config-mode-domain-select package/gluon-ebtables-filter-multicast package/gluon-ebtables-filter-ra-dhcp - -Releases --------- + package/gluon-ebtables-limit-arp + package/gluon-ebtables-source-filter + package/gluon-radv-filterd + package/gluon-web-admin + package/gluon-web-logging .. toctree:: + :caption: Releases :maxdepth: 1 + releases/v2018.1 + releases/v2017.1.8 + releases/v2017.1.7 + releases/v2017.1.6 + releases/v2017.1.5 + releases/v2017.1.4 + releases/v2017.1.3 + releases/v2017.1.2 + releases/v2017.1.1 + releases/v2017.1 + releases/v2016.2.7 + releases/v2016.2.6 + releases/v2016.2.5 + releases/v2016.2.4 + releases/v2016.2.3 + releases/v2016.2.2 + releases/v2016.2.1 + releases/v2016.2 + releases/v2016.1.6 releases/v2016.1.5 releases/v2016.1.4 releases/v2016.1.3 @@ -88,34 +116,40 @@ ar71xx-generic * ALFA Network - AP121 + - AP121F - AP121U - Hornet-UB + - Tube2H + - N2 + - N5 * Allnet - ALL0315N +* AVM + + - Fritz!Box 4020 + * Buffalo - WZR-HP-AG300H / WZR-600DHP - WZR-HP-G300NH + - WZR-HP-G300NH2 - WZR-HP-G450H -* Cisco Meraki - - - MR12 / MR62 - - MR16 / MR66 - * D-Link - - DIR-505 (A1) - - DIR-615 (C1) + - DIR-505 (A1, A2) - DIR-825 (B1) -* GL-Inet +* GL Innovations - - 6408A (v1) - - 6416A (v1) + - GL-AR150 + - GL-AR300M + - GL-AR750 [#ath10k]_ + - GL-iNet 6408A (v1) + - GL-iNet 6416A (v1) * Linksys @@ -123,7 +157,7 @@ ar71xx-generic * Netgear - - WNDR3700 (v1, v2) + - WNDR3700 (v1, v2, v5) - WNDR3800 - WNDRMAC (v2) @@ -133,65 +167,59 @@ ar71xx-generic * OpenMesh - - MR1750 - - MR600 (v1, v2) - - MR900 (v1, v2) - - OM2P (v1, v2) - - OM2P-HS (v1, v2) - - OM2P-LC - - OM5P - - OM5P-AC (v1, v2) - - OM5P-AN + - A40 + - A60 + - MR600 (v1, v2) + - MR900 (v1, v2) + - MR1750 (v1, v2) [#ath10k]_ + - OM2P (v1, v2, v4) + - OM2P-HS (v1, v2, v3, v4) + - OM2P-LC + - OM5P + - OM5P-AN + - OM5P-AC (v1, v2) [#ath10k]_ * TP-Link - - CPE210 (v1.0, v1.1) - - CPE220 (v1.0, v1.1) + - Archer C5 (v1) [#ath10k]_ + - Archer C59 (v1) [#80211s]_ + - Archer C7 (v2, v4) [#ath10k]_ + - CPE210 (v1.0, v1.1, v2.0) + - CPE220 (v1.1) - CPE510 (v1.0, v1.1) - - CPE520 (v1.0, v1.1) - - TL-MR13U (v1) - - TL-MR3020 (v1) - - TL-MR3040 (v1, v2) - - TL-MR3220 (v1, v2) - - TL-MR3420 (v1, v2) - - TL-WA701N/ND (v1, v2) - - TL-WA750RE (v1) - - TL-WA7510N (v1) - - TL-WA801N/ND (v1, v2) - - TL-WA830RE (v1, v2) - - TL-WA850RE (v1) - - TL-WA860RE (v1) - - TL-WA901N/ND (v1, v2, v3) + - CPE520 (v1.1) + - RE450 [#ath10k]_ - TL-WDR3500 (v1) - TL-WDR3600 (v1) - TL-WDR4300 (v1) - - TL-WR703N (v1) - - TL-WR710N (v1, v2) - - TL-WR740N (v1, v3, v4, v5) - - TL-WR741N/ND (v1, v2, v4, v5) - - TL-WR743N/ND (v1, v2) - - TL-WR801N/ND (v1, v2) - - TL-WR841N/ND (v3, v5, v7, v8, v9, v10, v11) - - TL-WR842N/ND (v1, v2) - - TL-WR843N/ND (v1) - - TL-WR940N (v1, v2, v3) - - TL-WR941ND (v2, v3, v4, v5, v6) - - TL-WR1043N/ND (v1, v2, v3) + - TL-WR710N (v1, v2.1) + - TL-WR842N/ND (v1, v2, v3) + - TL-WR1043N/ND (v1, v2, v3, v4, v5) - TL-WR2543N/ND (v1) + - WBS210 (v1.20) + - WBS510 (v1.20) * Ubiquiti - Air Gateway + - Air Gateway LR + - Air Gateway PRO - Air Router - - Bullet M - - Loco M - - Loco M XW - - Nanostation M - - Nanostation M XW - - Picostation M - - Rocket M - - Rocket M XW + - Bullet M2/M5 + - Loco M2/M5 + - Loco M2/M5 XW + - Nanostation M2/M5 + - Nanostation M2/M5 XW + - Picostation M2/M5 + - Rocket M2/M5 + - Rocket M2/M5 Ti + - Rocket M2/M5 XW + - UniFi AC Mesh [#ath10k]_ - UniFi AP + - UniFi AP AC Lite [#ath10k]_ + - UniFi AP AC LR [#ath10k]_ + - UniFi AP AC Pro [#ath10k]_ + - UniFi AP LR - UniFi AP Pro - UniFi AP Outdoor - UniFi AP Outdoor+ @@ -209,6 +237,61 @@ ar71xx-nand - WNDR3700 (v4) - WNDR4300 (v1) +* ZyXEL + + - NBG6716 [#ath10k]_ + +ar71xx-tiny +^^^^^^^^^^^ + +* D-Link + + - DIR-615 (C1) + +* TP-Link + + - TL-MR13U (v1) + - TL-MR3020 (v1) + - TL-MR3040 (v1, v2) + - TL-MR3220 (v1, v2) + - TL-MR3420 (v1, v2) + - TL-WA701N/ND (v1, v2) + - TL-WA730RE (v1) + - TL-WA750RE (v1) + - TL-WA801N/ND (v1, v2, v3) + - TL-WA830RE (v1, v2) + - TL-WA850RE (v1) + - TL-WA860RE (v1) + - TL-WA901N/ND (v1, v2, v3, v4, v5) + - TL-WA7210N (v2) + - TL-WA7510N (v1) + - TL-WR703N (v1) + - TL-WR710N (v1, v2, v2.1) + - TL-WR740N (v1, v3, v4, v5) + - TL-WR741N/ND (v1, v2, v4, v5) + - TL-WR743N/ND (v1, v2) + - TL-WR841N/ND (v3, v5, v7, v8, v9, v10, v11, v12) + - TL-WR843N/ND (v1) + - TL-WR940N (v1, v2, v3, v4, v5, v6) + - TL-WR941ND (v2, v3, v4, v5, v6) + +brcm2708-bcm2708 +^^^^^^^^^^^^^^^^ + +* RaspberryPi 1 + +brcm2708-bcm2709 +^^^^^^^^^^^^^^^^ + +* RaspberryPi 2 + +ipq806x +^^^^^^^ + +* TP-Link + + - Archer C2600 [#80211s]_ + mpc85xx-generic ^^^^^^^^^^^^^^^ @@ -216,34 +299,87 @@ mpc85xx-generic - TL-WDR4900 (v1) +ramips-mt7620 +^^^^^^^^^^^^^ + +* GL Innovations + + - GL-MT300A [#80211s]_ + - GL-MT300N [#80211s]_ + - GL-MT750 [#80211s]_ + +ramips-mt7621 +^^^^^^^^^^^^^ + +* Ubiquiti + + - EdgeRouter X + - EdgeRouter X-SFP + +ramips-mt7628 +^^^^^^^^^^^^^ + +* VoCore + + - VoCore2 [#80211s]_ + +ramips-rt305x +^^^^^^^^^^^^^ + +* A5-V11 [#80211s]_ + +* D-Link + + - DIR-615 (D1, D2, D3, D4, H1) [#80211s]_ + +* VoCore + + - VoCore (8M) [#80211s]_ + - VoCore (16M) [#80211s]_ + +sunxi +^^^^^ + +* LeMaker + + - Banana Pi M1 + x86-generic ^^^^^^^^^^^ + * x86-generic * x86-virtualbox * x86-vmware See also: :doc:`user/x86` -x86-kvm_guest -^^^^^^^^^^^^^ -* x86-kvm +x86-geode +^^^^^^^^^ -See also: :doc:`user/x86` - -x86-xen_domu -^^^^^^^^^^^^ -* x86-xen +* x86-geode See also: :doc:`user/x86` x86-64 ^^^^^^ + * x86-64-generic * x86-64-virtualbox * x86-64-vmware See also: :doc:`user/x86` +Footnotes +^^^^^^^^^ + +.. [#ath10k] + Device uses the ath10k WLAN driver; images are built for 11s by default unless GLUON_WLAN_MESH + is set as described in :ref:`getting-started-make-variables` + +.. [#80211s] + Device does not support IBSS; images are built by default unless GLUON_WLAN_MESH + is explicitly set to something other than *11s* + License ------- diff --git a/docs/multidomain-site-example/domains/alpha_centauri.conf b/docs/multidomain-site-example/domains/alpha_centauri.conf new file mode 100644 index 00000000..4ce763c6 --- /dev/null +++ b/docs/multidomain-site-example/domains/alpha_centauri.conf @@ -0,0 +1,62 @@ +{ + -- multiple codes/names can be defined, the first one is the primary name + -- additional aliases can be defined + domain_names = { + alpha_centauri = 'Alpha Centauri', + rigil_kentaurus = 'Rigil Kentaurus', + proxima_centauri = 'Proxima Centauri', + }, + + -- 32 byte random data in hexadecimal encoding + -- This data must be unique among all sites and domains! + -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' >' "$2" +# to decide if a version is newer or not. + +DEFAULT_GLUON_RELEASE := 0.6+exp$(shell date '+%Y%m%d') + +# Variables set with ?= can be overwritten from the command line + +## GLUON_RELEASE +# call make with custom GLUON_RELEASE flag, to use your own release version scheme. +# e.g.: +# $ make images GLUON_RELEASE=23.42+5 +# would generate images named like this: +# gluon-ff%site_code%-23.42+5-%router_model%.bin + +GLUON_RELEASE ?= $(DEFAULT_GLUON_RELEASE) + +# Default priority for updates. +GLUON_PRIORITY ?= 0 + +# Region code required for some images; supported values: us eu +GLUON_REGION ?= eu + +# Languages to include +GLUON_LANGS ?= en de diff --git a/docs/package/gluon-config-mode-domain-select.rst b/docs/package/gluon-config-mode-domain-select.rst new file mode 100644 index 00000000..4ca12217 --- /dev/null +++ b/docs/package/gluon-config-mode-domain-select.rst @@ -0,0 +1,19 @@ +gluon-config-mode-domain-select +=============================== +This package provides a drop-down list for the config mode to select the domain +the node will be placed in. If the selection has changed the upgrade scripts in +``/lib/gluon/upgrade/`` are triggered to update the nodes configuration. + +Hiding domains could be useful for default or testing domains, which should not +be accidentally selected by a node operater. + +domains/\*.conf +--------------- + +hide_domain \: optional (defaults to false) + - ``false`` shows this domain in drop-down list + - ``true`` hides this domain + +Example:: + + hide_domain = true diff --git a/docs/package/gluon-config-mode-geo-location.rst b/docs/package/gluon-config-mode-geo-location.rst deleted file mode 100644 index 83ca238b..00000000 --- a/docs/package/gluon-config-mode-geo-location.rst +++ /dev/null @@ -1,14 +0,0 @@ -gluon-config-mode-geo-location -============================== - -This package enables the user to set latitude, longitude and altitude of their -node within config mode. As the usage of the altitude is not well defined the -corresponding field can be disabled. - -site.conf ---------- - -config_mode.geo_location.show_altitude : optional - - ``true`` enables the altitude field - - ``false`` disables the altitude field if altitude has not yet been set - - defaults to ``true`` diff --git a/docs/package/gluon-ebtables-limit-arp.rst b/docs/package/gluon-ebtables-limit-arp.rst new file mode 100644 index 00000000..5a71de19 --- /dev/null +++ b/docs/package/gluon-ebtables-limit-arp.rst @@ -0,0 +1,23 @@ +gluon-ebtables-limit-arp +======================== + +The *gluon-ebtables-limit-arp* package adds filters to limit the +amount of ARP requests client devices are allowed to send into the +mesh. + +The limits per client device, identified by its MAC address, are +6 packets per minute and 1 per second per node in total. +A burst of up to 50 ARP requests is allowed until the rate-limiting +takes effect (see ``--limit-burst`` in ``ebtables(8)``). + +Furthermore, ARP requests for a target IP already present in the +batman-adv DAT cache are excluded from rate-limiting, in regard +to both counting and filtering, as batman-adv will be able +to respond locally without a burden for the mesh. Therefore, this +limiter should not affect popular target IP addresses, like those +of gateways or nameservers. + +However it mitigates the impact on the mesh when a larger range of +its IPv4 subnet is being scanned, which would otherwise result in +a significant amount of ARP chatter, even for unused IP addresses. + diff --git a/docs/package/gluon-ebtables-source-filter.rst b/docs/package/gluon-ebtables-source-filter.rst new file mode 100644 index 00000000..1bbb2e07 --- /dev/null +++ b/docs/package/gluon-ebtables-source-filter.rst @@ -0,0 +1,33 @@ +gluon-ebtables-source-filter +============================ + +The *gluon-ebtables-source-filter* package adds an additional layer-2 filter +ruleset to prevent unreasonable traffic entering the network via the nodes. +Unreasonable means traffic entering the mesh via a node which source IP does +not belong to the configured IP space. + +You may first check if there is a certain proportion of unreasonable traffic, +before adding this package to the firmware image. Furthermore, you should not +use this package if some kind of gateway or upstream network is provided by +a device connected to the client port. + +site.conf +--------- + +prefix4 : optional + - IPv4 subnet + +prefix6 : + - IPv6 subnet + +extra_prefixes6 : optional + - list of additional IPv6 subnets + +Example:: + + prefix4 = '198.51.100.0/21', + prefix6 = '2001:db8:8::/64', + extra_prefixes6 = { + '2001:db8:9::/64', + '2001:db8:100::/60', + }, diff --git a/docs/package/gluon-radv-filterd.rst b/docs/package/gluon-radv-filterd.rst new file mode 100644 index 00000000..88949611 --- /dev/null +++ b/docs/package/gluon-radv-filterd.rst @@ -0,0 +1,61 @@ +gluon-radv-filterd +================== + +This package drops all incoming router advertisements except for the +default router with the best metric according to B.A.T.M.A.N. advanced. + +Note that advertisements originating from the node itself (for example +via gluon-radvd) are not affected and considered at all. + +Selected router +--------------- + +The router selection mechanism is independent from the batman-adv gateway mode. +In contrast, the device originating the router advertisment could be any router +or client connected to the mesh, as radv-filterd captures all router +advertisements originating from it. All nodes announcing router advertisement +**with** a default lifetime greater than 0 are being considered as candidates. + +In case a router is not a batman-adv originator itself, its TQ is defined by +the originator it is connected to. This lookup uses the batman-adv global +translation table. + +Initially the router is the selected by choosing the candidate with the +strongest TQ. When another candidate can provide a better TQ metric it is not +picked up as the selected router until it will outperform the currently +selected router by X metric units. The hysteresis threshold is configurable +and prevents excessive flapping of the gateway. + +"Local" routers +--------------- + +The package has functionality to select "local" routers, i.e. those connected +via cable or WLAN instead of via the mesh (technically: appearing in the +``transtable_local``), a fake TQ of 512 so that they are always preferred. +However, if used together with the :doc:`gluon-ebtables-filter-ra-dhcp` +package, these router advertisements are filtered anyway and reach neither the +node nor any other client. You currently have to disable the package or insert +custom ebtables rules in order to use local routers. + +respondd module +--------------- + +This package also contains a module for respondd that announces the currently +selected router via the ``statistics.gateway6`` property using its interface MAC +address. Note that this is different from the ``statistics.gateway`` property, +which contains the MAC address of the main B.A.T.M.A.N. adv slave interface of +the selected IPv4 gateway. + +site.conf +--------- + +radv_filterd.threshold : optional + - minimal difference in TQ value that another gateway has to be better than + the currently chosen gateway to become the new chosen gateway + - defaults to ``20`` + +Example:: + + radv_filterd = { + threshold = 20, + } diff --git a/docs/package/gluon-web-admin.rst b/docs/package/gluon-web-admin.rst new file mode 100644 index 00000000..efdab02f --- /dev/null +++ b/docs/package/gluon-web-admin.rst @@ -0,0 +1,29 @@ +gluon-web-admin +=============== + +This package allows the user to set options like the password for ssh access +within config mode. You can define in your ``site.conf`` whether it should be +possible to access the nodes via ssh with a password or not and what the mimimum +password length must be. + +site.conf +--------- + +config_mode.remote_login.show_password_form \: optional + - ``true`` the password section in config mode is shown + - ``false`` the password section in config mode is hidden + - defaults to ``false`` + +config_mode.remote_login.min_password_length \: optional + - sets the minimum allowed password length. Set this to ``1`` to disable the + length check. + - defaults to ``12`` + +Example:: + + config_mode = { + remote_login = { + show_password_form = true, -- default false + min_password_length = 12 + } + } diff --git a/docs/package/gluon-web-logging.rst b/docs/package/gluon-web-logging.rst new file mode 100644 index 00000000..ddb9f573 --- /dev/null +++ b/docs/package/gluon-web-logging.rst @@ -0,0 +1,5 @@ +gluon-web-logging +================= + +The *gluon-web-logging* package adds a new section to advanced settings +to allow GUI-based configuration of a remote syslog server. diff --git a/docs/releases/v2016.1.6.rst b/docs/releases/v2016.1.6.rst new file mode 100644 index 00000000..e9f97838 --- /dev/null +++ b/docs/releases/v2016.1.6.rst @@ -0,0 +1,55 @@ +Gluon 2016.1.6 +============== + +Bugfixes +~~~~~~~~ + +* build: fix nodejs host build on Debian Wheezy (`#776 `_) +* build: fix parallel builds with Make 4.2+ + + Trying to use ``-j N`` with Make 4.2 would spawn an unlimited number of processes, + eventually leading to memory exhaustion. + +* build: fix occasional build failure in libpcap package +* build: don't require hexdump for x86 builds (`#811 `_) + + Trying to build Gluon for x86 on systems without hexdump would silently generate + broken images. + +* Add support for DNS servers given by their link-local IPv6 address in Router Advertisements + (`#854 `_) + +* ar71xx-generic: correctly setup LNA GPIOs on CPE210/510 (`#796 `_) + + Improves the reception by about 20dB. + +* ar71xx-generic: switch default WAN/LAN assignment on Ubiquiti UAP Pro + (`#764 `_) + + Switch to the usual "PoE is WAN/setup mode, secondary is LAN" scheme. This only affects + new installations; the assignment won't be changed on updates unless the configuration is + reset. + +* ar71xx-generic: fix ath10k memory leak (`#690 `_) +* ar71xx-generic: add support for new TP-Link region codes + (`#860 `_) + + TP-Link has started providing US- and EU-specific firmwares for the Archer C7 v2. To generate + Gluon images installable from these new firmwares, the ``GLUON_REGION`` variable must be set + to ``eu`` or ``us`` in ``site.mk`` or on the ``make`` command line (the images will still be + installable from all old firmwares without region codes). + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Expert Mode is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.1.rst b/docs/releases/v2016.1.rst index 5a42a1eb..94229c5a 100644 --- a/docs/releases/v2016.1.rst +++ b/docs/releases/v2016.1.rst @@ -175,9 +175,9 @@ Site changes mesh_vpn = { ifname = 'mesh-vpn', enabled = false, - limit_ingress = 3000, limit_egress = 200, - } + limit_ingress = 3000, + }, } needs to be changed to @@ -189,8 +189,8 @@ Site changes bandwidth_limit = { enabled = false, - ingress = 3000, egress = 200, + ingress = 3000, }, } diff --git a/docs/releases/v2016.2.1.rst b/docs/releases/v2016.2.1.rst new file mode 100644 index 00000000..2f71205c --- /dev/null +++ b/docs/releases/v2016.2.1.rst @@ -0,0 +1,59 @@ +Gluon 2016.2.1 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link + + - TL-WA901ND v4 + +Bugfixes +~~~~~~~~ + +* Make status page work with disabled cookies/local storage + (`#912 `_) + +* Update kernel to 3.18.44 + + Fixes CVE-2016-5195 and CVE-2016-7117. It is unlikely that these issues pose + a threat to usual Gluon setups, but installing additional packages may make a + system vulnerable. In any case, updating is highly recommended. + +* Downgrade mac80211 to an earlier state + + Unfortunately, a mac80211 update that was done shortly before the release of + Gluon v2016.2 (that seemed necessary to properly support ath10k devices) had + again caused severe ath9k stability issues that remained unreported until v2016.2 + was out. + + We have now reverted mac80211 to an earlier state that was reported to be very + stable (while keeping the ath10k-specific changes); in addition, some patches + that were reported to cause connection or performance issues with certain clients + have been reverted. While is it still not perfectly stable, is should be at least + as good as (and probably better than) the v2016.1.x release series. + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Git HTTPS downloads from git.kernel.org fail on Debian Wheezy (`#919 `_) + + The GnuTLS version on Debian Wheezy is too old and can't establish a connection with + git.kernel.org anymore. A newer GnuTLS version is available in wheezy-backports, but + as there is no libcurl3-gnutls package linked against the new version, installing the + new version has no effect. diff --git a/docs/releases/v2016.2.2.rst b/docs/releases/v2016.2.2.rst new file mode 100644 index 00000000..fe054f54 --- /dev/null +++ b/docs/releases/v2016.2.2.rst @@ -0,0 +1,78 @@ +Gluon 2016.2.2 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link + + - CPE210/510 EU/US versions + - TL-WA801N/ND v3 + - TL-WR841ND v11 EU/US versions + +Bugfixes +~~~~~~~~ + +* Fix boot on certain QCA955x-based devices (e.g. OpenMesh OM5P AC v2) (`#965 `_) + + This issue was a regression in Gluon v2016.2.1. + +* Build: Fix git downloads from git.kernel.org on Debian Wheezy (`#919 `_) + + We've switched back from HTTPS to the git protocol for now to avoid using + the old GnuTLS version of Debian Wheezy which can't establish a HTTPS connection + with git.kernel.org anymore. + + This issue was a regression in Gluon v2016.2. + +* Fix RX filter of Ubiquiti UAP Outdoor+ (`d43147a8e03d `_) + + This issue was a regression in Gluon v2016.2. + +* Fix switched WAN/LAN interface assignment on CPE210 (`59deb2064d54 `_) + + This issue was a regression in Gluon v2016.2. + +* Significantly reduce CPU load used by signal strength LEDs (`#897 `_) + +* Fix ethernet port of the Ubiquiti UAP AC Lite (`#911 `_) + +* Build: Don't use host ``/tmp`` directory (`f9072a36411b `_) + + Fixes build when ``/tmp`` is mounted with *noexec*. + +* Fix mesh interface type respondd/alfred announcements when using VLANs over IBSS (`#941 `_) + +* Fix next-node ebtables rules without *next_node.ip4* (`9dbe9f785d2b `_) + + Gluon v2016.2 added support for using the next-node feature without specifying an IPv4 + address. Some scripts had not been adjusted, making the next-node unreliable when + no IPv4 address was specified. + +Other changes +~~~~~~~~~~~~~ + +* x86-generic and x86-64 images now have PATA and MMC support to allow using them + on various devices that were previously unsupported. + +* Clean up opkg postinst scripts up on image generation + + OpenWrt does this by default to save a little space. + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.3.rst b/docs/releases/v2016.2.3.rst new file mode 100644 index 00000000..dacd5cd2 --- /dev/null +++ b/docs/releases/v2016.2.3.rst @@ -0,0 +1,62 @@ +Gluon 2016.2.3 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link TL-WR940N v4 +* TP-Link TL-WR1043ND v4 + +Removed hardware support +~~~~~~~~~~~~~~~~~~~~~~~~ + +Support for Meraki devices (MR12/16/62/66) has been removed for now because of +severe problems (all devices were using the same MAC addresses). Support will return +when the issues have been fixed. + +Bugfixes +~~~~~~~~ + +* Automatically restart respondd on failure (`#863 `_) + + There have been many reports of respondd processes disappearing; the exact cause is unclear, + but might be related to the batman-adv debugfs interface and/or out-of-memory conditions. + + A new respondd initscript uses procd to automatically restart respondd when it dies. + +* Make autoupdater timeouts more robust (`#987 `_) + + It was reported that wget processes sometimes hang indefinitely during the autoupdater manifest + download. The autoupdater has been improved to ensure that wget can always be interrupted after + a timeout. + + This issue, together with the recent addition of lock files to ensure that only one instance + of the autoupdater can run at a time, had caused the autoupdater to blocked completely + by hanging processes in some cases (till a node was rebooted). + +* Fix regulation domain switching in ath10k (`#1001 `_) + + Prevents use of too high transmission power in some cases. + +* Ensure that *prefix6* in site.conf is always a /64 prefix (`6b62e2f `_) + + Other prefix lengths were never supported and don't make sense in many places the prefix is used. Ensure + that such configurations will not pass validation. + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.4.rst b/docs/releases/v2016.2.4.rst new file mode 100644 index 00000000..4fb06026 --- /dev/null +++ b/docs/releases/v2016.2.4.rst @@ -0,0 +1,55 @@ +Gluon 2016.2.4 +============== + +Bugfixes +~~~~~~~~ + +* Fix batman-adv (compat 15) not being able to transmit packages of specific sizes (`b7eeef9 `_) + + We suspect that this issue was also the reason for the autoupdater/wget hangs observed by many communities. + Non-Gluon nodes like gateways should be updated to batman-adv 2017.0.1 to get the fix. + +* Fix build after ftp.all.kernel.org discontinuation (`#1059 `_) + +* Fix high load because of frequent calls of the respondd initscript (`9a0aeb9 `_) + + The respondd restart triggers added in v2016.2.3 ran a significant portion of the respondd initscript for each router advertisement + received. This was fixed by a backport of a netifd patch. + +* x86 sysupgrade fixes (`41fd50d `_, + `ad37e2b `_) + + This fixes sysupgrade on mmcblk and similar devices. + +Other changes +~~~~~~~~~~~~~ + +* The manifest generator has been extended to generate SHA256 checksums in addition to SHA512 ones + (`f9d59be `_) + + We have recently switched the autoupdater to SHA256 in the Gluon master to avoid mixing two different + lengths of hashes for no good reason. This makes the manifests of Gluon v2016.2.x compatible with the + new autoupdater so it doesn't prevent backports or downgrades. + + **Note:** Downgrades of major Gluon versions are generally unsupported and will often lead to + broken configurations. + +Known Issues +~~~~~~~~~~~~ + +* x86 sysupgrade (sometimes) loses config when kernel partition grows (`#1010 `_) + + This issue affects upgrades from v2016.2.x and older to the Gluon master only, we hope to fix it before the next + major release. + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.5.rst b/docs/releases/v2016.2.5.rst new file mode 100644 index 00000000..07a27f0c --- /dev/null +++ b/docs/releases/v2016.2.5.rst @@ -0,0 +1,36 @@ +Gluon 2016.2.5 +============== + +This version contains only a single bugfix for a regression introduced in Gluon v2016.2.4. +As the regression affects batman-adv compat 15 only, firmwares using the compat 14 legacy +version don't need to be updated. + +Bugfixes +~~~~~~~~ + +* Fix kernel crash with batman-adv compat 15 (`d452a7c `_) + + An incorrect backport of a fix for a very improbable kernel crash caused a much more + frequent kernel crash. The backport has been fixed. + + This bug a regression in Gluon v2016.2.4. + +Known Issues +~~~~~~~~~~~~ + +* x86 sysupgrade (sometimes) loses config when kernel partition grows (`#1010 `_) + + This issue affects upgrades from v2016.2.x and older to the Gluon master only, we hope to fix it before the next + major release. + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.6.rst b/docs/releases/v2016.2.6.rst new file mode 100644 index 00000000..fac3f13d --- /dev/null +++ b/docs/releases/v2016.2.6.rst @@ -0,0 +1,57 @@ +Gluon 2016.2.6 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link TL-WR841N/ND v12 + +Bugfixes +~~~~~~~~ + +* Fix `CVE-2016-10229 `_ + (`#1097 `_) + + Fortunately, the standard Gluon setup is not vulnerable, as the issue only affects + applications that use MSG_PEEK on UDP sockets. dnsmasq does use MSG_PEEK, but + only in the DHCP component, which is not enabled during normal node operation. + +* Fix roaming issue affecting communication between clients + (`#1121 `_) + + This issue affects all previous releases of Gluon v2016.2.x. + +* Fix build against OpenSSL 1.1 (`b6a22ce `_) + +* Fix build with long path names (`#1120 `_) + +* Use new staged sysupgrade procedure (`d4a69c0 `_) + + The new sysupgrade fixes an issue affecting x86, causing nodes to lose their + configuration on upgrade when the size of the kernel partition grows. This is + the case when upgrading from Gluon v2016.2.x to newer (LEDE-based) Gluon + versions. **This means that a Gluon node running an older version must be + upgraded to Gluon v2016.2.6 first before switching to a LEDE-based version!** + + One downside of the staged sysupgrade is that all processes, including the SSH + server, will be terminated at the start of the sysupgrade to allow unmounting + the root filesystem. This makes it impossible to get any feedback from the + upgrade process without a serial console. + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.7.rst b/docs/releases/v2016.2.7.rst new file mode 100644 index 00000000..88e809ab --- /dev/null +++ b/docs/releases/v2016.2.7.rst @@ -0,0 +1,31 @@ +Gluon 2016.2.7 +============== + +This release only fixes a single regression introduced in Gluon v2016.2.6, and +add support for building using Perl 5.26. + +Bugfixes +~~~~~~~~ + +* Improve sysupgrade error handling (`#1160 `_) + + If for some reason processes don't react to SIGKILL (usually because of a kernel bug), + a node could hang forever in sysupgrade, requiring a power cycle. This has been + fixed, triggering a reboot instead. + +* Backport fixes to support building with Perl 5.26 or newer (`76753ed `_) + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2016.2.rst b/docs/releases/v2016.2.rst new file mode 100644 index 00000000..7693e447 --- /dev/null +++ b/docs/releases/v2016.2.rst @@ -0,0 +1,179 @@ +Gluon 2016.2 +============ + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* ALFA Network + + - Tube2H + - N2 + - N5 + +* Buffalo + + - WZR-HP-G300NH2 + +* GL Innovations + + - GL-AR150 + +* OpenMesh + + - MR1750 v1, v2 [#ath10k]_ + - OM2P-HS v3 + - OM5P-AC v1, v2 [#ath10k]_ + +* TP-Link + + - Archer C5 v1 [#ath10k]_ + - Archer C7 v2 [#ath10k]_ + - TL-WR710N v2.1 + - TL-WR842N/ND v3 + +* Ubiquiti + + - UniFi AP AC Lite [#ath10k]_ + - UniFi AP AC Pro [#ath10k]_ + +.. [#ath10k] + Device uses the ath10k WLAN driver; no image is built unless GLUON_ATH10K_MESH + is set as described in :ref:`getting-started-make-variables` + +brcm2708-bcm2708 +^^^^^^^^^^^^^^^^ + +* RaspberryPi 1 + +brcm2708-bcm2709 +^^^^^^^^^^^^^^^^ + +* RaspberryPi 2 + +New features +~~~~~~~~~~~~ + +* Many UBNT Airmax XM model names are detected correctly now (e.g., the Loco + is no longer displayed as Bullet) (`#632 `_) + + Also, various new image aliases have been added for these devices. + +* batman-adv: mesh_no_rebroadcast is now enabled for Mesh-on-WAN/LAN (`#652 `_) + +* The new UCI option ``gluon-core.@wireless[0].preserve_channels`` can be used to + prevent a changed WLAN channel from being reset on firmware upgrades (`#640 `_) + +* PoE passthrough can now be configured from site.conf and the Advanced Settings + on TP-Link CPE 210/510 and Ubiquiti NanoStations (`#328 `_) + +* The config mode *altitude* field can now be hidden using the ``config_mode.geo_location.show_altitude`` + site.conf setting (`#693 `_) + +* The contact information field in the config mode can be made obligatory using + the ``config_mode.owner.obligatory`` site.conf option + +* The *node name* setting in the config mode is no longer restricted to valid DNS + hostnames, but allows any UTF-8 string (`#414 `_) + +* Besides the hostname, public key, site config and primary MAC address, the contact + information can now be accessed from config mode site texts + +* The functions ``escape`` and ``urlescape`` for HTML and URL escaping are now available from config mode + site texts. They should always be used when including user-provided information like + hostnames and contact information in HTML code or URLs. + +* Dropbear has been updated to a newer version, enabling new SSH crypto methods and removing + some old ones like DSA. This reduces the time needed for the first boot and makes + SSH logins faster (`#223 `_) + +* WLAN basic and supported rate sets have been made configurable, to allow disabling + 802.11b rates (`#810 `_) + +* ath10k-based devices are now supported officially; it's possible to choose between + IBSS- and 11s-capable firmwares in site.mk (`#864 `_) + +* The ``prefix4`` and ``next_node.ip4`` site.conf options are optional now. + +Bugfixes +~~~~~~~~ + +* The stability of the ath9k WLAN driver has been improved significantly + (`#605 `_) + + mac80211, hostapd and other related drivers and services have been backported from LEDE ``42f559e``. + +* Extremely slow downloads could lead to multiple instances of the autoupdater + running concurrently (`#582 `_) + + A lockfile is used to prevent this and timeouts have been added to download processes. + +* Usage of static DNS servers on the WAN port has been fixed + (`#886 `_) + + This is a regression introduced in Gluon v2016.1.6. + +Other changes +~~~~~~~~~~~~~ + +* The "Expert Mode" has been renamed to "Advanced Settings" + +Site changes +~~~~~~~~~~~~ + +site.mk +^^^^^^^ + +If you want to support ath10k-based devices, you should set GLUON_ATH10K_MESH +and GLUON_REGION as described in :ref:`getting-started-make-variables`. + +i18n +^^^^ + +As the hostname field may now contain an arbitrary UTF-8 string, escaping must +be added. + +Change + +:: + + <%=hostname%> + +to + +:: + + <%=escape(hostname)%> + +Inside of URLs, ``urlescape`` must be used instead of ``escape``. + +Internals +~~~~~~~~~ + +* Mesh interfaces are now configured in a protocol-independent way in UCI (`#870 `_) + + The MAC address assignment of all mesh and WLAN interfaces has been modified to prepare for support of + Ralink/Mediatek-based WLAN chips. + +* Preparations for supporting the new batman-adv multicast optimizations have been made + (`#674 `_, `#675 `_, + `#679 `_) + +* All Lua code is minified now to save some space + +Known Issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2017.1.1.rst b/docs/releases/v2017.1.1.rst new file mode 100644 index 00000000..7a3cf653 --- /dev/null +++ b/docs/releases/v2017.1.1.rst @@ -0,0 +1,41 @@ +Gluon 2017.1.1 +============== + +Bugfixes +~~~~~~~~ + +* The autoupdater manifest has been extended to allow automatic upgrades from + old *x86-kvm* and *x86-xen_domu* systems to the new *x86-generic* image + (`869ceb4 `_) + +* Make flash writable again on Ubiquiti PicoStations with certain bootloader + versions (and possibly other devices) + (`9a787c9 `_) + + Units affected by this issue running Gluon v2017.1 can't leave config mode and + no regular sysupgrades are possible. TFTP recovery is necessary to make them + work again. + +* Add workaround to prevent sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + (`#1157 `_) + +* Disable batman-adv multicast optimizations to work around issue causing large + amounts of management traffic + (`819758f `_) + + Multicast optimizations will be enabled again when a proper fix is available. + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2017.1.2.rst b/docs/releases/v2017.1.2.rst new file mode 100644 index 00000000..eac4ddc2 --- /dev/null +++ b/docs/releases/v2017.1.2.rst @@ -0,0 +1,84 @@ +Gluon 2017.1.2 +============== + +New features +~~~~~~~~~~~~ + +* Preserve *gw_mode* on sysupgrades (`#1196 `_) + + When a Gluon node is used as uplink (for example by connecting it to a router with + a DHCP server directly, instead of using non-Gluon servers for the internet uplink), + the *gw_mode* must be set to *server* on that node. The changed *gw_mode* is now + preserved on upgrades. + +* Allow configuring the batman-adv routing algorithm (*BATMAN IV* or *BATMAN V*) + in *site.conf* (`#1185 `_) + + *BATMAN V* still hasn't received extensive testing (and is incompatible with *BATMAN IV*). + This new option allows to set up *BATMAN V*-based test meshes. If unset, the routing + algorithm will default to *BATMAN IV*. + + Configuration: + + .. code-block:: lua + + mesh = { + batman_adv = { + routing_algo = 'BATMAN_V' + } + } + +* New *show-release* Make target + + The command ``make show-release`` can be used to print the release number + defined by *GLUON_RELEASE* to the standard output. This can be useful for build scripts + when a ``$(shell ...)`` expression is used in *site.mk* to generate the release + number. + +Bugfixes +~~~~~~~~ + +* The image build code used for some devices has been fixed, solving multiple + issues (`#1193 `_) + + Problems caused by this issue include: + + - sysupgrade rejecting Allnet images + - OpenMesh devices losing their configuration on upgrades + + This is a regression introduced in Gluon v2017.1. + +* Improve sysupgrade error handling (`#1160 `_) + + If for some reason processes don't react to SIGKILL (usually because of a kernel bug), + a node could hang forever in sysupgrade, requiring a power cycle. This has been + fixed, triggering a reboot instead. + +* Also display *gluon-config-mode:novpn* message when Tunneldigger is installed, but disabled + (`#1172 `_) + + It was only displayed on nodes with fastd before. + +* Fix migration of enabled/disabled state between fastd and Tunneldigger + (`#1187 `_) + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + (`#1157 `_) + + The workaround added in Gluon v2017.1.1 has greatly reduced the frequency of + segfaults, but did not make them disappear completely. diff --git a/docs/releases/v2017.1.3.rst b/docs/releases/v2017.1.3.rst new file mode 100644 index 00000000..adad17a7 --- /dev/null +++ b/docs/releases/v2017.1.3.rst @@ -0,0 +1,65 @@ +Gluon 2017.1.3 +============== + +The LEDE base of Gluon has been updated to v17.01.3, including various updates, +stability improvements and security fixes. This includes some critical fixes +to core packages like dnsmasq (see below for details); upgrading all Gluon +nodes to v2017.1.3 is highly recommended. + + +Bugfixes +~~~~~~~~ + +* dnsmasq has been upgraded to v2.78, fixing CVE-2017-13704, CVE-2017-14491, + CVE-2017-14492, CVE-2017-14493, CVE-2017-14494, 2017-CVE-14495 and + 2017-CVE-14496 + + While many of the most severe (remote code execution) vulnarabilities are in + the DHCP component of dnsmasq, which is not active on a Gluon node unless in + Config Mode, CVE-2017-14491 does affect us. An attacker can cause memory + corruption and possibly remote code execution by deploying a malicious DNS + server and tricking a node into querying this server. + +* The Linux kernel has been upgraded to v4.4.89 + +* Multiple security issues have been fixed in packages that are not usually part + of the Gluon build, including tcpdump, curl and mbedtls + + Please refer to the + `LEDE commit log `_ + for details. + +* Filtering of multicast packets between the mesh and the *local-node* interface + has been fixed (`#1230 `_) + + This issue was causing gluon-radvd to send a router advertisement to the local + clients whenever a router solicitation from the mesh was received. In busy + meshes, it would continuously send router advertisements every 3 seconds. + +* Reject autoupdater mirror URLs not starting with ``http://`` during build + (`9ab93992d1fc `_) + +* Fix MAC addresses on TP-Link TL-WR1043ND v4 when installing Gluon over newer + stock firmwares (`#1223 `_) + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + (`#1157 `_) + + The workaround added in Gluon v2017.1.1 has greatly reduced the frequency of + segfaults, but did not make them disappear completely. diff --git a/docs/releases/v2017.1.4.rst b/docs/releases/v2017.1.4.rst new file mode 100644 index 00000000..d5b54c48 --- /dev/null +++ b/docs/releases/v2017.1.4.rst @@ -0,0 +1,56 @@ +Gluon 2017.1.4 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* GL Innovations GL-AR300M + + +Bugfixes +~~~~~~~~ + +* LEDE has been updated to the latest stable commit, including various fixes for + the kernel (including security updates), and making opkg work again. This also + includes fixes for the KRACK issue (which is irrelevant for most Gluon + deployments, as Gluon nodes are rarely used as WLAN clients) + (`b62af904bbfd `_, + `ba56b41ddaf6 `_, + `ad0824136e5b `_, + `017fbe88bb8a `_) + +* Fix DNS resolution for mesh VPN (fastd / tunneldigger) on ARM-based targets + (`#1245 `_) + +* Fix a build issue in *kmod-jool* + (`06842728233a `_) + +* Fix enabling/disabling PoE Passthrough in *site.conf* or in the + advanced settings + (`7268e49a301f `_, + `7c2636d28264 `_) + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + (`#1157 `_) + + The workaround added in Gluon v2017.1.1 has greatly reduced the frequency of + segfaults, but it did not make them disappear completely. diff --git a/docs/releases/v2017.1.5.rst b/docs/releases/v2017.1.5.rst new file mode 100644 index 00000000..33455a8c --- /dev/null +++ b/docs/releases/v2017.1.5.rst @@ -0,0 +1,57 @@ +Gluon 2017.1.5 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link TL-WR1043N v5 + +ramips-mt7621 +^^^^^^^^^^^^^ + +* Ubiquiti EdgeRouter-X +* Ubiquiti EdgeRouter-X SFP + + +Bugfixes +~~~~~~~~ + +* Fix build with empty ``site/modules`` + (`#1262 `_) + +* Fix Ethernet stalls at high throughput on certain devices + (`#1101 `_) + +* Update Tunneldigger to support connections with servers running newer kernel + versions (`9ed6ff752eb7 `_) + +* Fix batman-adv Bridge Loop Avoidance (BLA) with *gluon-ebtables-filter-multicast* + (`#1198 `_) + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + (`#1157 `_) + + The workaround added in Gluon v2017.1.1 has greatly reduced the frequency of + segfaults, but it did not make them disappear completely. + +* Frequent reboots due to out-of-memory on weak hardware in larger meshes + (`#1243 `_) diff --git a/docs/releases/v2017.1.6.rst b/docs/releases/v2017.1.6.rst new file mode 100644 index 00000000..2a05ebb8 --- /dev/null +++ b/docs/releases/v2017.1.6.rst @@ -0,0 +1,91 @@ +Gluon 2017.1.6 +============== + +Bugfixes +~~~~~~~~ + +* Remove broken DNS cache feature + (`#1362 `_) + + It was found that dnsmasq does not handle all answer records + equally. In particular, its cached answers are missing DNSKEY and DS + records, breaking DNSSEC validation on clients. + + Nodes can still resolve the next-node hostname locally and will continue to + work as DNS forwarders. The DNS cache feature may return if dnsmasq is fixed + or if we switch to a different resolver. + +* Ensure that corefiles are stored in /tmp rather than cluttering the root + filesystem + (`00df8b76e54c `_) + + Nodes upgrades from Gluon v2016.2.x or earlier did not set kernel.core_pattern + correctly, leading to corefiles being stored in the current directory (usually + / for system services) in the case of crashes. + + This is a regression introduced in Gluon v2017.1. + +* Only request a single IPv6 address instead of a prefix on the WAN interface + (`5db54ba78c3 `_) + +* Fix signal graph on status page when there are many neighbours + (packages/`d1e0b6e0bdae `_) + +* Fix config files managed by opkg not being saved on sysupgrades on ar71xx-tiny + (LEDE/`17c0362178ca `_, + LEDE/`75be005e8bdc `_) + +* Fix kernel crash in batman-adv-14 + (`#1358 `_) + + Starting with Gluon v2017.1, respondd could trigger a kernel crash caused by + a use-after-free in batman-adv-14, in particular after a gateway disappeared. + + batman-adv-15 is not affected. + +* Increase bridge multicast querier timeout ("robustness") to avoid + "querier appeared/disappeared" log spam by batman-adv in the presence of + an external querier + (`e305a8c01917 `_) + +* Fix "broken pipe" log spam caused by the status page + (`883c32f2f1dc `_) + +* Reduce memory limit of WLAN packet queues to 256KB on devices with small RAM + (`e63c6ca01f50 `_) + + Will hopefully make out-of-memory crashes in busy meshes less likely. + +* Improve image validation for TP-Link CPE/WBS 210/510 and make it ready for + future images + (LEDE/`6577fe2198f5 `_) + + Future OpenWrt/Gluon images will move the image metadata ("support-list") of + the CPE/WBS 210/510 images to a different offset. Make sysupgrade ready + to allow installing such images. + + This change was also backported to Gluon v2016.2.x to allow direct updates + to future Gluon master versions without installing v2017.1.x first. + +* Sporadic segfaults of busybox (ash) when running shell scripts on ar71xx + have disappeared with the latest updates + (`#1157 `_) + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Frequent reboots due to out-of-memory on weak hardware in larger meshes + (`#1243 `_) diff --git a/docs/releases/v2017.1.7.rst b/docs/releases/v2017.1.7.rst new file mode 100644 index 00000000..b06cc7d4 --- /dev/null +++ b/docs/releases/v2017.1.7.rst @@ -0,0 +1,34 @@ +Gluon 2017.1.7 +============== + +Bugfixes +~~~~~~~~ + +* Fix boot failure on many Ubiquiti devices + (`#1370 `_) + + A kernel update in Gluon 2017.1.6 led to boot failures on Ubiquiti Airmax M2/M5 + (NanoStation, Bullet, etc.) if the device had been running AirOS 5.6 before + installing Gluon/OpenWrt. The XW hardware revision is unaffected. + + While the root cause is a bug in Ubiquiti's bootloader, the issue is mitigated in + Gluon 2017.1.7. + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Frequent reboots due to out-of-memory on weak hardware in larger meshes + (`#1243 `_) diff --git a/docs/releases/v2017.1.8.rst b/docs/releases/v2017.1.8.rst new file mode 100644 index 00000000..b593305d --- /dev/null +++ b/docs/releases/v2017.1.8.rst @@ -0,0 +1,71 @@ +Gluon 2017.1.8 +============== + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* GL.iNet GL-AR750 +* TP-Link Archer C7 v4 +* Ubiquiti UniFi AC Mesh + +ar71xx-tiny +^^^^^^^^^^^ + +* TP-Link TL-WR940N v6 + + +Bugfixes +~~~~~~~~ + +* Fix refcounting issue in batman-adv leading to hangs on interface restarts + (`#1258 `_) + + This fix applied to both batman-adv compat 14 (legacy) and 15. + +* Various batman-adv bugfixes have been backported + (`f5b3c0c3bc7e `_ and + `5947ba300e50 `_, + fixing + `#1321 `_, + `#1380 `_, + `#1382 `_, + `#1419 `_ + and a number of other minor issues) + + The listed bugs could lead to high rates of batman-adv management traffic + (causing considerable load), trigger warnings about packet checksum failues + in certain non-standard interface configurations, and possibly other issues. + + +Other changes +~~~~~~~~~~~~~ + +* Linux kernel has been updated to v4.4.129 (LEDE/`81573ea25924 `_) + +* The description of the "contact information" field in the configuration wizard + has been extended with regard to the EU General Data Protection Regulation (GDPR) + (`fd355cf0ef7b `_) + + The *mandatory* site option for the contact information field has been removed. + + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Frequent reboots due to out-of-memory on weak hardware in larger meshes + (`#1243 `_) diff --git a/docs/releases/v2017.1.rst b/docs/releases/v2017.1.rst new file mode 100644 index 00000000..cc445933 --- /dev/null +++ b/docs/releases/v2017.1.rst @@ -0,0 +1,232 @@ +Gluon 2017.1 +============ + +General changes +~~~~~~~~~~~~~~~ + +Gluon 2017.1 is the first release of Gluon based on the LEDE 17.01 branch. The +kernel has been updated from 3.18.x to 4.4.x. + +We've used the opportunity to greatly simplify the Gluon build system, removing +many hacks that were required to make the build work with older OpenWrt releases. + +The *output/modules* directory is now called *output/packages* and provides a +replacement for the whole repository with target-specific packages of LEDE (in +contrast to packages that are common for all targets of the same architecture). +Another change to the build system makes it necessary that the same *GLUON_RELEASE* +value that is used to build the images is also set for ``make manifest``. + +GCC 4.8 or newer is now required to build Gluon. + +**Note: There is an issue in all Gluon versions before 2016.2.6 that will +lead to x86 systems losing their configuration when upgrading to Gluon 2017.1!** +Older Gluon versions should be upgraded to 2016.2.6 first before switching to +2017.1. + +Another potential issue mostly affects virtual machines: Gluon 2017.1 images are +bigger than 2016.2.x images on x86. If your virtual harddisk is based on a +2016.2.x image, it must be resized to 273MB or bigger before upgrading to Gluon +2017.1. Using qemu, the command + +:: + + qemu-img resize $IMAGE 273MB + +can be used to do this. + +Added hardware support +~~~~~~~~~~~~~~~~~~~~~~ + +ar71xx-generic +^^^^^^^^^^^^^^ + +* TP-Link + + - RE450 + - WBS210 v1.20 + - WBS510 v1.20 + +* Ubiquiti + + - AirGateway LR + - AirGateway PRO + - Rocket M2/M5 Ti + - UniFi AP LR + +ar71xx-tiny +^^^^^^^^^^^ + +The new *ar71xx-tiny* target has split out of *ar71xx-generic*; all +*ar71xx-generic* devices with only 4MB of flash have been moved to this target. + +In contrast to *ar71xx-generic*, *ar71xx-tiny* **does not support opkg anymore** +to save some space. + +* TP-Link + + - TL-WA730RE v1 + - TL-WA7210N v2 + +x86-generic +^^^^^^^^^^^ + +The *x86-kvm* and *x86-xen_domu* targets have been removed; the *x86-generic* +images now support these usecases as well, so no separate targets are needed +anymore. + +x86-geode +^^^^^^^^^ + +The new *x86-geode* target for hardware based on Geode CPUs has been added. + +New features +~~~~~~~~~~~~ + +* Localization support has been added to the status page. In addition to German, + there are English and Russian translations now (`#1044 `_) + +* Add support for making nodes a DNS cache for clients + (`#1000 `_) + +* Add L2TP via tunneldigger as an alternative VPN system + (`#978 `_) + + L2TP will usually give better performance than fastd as it runs in kernel + space, but it does not provide encryption. Also, tunneling over IPv6 is + currently unsupported by tunneldigger. + + It is not possible to include both fastd and tunneldigger in the same + firmware. + +* Add source filter package (`#1015 `_) + + The new package *gluon-ebtables-source-filter* can be used to prevent traffic + using unexpected IP addresses or packet types from entering the mesh. + + See also: :doc:`../package/gluon-ebtables-source-filter` + +Bugfixes +~~~~~~~~ + +* Disabling batman-adv on an interface (for example when an Ethernet link is lost + or before sysupgrades) could lead to a kernel crash in certain configurations + (`#680 `_) + +* A race condition in the network setup scripts could lead to incomplete setup + during boot or when interfaces were added or removed from batman-adv after + Ethernet link changes (`#905 `_) + + The fix also solved the long-standing issue of Ethernet-only nodes (i.e. no + WLAN or VPN mesh) not booting up correctly without an Ethernet mesh link. + +* Some fixes in the WLAN stack of LEDE have improved the stability of the ath9k + driver (`#605 `_) + +Site changes +~~~~~~~~~~~~ + +site.mk +^^^^^^^ + +* The *gluon-legacy* package does not exist anymore +* All *gluon-luci-* packages have been renamed to *gluon-web-*; + *gluon-luci-portconfig* is now called *gluon-web-network* +* The *gluon-next-node* package has been merged into the Gluon core and must not + be specified in *site.mk* anymore + +site.conf +^^^^^^^^^ + +* The *fastd_mesh_vpn* configuration section has been restructured to allow + sharing more options with tunneldigger. Instead of + + .. code-block:: lua + + fastd_mesh_vpn = { + mtu = 1280, + configurable = true, + methods = {'salsa2012+umac'}, + groups = { ... }, + bandwidth_limit = { ... }, + } + + the configuration must look like this now: + + .. code-block:: lua + + mesh_vpn = { + mtu = 1280, + fastd = { + configurable = true, + methods = {'salsa2012+umac'}, + groups = { ... }, + } + bandwidth_limit = { ... }, + } + +* The *opkg.openwrt* option has been renamed to *opkg.lede* + +i18n +^^^^ + +* The *escape* function has been removed as it was duplicating the existing + *pcdata* function. All uses of *escape* in i18n templates must be changed to + use *pcdata* instead. + +* The *gluon-config-mode:altitude-label* and *gluon-config-mode:altitude-help* + translation IDs have been added to allow adjusting the texts for different + kinds of altitudes that might be expected. + +* The optional *gluon-config-mode:novpn* label has been added, which will be + shown in place of *gluon-config-mode:pubkey* when mesh VPN is disabled. + +Internals +~~~~~~~~~ + +* The LuCI base libraries have been replaced by a stripped-down + version called "gluon-web" (`#1007 `_) + + Custom packages will need to be adjusted; in particular, all uses of *luci.model.uci* + need to be replaced with *simple-uci*. The Gluon documentation explains the most important + changes required to migrate from LuCI to gluon-web. + +* respondd now listens on ``ff05::2:1001`` in addition to ``ff02::2:1001`` for mesh-wide + operation (`#984 `_) + + Eventually, ``ff02::2:1001`` will be available for exchanging information + between neighbouring nodes only; map servers should be moved to ``ff05::2:1001``. + +* batman-adv has been updated to version 2017.1 + +* Directly running make commands in the *lede* directory is supported now. Consequently, + build targets like ``target/linux/clean`` and ``package/NAME/compile`` can't be used + in the Gluon repository root anymore. + + The command ``make config`` will set up the LEDE *.config* in the way a normal + Gluon build would, so it's possible to build individual packages for testing + and development afterwards. + +* Target definitions have been migrated from a Make-based format to a simpler + shell-based DSL + +* Gluon does not pass any custom variables into the LEDE build anymore, so things + like *GLUONDIR*, *GLUON_VERSION*, or *GLUON_SITEDIR* aren't available + to package Makefiles in Gluon 2017.1. + + Instead of ``$(GLUONDIR)/package.mk``, ``$(TOPDIR)/../package/gluon.mk`` must + be included in custom packages now. + +Known issues +~~~~~~~~~~~~ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. diff --git a/docs/releases/v2018.1.rst b/docs/releases/v2018.1.rst new file mode 100644 index 00000000..a7488f83 --- /dev/null +++ b/docs/releases/v2018.1.rst @@ -0,0 +1,402 @@ +Gluon 2018.1 +############ + +Important notes +*************** + +This version changes the flash partition layout on some devices (TP-Link CPE/WBS 210/510). To avoid +upgrade failures, make sure to upgrade to Gluon 2017.1.8 or the latest Gluon 2016.2.x (unreleased) +before installing Gluon 2018.1. + +Some of the following paragraphs describe so-called "feature flags". This new concept is +explained in :ref:`user-site-feature-flags`. + +Added hardware support +********************** + +ar71xx-generic +============== + +* ALFA NETWORK + + - AP121F + +* AVM + + - FRITZ!Box 4020 + +* OpenMesh + + - A40 + - A60 + - OM2P v4 + - OM2P-HS v4 + +* TP-Link + + - Archer C59 v1 [#noibss]_ + - CPE210 v2 + +ar71xx-nand +=========== + +* ZyXEL + + - NBG6716 + +ar71xx-tiny +=========== + +* TP-Link + + - TL-WA901ND v5 + +ipq806x [#newtarget]_ [#noibss]_ +================================ + +* TP-Link + + - Archer C2600 + +ramips-mt7620 [#newtarget]_ [#noibss]_ +====================================== + +* GL Innovations + + - GL-MT300A + - GL-MT300N + - GL-MT750 + +ramips-mt7628 [#newtarget]_ [#noibss]_ +====================================== + +* VoCore + + - VoCore 2 + +ramips-rt305x [#newtarget]_ [#noibss]_ +====================================== + +* A5 + + - V11 + +* D-Link + + - DIR615 (D1, D2, D3, D4, H1) + +* VoCore + + - VoCore (8MB, 16MB) + +sunxi [#newtarget]_ +=================== + +* LeMaker/SinoVoip + + - Banana Pi (M1) + + +.. [#newtarget] + New target + +.. [#noibss] + Device or target does not support AP+IBSS mode: This device or target will not be built + when *GLUON_WLAN_MESH* is set to ``ibss``. + +New features +************ + +Multidomain support +=================== + +When mesh networks grow too large, it becomes necessary to split them into +multiple independent mesh domains to allow the meshes to work with reasonable +performance. Formerly, the only way to achieve this with Gluon was to build +a separate set of firmware images for each domain. + +With Gluon 2018.1, multidomain firmwares can be used to achieve the same, +using only a single site configuration that is basis for several different +domain-specific configurations. The feature is explained in detail in +:doc:`../features/multidomain`. + +Wired mesh encapsulation +======================== + +Gluon now supports encapsulating wired mesh traffic (Mesh on LAN/WAN) in +`VXLAN `_. +See :doc:`../features/wired-mesh` for details on this feature. + +Router advertisement filtering +============================== + +Similar to the builtin batman-adv gateway feature for IPv4, the *gluon-radv-filterd* package +(*radv-filterd* feature flag) allows to filter IPv6 router advertisements received from the mesh +so that only the RAs with the best routing metric (TQ) reach the clients, ensuring that +the "best" (topologically closest) gateway is chosen as the IPv6 default route, thereby +reducing gateway crosstalk. + +At the moment, this feature only filters RAs forwarded to clients; the RAs handled on +the nodes themselves will be unfiltered, so the nodes will still use arbitrary default +gateways. + +IGMP/MLD segmentation +===================== + +The IGMP/MLD segmentation feature previously provided by the *gluon-ebtables-segment-mld* +package has been extended and moved into the Gluon core; it does not exist as a separate package +anymore. + +Filtering IGMP/MLD queries directed towards the mesh ensures that each node becomes the multicast querier +for its own clients (unless there are other multicast-aware switches connected to the node), rather +than electing a single, basically arbitrary node in the mesh to become the querier. Overall, +this should significantly improve the reliablity of multicast in the mesh. This is especially +important for IPv6, as the IPv6 Neighbour Discovery Protocol (NDP) is based on local multicast. + +See also the documentation of the :ref:`site.conf mesh section `. + +gluon-ebtables-limit-arp +======================== + +The *gluon-ebtables-limit-arp* (*ebtables-limit-arp* feature flag) package adds filters to limit the +rate of ARP requests client devices are allowed to send into the mesh. + +Certain client applications are known to generate a significant amount of such ARP requests and +are reportedly becoming more and more common. Without this package, such clients are one +known cause for mesh wide load and congestion problems (see also the :ref:`releases-v2018.1-known-issues` +section below). + +Because of this package's implementation, which relies on frequent dynamic updates +- something ebtables does not perform well at - it is not included by default, as it can +cause unnecessary load. Feedback, especially with a close look on load and congestion on +nodes with a large number of changing client devices, is very much welcome. Depending on the +feedback, we might enable this feature by default in a future release. + +Public key in respondd data (optional) +====================================== + +If desired, the fastd public key of a node can be included in the respondd nodeinfo data, +faciliating the correlations of VPN peers and nodes. As the VPN key is transmitted unencrypted +in the fastd handshake, this would theoretically allow an ISP to determine which nodes +are operated behind which internet line. Therefore, this feature must be enabled explicitly +by setting *mesh_vpn.pubkey_privacy* to ``false`` in *site.conf*. + +B.A.T.M.A.N. V (experimental) +============================= + +When using batman-adv compat 15, it is now possible to switch to the new routing +algorithm B.A.T.M.A.N. V (while the old algorithm is called B.A.T.M.A.N. IV) by +setting *mesh.batman_adv.routing_algo* to ``"BATMAN_V"``. Note that the new routing +algorithm is not backwards-compatible, so nodes using different algorithms can +not interoperate. + +.. _releases-v2018.1-site-changes: + +Site changes +************ + +site.mk +======= + +* Due to improved package dependency handling, the packages + *gluon-config-mode-core* and *gluon-setup-mode* do not need + to be listed explicitly in *site.mk* anymore; they will be + pulled in implicitly. +* Including the *ebtables-limit-arp* feature flag is recommended. Please note + the abovementioned caveats on this feature. +* We recommend to use *GLUON_FEATURES* for all Gluon packages, and rely on + *GLUON_SITE_PACKAGES* for non-Gluon (OpenWrt) packages only, as explained + in :ref:`user-site-feature-flags`. + +site.conf +========= + +When updating a site configuration from Gluon 2017.1.x, the following changes +must be made: + +* .. code-block:: lua + + domain_seed = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', + + These 32 bytes of random data (encoded in hexadecimal) are used to seed a number + of site/domain specific random values that must be the same on all nodes of the + same mesh, but different for different meshes. The following command + can be used to generate such a random value: + + .. code-block:: shell + + echo $(hexdump -v -n 32 -e '1/1 "%02x"' `_. When finished, the optimizations +will help reduce the remaining Layer-2-specific network overhead, e.g. multicasted ICMPv6 messages. + +No behaviour changes are expected yet, as the multicast sender side is still disabled. +Once the majority of the mesh network has been updated to Gluon 2018.1, it can be activated on +dedicated nodes by including `#1357 `_ in the firmware +build. Test feedback is very welcome. + +.. _releases-v2018.1-known-issues: + +Known issues +************ + +* Default TX power on many Ubiquiti devices is too high, correct offsets are unknown (`#94 `_) + + Reducing the TX power in the Advanced Settings is recommended. + +* The MAC address of the WAN interface is modified even when Mesh-on-WAN is disabled (`#496 `_) + + This may lead to issues in environments where a fixed MAC address is expected (like VMware when promicious mode is disallowed). + +* Inconsistent respondd API (`#522 `_) + + The current API is inconsistent and will be replaced eventually. The old API will still be supported for a while. + +* Frequent reboots due to out-of-memory or high load due to memory pressure on weak hardware specially in larger meshes + (`#1243 `_) + + Optimizations in Gluon 2018.1 have significantly improved memory usage. + There are still known bugs leading to unreasonably high load that we hope to + solve in future releases. diff --git a/docs/site-example/i18n/de.po b/docs/site-example/i18n/de.po index 69cf1dd8..3a16b5b5 100644 --- a/docs/site-example/i18n/de.po +++ b/docs/site-example/i18n/de.po @@ -12,33 +12,76 @@ msgstr "" msgid "gluon-config-mode:welcome" msgstr "" -"Willkommen zum Einrichtungsassistenten für deinen neuen Entenhausener " +"Willkommen zum Einrichtungsassistenten für deinen neuen Alpha Centauri " "Freifunk-Knoten. Fülle das folgende Formular deinen Vorstellungen " "entsprechend aus und sende es ab." +msgid "gluon-config-mode:domain" +msgstr "Domäne" + +msgid "gluon-config-mode:domain-select" +msgstr "" +"Hier hast du die Möglichkeit, die Mesh-Domäne, in der sich dein Knoten " +"befindet, auszuwählen. Bitte denke daran, dass sich dein Knoten nur mit den " +"Knoten der ausgewählten Domäne verbinden kann." + msgid "gluon-config-mode:pubkey" msgstr "" "

Dies ist der öffentliche Schlüssel deines Freifunk-Knotens. Erst nachdem " -"er auf den Servern des Entenhausener Freifunk-Projektes eingetragen wurde, " -"kann sich dein Knoten mit dem Entenhausener Mesh-VPN verbinden. Bitte " +"er auf den Servern des Freifunk-Projektes auf Alpha Centauri eingetragen wurde, " +"kann sich dein Knoten mit dem Mesh-VPN dort verbinden. Bitte " "schicke dazu diesen Schlüssel und den Namen deines Knotens " -"(<%=hostname%>) an " -"keys@entenhausen.freifunk.net." +"(<%=pcdata(hostname)%>) an " +"&" +"body=<%= urlencode('# ' .. hostname .. '\n' .. pubkey) %>\">keys@alpha-centauri.freifunk.net." "

" "
" -" # <%= hostname %>" -"
" +" # <%= pcdata(hostname) %>" +"
" "<%= pubkey %>" "
" +msgid "gluon-config-mode:novpn" +msgstr "" +"

Du hast ausgewählt, kein Mesh-VPN " +"zu nutzen. Dein Knoten kann also nur dann eine Verbindung zum Freifunk-Netz " +"aufbauen, wenn andere Freifunk-Router in WLAN-Reichweite sind." +"

" + msgid "gluon-config-mode:reboot" msgstr "" -"

Dein Knoten startet gerade neu und wird anschließend versuchen, " -"sich mit anderen Freifunkknoten in seiner Nähe zu " +"

Dein Knoten <%= pcdata(hostname) %> startet gerade neu und wird " +"anschließend versuchen, sich mit anderen Freifunkknoten in seiner Nähe zu " "verbinden. Weitere Informationen zur " -"Entenhausener Freifunk-Community findest du auf " -"unserer Webseite.

" +"Alpha Centauri Freifunk-Community findest du auf " +"unserer Webseite.

" "

Um zu dieser Konfigurationsseite zurückzugelangen, drücke im normalen " "Betrieb für drei Sekunden den Reset-Button. Das Gerät wird dann im Config " "Mode neustarten.

" "

Viel Spaß mit deinem Knoten und der Erkundung von Freifunk!

" + +msgid "gluon-config-mode:altitude-label" +msgstr "Höhe" + +msgid "gluon-config-mode:altitude-help" +msgstr "" +"Die Höhenangabe ist optional und sollte nur gesetzt werden, wenn ein " +"exakter Wert bekannt ist." + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-hostname/i18n/ +msgid "gluon-config-mode:hostname-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-geo-location/i18n/ +msgid "gluon-config-mode:geo-location-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-contact-info/i18n/ +msgid "gluon-config-mode:contact-help" +msgstr "" + +msgid "gluon-config-mode:contact-note" +msgstr "" diff --git a/docs/site-example/i18n/en.po b/docs/site-example/i18n/en.po index 13273230..c31043a2 100644 --- a/docs/site-example/i18n/en.po +++ b/docs/site-example/i18n/en.po @@ -12,31 +12,71 @@ msgstr "" msgid "gluon-config-mode:welcome" msgstr "" -"Welcome to the setup wizard of your new Freifunk Duckburg node. " +"Welcome to the setup wizard of your new Freifunk Alpha Centauri node. " "Please fill out the following form and submit it." +msgid "gluon-config-mode:domain" +msgstr "Domain" + +msgid "gluon-config-mode:domain-select" +msgstr "" +"Here you have the possibility of selecting the mesh domain in which your node " +"is placed. Please keep in mind that your router only connects with the nodes " +"of the selected domain" + msgid "gluon-config-mode:pubkey" msgstr "" "

This is your Freifunk node's public key. The node won't be able to " -"connect to the mesh VPN until the key has been registered on the Freifunk " -"Duckburg servers. " -"To register, send the key together with your node's name (<%=hostname%>) to " -"keys@entenhausen.freifunk.net." +"connect to the mesh VPN until the key has been registered on the Freifunk servers. " +"To register, send the key together with your node's name (<%=pcdata(hostname)%>) to " +"&" +"body=<%= urlencode('# ' .. hostname .. '\n' .. pubkey) %>\">keys@alpha-centauri.freifunk.net." "

" "
" -" # <%= hostname %>" -"
" +" # <%= pcdata(hostname) %>" +"
" "<%= pubkey %>" "
" +msgid "gluon-config-mode:novpn" +msgstr "" +"

You have selected not to use the mesh VPN. " +"Your node will only be able to connect to the Freifunk network if other nodes in reach " +"already have a connection.

" msgid "gluon-config-mode:reboot" msgstr "" -"

The node is currently rebooting and will try to connect to other " -"nearby Freifunk nodes after that. " -"For more information on the Freifunk Duckburg community, have a look at " -"our homepage.

" +"

Your node <%= pcdata(hostname) %> is currently rebooting and will " +"try to connect to other nearby Freifunk nodes after that. For more " +"information about the Freifunk community on Alpha Centauri, have a look at " +"our homepage.

" "

To get back to this configuration interface, press the reset button for " "3 seconds during normal operation. The device will then reboot into config " "mode.

" "

Have fun with your node and exploring of the Freifunk network!

" + +msgid "gluon-config-mode:altitude-label" +msgstr "Altitude" + +msgid "gluon-config-mode:altitude-help" +msgstr "" +"Specifying the altitude is optional and should only be done if a proper " +"value is known." + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-hostname/i18n/ +msgid "gluon-config-mode:hostname-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-geo-location/i18n/ +msgid "gluon-config-mode:geo-location-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-contact-info/i18n/ +msgid "gluon-config-mode:contact-help" +msgstr "" + +msgid "gluon-config-mode:contact-note" +msgstr "" diff --git a/docs/site-example/i18n/fr.po b/docs/site-example/i18n/fr.po index 30e21c50..5a591ee5 100644 --- a/docs/site-example/i18n/fr.po +++ b/docs/site-example/i18n/fr.po @@ -14,7 +14,13 @@ msgid "gluon-config-mode:welcome" msgstr "" "Bienvenue dans l'assistant de configuration pour votre nouveau nœud " "Freifunk. Remplissez le formulaire suivant en fonction de vos besoins " -"et enregistrez le" +"et enregistrez le" + +msgid "gluon-config-mode:domain" +msgstr "Domaine" + +msgid "gluon-config-mode:domain-select" +msgstr "" msgid "gluon-config-mode:pubkey" msgstr "" @@ -22,22 +28,55 @@ msgstr "" "entrée sur les serveurs de votre groupe de Freifunk votre nœud pourra se connecter " "sur les serveur Mesh-VPN de votre groupe Freifunk. Veuillez envoyer la clé avec le " "nom de votre nœud " -"(<%=hostname%>) à " -"keys@entenhausen.freifunk.net." +"(<%=pcdata(hostname)%>) à " +"&" +"body=<%= urlencode('# ' .. hostname .. '\n' .. pubkey) %>\">keys@alpha-centauri.freifunk.net." "

" "
" -" # <%= hostname %>" -"
" +" # <%= pcdata(hostname) %>" +"
" "<%= pubkey %>" "
" +msgid "gluon-config-mode:novpn" +msgstr "" +"

Vous avez choisi de ne pas utiliser " +"le réseau VPN. Votre nœud ne pourra se connecter au réseau Freifunk que si " +"d'autres nœuds à portée ont déjà une connexion.

" + msgid "gluon-config-mode:reboot" msgstr "" -"

Votre nœud es en train de redémarrer et va ensuite éssayer de se connecter " -"avec les autres nœuds du réseau Freifunk " +"

Votre nœud <%= pcdata(hostname) %> es en train de redémarrer et " +"va ensuite éssayer de se connecter avec les autres nœuds du réseau Freifunk " "Vous pourrez trouver plus d'informations sur votre groupe Freifunk sur la page " -" de ton groupe .

" +" de ton groupe .

" "

Pour retrouver cette page de configuration veuillier appuyez pendant le " "fonctionement normal pendant 3 Secondes sur le bouton reset. L'appareil va ensuite " "redémarer en mode configuration.

" "

Profitez votre de nœud et amusez vous à découvrir le réseau Freifunk!

" + +msgid "gluon-config-mode:altitude-label" +msgstr "Hauteur" + +msgid "gluon-config-mode:altitude-help" +msgstr "" +"La altitude est optionelle et ne devrait que être ajoutée si la valeur " +"exacte est connue." + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-hostname/i18n/ +msgid "gluon-config-mode:hostname-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-geo-location/i18n/ +msgid "gluon-config-mode:geo-location-help" +msgstr "" + +# Leave empty to use the default text, which can be found in: +# package/gluon-config-mode-contact-info/i18n/ +msgid "gluon-config-mode:contact-help" +msgstr "" + +msgid "gluon-config-mode:contact-note" +msgstr "" diff --git a/docs/site-example/i18n/gluon-site.pot b/docs/site-example/i18n/gluon-site.pot index 670de410..032c6931 100644 --- a/docs/site-example/i18n/gluon-site.pot +++ b/docs/site-example/i18n/gluon-site.pot @@ -4,8 +4,35 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "gluon-config-mode:welcome" msgstr "" +msgid "gluon-config-mode:domain" +msgstr "" + +msgid "gluon-config-mode:domain-select" +msgstr "" + msgid "gluon-config-mode:pubkey" msgstr "" +msgid "gluon-config-mode:novpn" +msgstr "" + msgid "gluon-config-mode:reboot" msgstr "" + +msgid "gluon-config-mode:altitude-label" +msgstr "" + +msgid "gluon-config-mode:altitude-help" +msgstr "" + +msgid "gluon-config-mode:contact-help" +msgstr "" + +msgid "gluon-config-mode:contact-note" +msgstr "" + +msgid "gluon-config-mode:hostname-help" +msgstr "" + +msgid "gluon-config-mode:geo-location-help" +msgstr "" diff --git a/docs/site-example/site.conf b/docs/site-example/site.conf index 45719b94..6b52d53a 100644 --- a/docs/site-example/site.conf +++ b/docs/site-example/site.conf @@ -1,21 +1,28 @@ --- This is an example site configuration for Gluon v2016.1+ +-- This is an example site configuration for Gluon v2018.1 -- -- Take a look at the documentation located at -- http://gluon.readthedocs.org/ for details. -- --- This configuration will not work as it. You're required to make +-- This configuration will not work as is. You're required to make -- community specific changes to it! { -- Used for generated hostnames, e.g. freifunk-abcdef123456. (optional) -- hostname_prefix = 'freifunk-', -- Name of the community. - site_name = 'Freifunk Entenhausen', + site_name = 'Freifunk Alpha Centauri', -- Shorthand of the community. site_code = 'ffxx', - -- Prefixes used within the mesh. Both are required. + -- 32 bytes of random data, encoded in hexadecimal + -- This data must be unique among all sites and domains! + -- Can be generated using: echo $(hexdump -v -n 32 -e '1/1 "%02x"' `. @@ -54,23 +67,27 @@ opkg \: optional There are two optional fields in the ``opkg`` section: - - ``openwrt`` overrides the default OpenWrt repository URL + - ``lede`` overrides the default LEDE repository URL. The default URL would + correspond to ``http://downloads.lede-project.org/snapshots/packages/%A`` + and usually doesn't need to be changed when nodes are expected to have IPv6 + internet connectivity. - ``extra`` specifies a table of additional repositories (with arbitrary keys) :: opkg = { - openwrt = 'http://opkg.services.ffeh/openwrt/%n/%v/%S/packages', + lede = 'http://opkg.services.ffac/lede/snapshots/packages/%A', extra = { - modules = 'http://opkg.services.ffeh/modules/gluon-%GS-%GR/%S', + gluon = 'http://opkg.services.ffac/modules/gluon-%GS-%GR/%S', }, } There are various patterns which can be used in the URLs: - - ``%n`` is replaced by the OpenWrt version codename (e.g. "chaos_calmer") - - ``%v`` is replaced by the OpenWrt version number (e.g. "15.05") - - ``%S`` is replaced by the target architecture (e.g. "ar71xx/generic") + - ``%n`` is replaced by the LEDE version codename + - ``%v`` is replaced by the LEDE version number (e.g. "17.01") + - ``%S`` is replaced by the target board (e.g. "ar71xx/generic") + - ``%A`` is replaced by the target architecture (e.g. "mips_24kc") - ``%GS`` is replaced by the Gluon site code (as specified in ``site.conf``) - ``%GV`` is replaced by the Gluon version - ``%GR`` is replaced by the Gluon release (as specified in ``site.mk``) @@ -81,13 +98,13 @@ regdom \: optional regdom = 'DE' - Setting ``regdom`` in mandatory if ``wifi24`` or ``wifi5`` is defined. + Setting ``regdom`` is mandatory if ``wifi24`` or ``wifi5`` is defined. wifi24 \: optional WLAN configuration for 2.4 GHz devices. ``channel`` must be set to a valid wireless channel for your radio. - There are currently three interface types available. You many choose to + There are currently three interface types available. You may choose to configure any subset of them: - ``ap`` creates a master interface where clients may connect @@ -96,27 +113,39 @@ wifi24 \: optional Each interface may be disabled by setting ``disabled`` to ``true``. This will only affect new installations. - Upgrades will not changed the disabled state. + Upgrades will not change the disabled state. + + Additionally it is possible to configure the ``supported_rates`` and ``basic_rate`` + of each radio. Both are optional, by default hostapd/driver dictate the rates. + If ``supported_rates`` is set, ``basic_rate`` is required, because ``basic_rate`` + has to be a subset of ``supported_rates``. + The example below disables 802.11b rates. ``ap`` requires a single parameter, a string, named ``ssid`` which sets the - interface's ESSID. + interface's ESSID. This is the WiFi the clients connect to. - ``mesh`` requires a single parameter, a string, named ``id`` which sets the mesh id. + ``mesh`` requires a single parameter, a string, named ``id`` which sets the + mesh id, also visible as an open WiFi in some network managers. Usually you + don't want users to connect to this mesh-SSID, so use a cryptic id that no + one will accidentally mistake for the client WiFi. ``ibss`` requires two parametersr: ``ssid`` (a string) and ``bssid`` (a MAC). An optional parameter ``vlan`` (integer) is supported. Both ``mesh`` and ``ibss`` accept an optional ``mcast_rate`` (kbit/s) parameter for - setting the default multicast datarate. + setting the multicast bitrate. Increasing the default value of 1000 to something + like 12000 is recommended. :: wifi24 = { channel = 11, + supported_rates = {6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000}, + basic_rate = {6000, 9000, 18000, 36000, 54000}, ap = { - ssid = 'entenhausen.freifunk.net', + ssid = 'alpha-centauri.freifunk.net', }, mesh = { - id = 'entenhausen-mesh', + id = 'ueH3uXjdp', mcast_rate = 12000, }, ibss = { @@ -134,81 +163,161 @@ next_node \: package :: next_node = { + name = { 'nextnode.location.community.example.org', 'nextnode', 'nn' }, ip4 = '10.23.42.1', ip6 = 'fdca:ffee:babe:1::1', - mac = 'ca:ff:ee:ba:be:00' + mac = '16:41:95:40:f7:dc' } -mesh \: optional - Options specific to routing protocols. + All values of this section are optional. If the IPv4 or IPv6 address is + omitted, there will be no IPv4 or IPv6 anycast address. The MAC address + defaults to ``16:41:95:40:f7:dc``; this value usually doesn't need to be + changed, but it can be adjusted to match existing deployments that use a + different value. - At the moment, only the ``batman_adv`` routing protocol has such options: + When the nodes' next-node address is used as a DNS resolver by clients + (by passing it via DHCP or router advertisements), it may be useful to + allow resolving a next-node hostname without referring to an upstream DNS + server (e.g. to allow reaching the node using such a hostname via HTTP or SSH + in isolated mesh segments). This is possible by providing one or more names + in the ``name`` field. - The optional value ``gw_sel_class`` sets the gateway selection class. The default - class 20 is based on the link quality (TQ) only, class 1 is calculated from - both the TQ and the announced bandwidth. +.. _user-site-mesh: + +mesh + Configuration of general mesh functionality. + + To avoid inter-mesh links, Gluon can encapsulate the mesh protocol in VXLAN + for Mesh-on-LAN/WAN. It is recommended to set *mesh.vxlan* to ``true`` to + enable VXLAN in new setups. Setting it to ``false`` disables this + encapsulation to allow meshing with other nodes that don't support VXLAN + (Gluon 2017.1.x and older). In multi-domain setups, *mesh.vxlan* is optional + and defaults to ``true``. + + Gluon generally segments layer-2 meshes so that each node becomes IGMP/MLD + querier for its own local clients. This is necessary for reliable multicast + snooping. The segmentation is realized by preventing IGMP/MLD queries from + passing through the mesh. + + By default, not only queries are filtered, but also membership report and + leave packets, as they add to the background noise of the mesh. As a + consequence, snooping switches outside the mesh that are connected to a + Gluon node need to be configured to forward all multicast traffic towards + the mesh; this is usually not a problem, as such setups are unusual. If + you run a special-purpose mesh that requires membership reports to be + working, this filtering can be disabled by setting the + optional *filter_membership_reports* value to ``false``. + + In addition, options specific to the batman-adv routing protocol can be set + in the *batman_adv* section: + + The optional value *gw_sel_class* sets the gateway selection class. The + default is class 20, which is based on the link quality (TQ) only; class 1 + is calculated from both the TQ and the announced bandwidth. :: - mesh = { - batman_adv = { - gw_sel_class = 1, - }, - } + mesh = { + vxlan = true, + filter_membership_reports = false, + batman_adv = { + gw_sel_class = 1, + }, + } -fastd_mesh_vpn - Remote server setup for the fastd-based mesh VPN. +mesh_vpn + Remote server setup for the mesh VPN. - The `enabled` option can be set to true to enable the VPN by default. + The `enabled` option can be set to true to enable the VPN by default. `mtu` + defines the MTU of the VPN interface, determining a proper MTU value is described + in the :ref:`FAQ `. + + By default the public key of a node's VPN daemon is not added to announced respondd + data; this prevents malicious ISPs from correlating VPN sessions with specific mesh + nodes via public respondd data. If this is of no concern in your threat model, + this behaviour can be disabled (and thus announcing the public key be enabled) by + setting `pubkey_privacy` to `false`. At the moment, this option only affects fastd. + + The `fastd` section configures settings specific to the *fastd* VPN + implementation. If `configurable` is set to `false` or unset, the method list will be replaced on updates with the list from the site configuration. Setting `configurable` to `true` will allow the user to add the method ``null`` to the beginning of the method list or remove ``null`` from it, and make this change survive updates. Setting `configurable` is necessary for the - package `gluon-luci-mesh-vpn-fastd`, which adds a UI for this configuration. + package `gluon-web-mesh-vpn-fastd`, which adds a UI for this configuration. In any case, the ``null`` method should always be the first method in the list if it is supported at all. You should only set `configurable` to `true` if the configured peers support both the ``null`` method and methods with encryption. + + You can set syslog_level from verbose (default) to warn to reduce syslog output. + + The `tunneldigger` section is used to define the *tunneldigger* broker list. + + **Note:** It doesn't make sense to include both `fastd` and `tunneldigger` + sections in the same configuration file, as only one of the packages *gluon-mesh-vpn-fastd* + and *gluon-mesh-vpn-tunneldigger* should be installed with the current + implementation. + :: - fastd_mesh_vpn = { - methods = {'salsa2012+umac'}, - -- enabled = true, - -- configurable = true, - mtu = 1280, - groups = { - backbone = { - -- Limit number of connected peers from this group - limit = 1, - peers = { - peer1 = { - key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - -- Having multiple domains prevents SPOF in freifunk.net - remotes = { - 'ipv4 "vpn1.entenhausen.freifunk.net" port 10000', - 'ipv4 "vpn1.entenhausener-freifunk.de" port 10000', + mesh_vpn = { + -- enabled = true, + mtu = 1312, + -- pubkey_privacy = true, + + fastd = { + methods = {'salsa2012+umac'}, + -- configurable = true, + -- syslog_level = 'warn', + groups = { + backbone = { + -- Limit number of connected peers from this group + limit = 1, + peers = { + peer1 = { + key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', + -- Having multiple domains prevents SPOF in freifunk.net + remotes = { + 'ipv4 "vpn1.alpha-centauri.freifunk.net" port 10000', + 'ipv4 "vpn1.alpha-centauri-freifunk.de" port 10000', + }, + }, + peer2 = { + key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', + -- You can also omit the ipv4 to allow both connection via ipv4 and ipv6 + remotes = {'"vpn2.alpha-centauri.freifunk.net" port 10000'}, + }, + peer3 = { + key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', + -- In addition to domains you can also add ip addresses, which provides + -- resilience in case of dns outages + remotes = { + '"vpn3.alpha-centauri.freifunk.net" port 10000', + '[2001:db8::3:1]:10000', + '192.0.2.3:10000', + }, }, }, - peer2 = { - key = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', - -- You can also omit the ipv4 to allow both connection via ipv4 and ipv6 - remotes = {'"vpn2.entenhausen.freifunk.net" port 10000'}, - }, + -- Optional: nested peer groups + -- groups = { + -- lowend_backbone = { + -- limit = 1, + -- peers = ... + -- }, + -- }, }, - -- Optional: nested peer groups - -- groups = { - -- lowend_backbone = { - -- limit = 1, - -- peers = ... - -- }, + -- Optional: additional peer groups, possibly with other limits + -- peertopeer = { + -- limit = 10, + -- peers = { ... }, -- }, }, - -- Optional: additional peer groups, possibly with other limits - -- peertopeer = { - -- limit = 10, - -- peers = { ... }, - -- }, + }, + + tunneldigger = { + brokers = {'vpn1.alpha-centauri.freifunk.net'} }, bandwidth_limit = { @@ -225,12 +334,24 @@ fastd_mesh_vpn mesh_on_wan \: optional Enables the mesh on the WAN port (``true`` or ``false``). + :: + + mesh_on_wan = true, mesh_on_lan \: optional Enables the mesh on the LAN port (``true`` or ``false``). + :: + + mesh_on_lan = true, + +poe_passthrough \: optional + Enable PoE passthrough by default on hardware with such a feature. autoupdater \: package Configuration for the autoupdater feature of Gluon. + + The mirrors are checked in random order until the manifest could be downloaded + successfully or all mirrors have been tried. :: autoupdater = { @@ -240,7 +361,7 @@ autoupdater \: package name = 'stable', mirrors = { 'http://[fdca:ffee:babe:1::fec1]/firmware/stable/sysupgrade/', - 'http://autoupdate.entenhausen.freifunk.net/firmware/stable/sysupgrade/', + 'http://autoupdate.alpha-centauri.freifunk.net/firmware/stable/sysupgrade/', }, -- Number of good signatures required good_signatures = 2, @@ -255,6 +376,39 @@ autoupdater \: package All configured mirrors must be reachable from the nodes via IPv6. If you don't want to set an IPv6 address explicitly, but use a hostname (which is recommended), see also the :ref:`FAQ `. +config_mode \: optional + Additional configuration for the configuration web interface. All values are + optional. + + When no hostname is specified, a default hostname based on the *hostname_prefix* + and the node's primary MAC address is assigned. Manually setting a hostname + can be enforced by setting *hostname.optional* to *false*. + + By default, no altitude fields are shown by the *gluon-config-mode-geo-location* + package. If *geo_location.show_altitude* is set to *true*, the *gluon-config-mode:altitude-label* + and *gluon-config-mode:altitude-help* strings must be provided in the site i18n + data as well. + + The remote login page only shows SSH key configuration by default. A + password form can be displayed by setting *remote_login.show_password_form* + to true; in this case, *remote_login.min_password_length* defines the + minimum password length. + :: + + config_mode = { + hostname = { + optional = false, + }, + geo_location = { + show_altitude = true, + }, + remote_login = { + show_password_form = true, + min_password_length = 10, + }, + }, + + roles \: optional Optional role definitions. Nodes will announce their role inside the mesh. This will allow in the backend to distinguish between normal, backbone and @@ -262,11 +416,11 @@ roles \: optional the community which roles to define. See the section below as an example. ``default`` takes the default role which is set initially. This value should be part of ``list``. If you want node owners to change the role via config mode add - the package ``gluon-luci-node-role`` to ``site.mk``. + the package ``gluon-web-node-role`` to ``site.mk``. - The strings to display in the LuCI interface can be configured per language in the + The strings to display in the web interface are configured per language in the ``i18n/en.po``, ``i18n/de.po``, etc. files of the site repository using message IDs like - ``gluon-luci-node-role:role:node`` and ``gluon-luci-node-role:role:backbone``. + ``gluon-web-node-role:role:node`` and ``gluon-web-node-role:role:backbone``. :: roles = { @@ -288,30 +442,20 @@ setup_mode \: package skip = true, }, -legacy \: package - Configuration for the legacy upgrade path. - This is only required in communities upgrading from Lübeck's LFF-0.3.x. - :: +Build configuration +------------------- - legacy = { - version_files = {'/etc/.freifunk_version_keep', '/etc/.eff_version_keep'}, - old_files = {'/etc/config/config_mode', '/etc/config/ffeh', '/etc/config/freifunk'}, - config_mode_configs = {'config_mode', 'ffeh', 'freifunk'}, - fastd_configs = {'ffeh_mesh_vpn', 'mesh_vpn'}, - mesh_ifname = 'freifunk', - tc_configs = {'ffki', 'freifunk'}, - wifi_names = {'wifi_freifunk', 'wifi_freifunk5', 'wifi_mesh', 'wifi_mesh5'}, - } - -Packages --------- - -The ``site.mk`` is a Makefile which should define constants +The ``site.mk`` is a Makefile which defines various values involved in the build process of Gluon. +GLUON_FEATURES + Defines a list of features to include. The feature list is used to generate + the default package set. + GLUON_SITE_PACKAGES - Defines a list of packages which should be installed additionally - to the ``gluon-core`` package. + Defines a list of packages which should be installed in addition to the + default package set. It is also possible to remove packages from the + default set by prepending a minus sign to the package name. GLUON_RELEASE The current release version Gluon should use. @@ -320,10 +464,86 @@ GLUON_PRIORITY The default priority for the generated manifests (see the autoupdater documentation for more information). +GLUON_REGION + Region code to build into images where necessary. Valid values are the empty string, + ``us`` and ``eu``. + GLUON_LANGS List of languages (as two-letter-codes) to be included in the web interface. Should always contain ``en``. +GLUON_WLAN_MESH + Setting this to ``11s`` or ``ibss`` will enable generation of matching images for devices which don't + support both meshing modes, either at all (e.g. ralink and mediatek don't support AP+IBSS) or in the + same firmware (ath10k-based 5GHz). Defaults to ``11s``. + +.. _user-site-feature-flags: + +Feature flags +^^^^^^^^^^^^^ + +With the addition of more and more features that interact in complex ways, it +has become necessary to split certain packages into multiple parts, so it is +possible to install just what is needed for a specific usecase. One example +is the package *gluon-status-page-mesh-batman-adv*: There are batman-adv-specific +status page components; they should only be installed when both batman-adv and +the status page are enabled, making the addition of a specific package for this +combination necessary. + +With the ongoing modularization, e.g. for the purpose of supporting new +routing protocols, specifying all such split packages in *site.mk* would +soon become very cumbersome: In the future, further components like +respondd support or languages might be split off as separate packages, +leading to entangled package names like *gluon-mesh-vpn-fastd-respondd* or +*gluon-status-page-mesh-batman-adv-i18n-de*. + +For this reason, we have introduced *feature flags*, which can be specified +in the *GLUON_FEATURES* variable. These flags allow to specify a set of features +on a higher level than individual package names. + +Most Gluon packages can simply be specified as feature flags by removing the ``gluon-`` +prefix: The feature flag corresponding to the package *gluon-mesh-batman-adv-15* is +*mesh-batman-adv-15*. + +The file ``package/features`` in the Gluon repository (or +``features`` in site feeds) can specify additional rules for deriving package lists +from feature flags, e.g. specifying both *status-page* and either *mesh-batman-adv-14* +or *mesh-batman-adv-15* will automatically select the additional package +*gluon-status-page-mesh-batman-adv*. In the future, selecting the flags +*mesh-vpn-fastd* and *respondd* might automatically enable the additional +package *gluon-mesh-vpn-fastd-respondd*, and enabling *status-page* and +*mesh-batman-adv-15* (or *-14*) with ``de`` in *GLUON_LANGS* could +add the package *gluon-status-page-mesh-batman-adv-i18n-de*. + +In short, it is not necessary anymore to list all the individual packages that are +relevant for a firmware; instead, the package list is derived from a list of feature +flags using a flexible ruleset defined in the Gluon repo or site package feeds. +To some extent, it will even allow us to further modularize existing Gluon packages, +without necessitating changes to existing site configurations. + +It is still possible to override such automatic rules using *GLUON_SITE_PACKAGES* +(e.g., ``-gluon-status-page-mesh-batman-adv`` to remove the automatically added +package *gluon-status-page-mesh-batman-adv*). + +For convenience, there are two feature flags that do not directly correspond to a Gluon +package: + +* web-wizard + + Includes the *gluon-config-mode-...* base packages (hostname, geolocation and contact info), + as well as the *gluon-config-mode-autoupdater* (when *autoupdater* is in *GLUON_FEATURES*), + and *gluon-config-mode-mesh-vpn* (when *mesh-vpn-fastd* or *mesh-vpn-tunneldigger* are in + *GLUON_FEATURES*) + +* web-advanced + + Includes the *gluon-web-...* base packages (admin, network, WiFi config), + as well as the *gluon-web-autoupdater* (when *autoupdater* is in *GLUON_FEATURES*) + +We recommend to use *GLUON_SITE_PACKAGES* for non-Gluon OpenWrt packages only and +completely rely on *GLUON_FEATURES* for Gluon packages, as it is shown in the +example *site.mk*. + .. _site-config-mode-texts: Config mode texts @@ -338,6 +558,27 @@ gluon-config-mode:welcome gluon-config-mode:pubkey Information about the public VPN key on the reboot page. +gluon-config-mode:novpn + Information shown on the reboot page, if the mesh VPN was not selected. + +gluon-config-mode:altitude-label + Label for the ``altitude`` field + +gluon-config-mode:altitude-help + Description for the usage of the ``altitude`` field + +gluon-config-mode:contact-help + Description for the usage of the ``contact`` field + +gluon-config-mode:contact-note + Note shown (in small font) below the ``contact`` field + +gluon-config-mode:hostname-help + Description for the usage of the ``hostname`` field + +gluon-config-mode:geo-location-help + Description for the usage of the longitude/latitude fields + gluon-config-mode:reboot General information shown on the reboot page. @@ -355,6 +596,41 @@ utilities are installed. Depending on the context, you might be able to use comments like ```` as translations to effectively hide the text. +Site modules +------------ + +The file ``modules`` in the site repository is completely optional and can be used +to supply additional package feeds from which packages are built. The git repositories +specified here are retrieved in addition to the default feeds when ``make update`` +it called. + +This file's format is very similar to the toplevel ``modules`` file of the Gluon +tree, with the important different that the list of feeds must be assigned to +the variable ``GLUON_SITE_FEEDS``. Multiple feed names must be separated by spaces, +for example:: + + GLUON_SITE_FEEDS='foo bar' + +The feed names may only contain alphanumerical characters, underscores and slashes. +For each of the feeds, the following variables are used to specify how to update +the feed: + +PACKAGES_${feed}_REPO + The URL of the git repository to clone (usually ``git://`` or ``http(s)://``) + +PACKAGES_${feed}_COMMIT + The commit ID of the repository to use + +PACKAGES_${feed}_BRANCH + Optional: The branch of the repository the given commit ID can be found in. + Defaults to the default branch of the repository (usually ``master``) + +These variables are always all uppercase, so for an entry ``foo`` in GLUON_SITE_FEEDS, +the corresponding configuration variables would be ``PACKAGES_FOO_REPO``, +``PACKAGES_FOO_COMMIT`` and ``PACKAGES_FOO_BRANCH``. Slashes in feed names are +replaced by underscores to get valid shell variable identifiers. + + Examples -------- @@ -394,23 +670,38 @@ site-repos in the wild This is a non-exhaustive list of site-repos from various communities: * `site-ffa `_ (Altdorf, Landshut & Umgebung) +* `site-ffac `_ (Regio Aachen) * `site-ffbs `_ (Braunschweig) * `site-ffhb `_ (Bremen) -* `site-ffda `_ (Darmstadt) +* `site-ffda `_ (Darmstadt) +* `site-ff3l `_ (Dreiländereck) +* `site-ffeh `_ (Ehingen) +* `site-fffl `_ (Flensburg) * `site-ffgoe `_ (Göttingen) +* `site-ffgt-rhw `_ (Guetersloh) * `site-ffhh `_ (Hamburg) -* `site-ffho `_ (Hochstift) +* `site-ffho `_ (Hochstift) * `site-ffhgw `_ (Greifswald) +* `site-ffka `_ (Karlsruhe) +* `site-ffki `_ (Kiel) +* `site-fflz `_ (Lausitz) * `site-ffl `_ (Leipzig) * `site-ffhl `_ (Lübeck) +* `site-fflg `_ (Lüneburg) * `site-ffmd `_ (Magdeburg) -* `site-ffmwu `_ (Mainz, Wiesbaden & Umgebung) +* `site-ffmwu `_ (Mainz, Wiesbaden & Umgebung) * `site-ffmyk `_ (Mayen-Koblenz) +* `site-ffmo `_ (Moers) +* `site-ffmg `_ (Mönchengladbach) * `site-ffm `_ (München) +* `site-ffhmue `_ (Münden) * `site-ffms `_ (Münsterland) +* `site-neuss `_ (Neuss) +* `site-ffniers `_ (Niersufer) +* `site-ffndh `_ (Nordheide) * `site-ffnw `_ (Nordwest) -* `site-ffka `_ (Karlsruhe) -* `site-ffrl `_ (Rheinland) -* `site-ffrg `_ (Ruhrgebiet) +* `site-ffrgb `_ (Regensburg) +* `site-ffrn `_ (Rhein-Neckar) +* `site-ffruhr `_ (Ruhrgebiet, Multi-Communities) * `site-ffs `_ (Stuttgart) * `site-fftr `_ (Trier) diff --git a/docs/user/x86.rst b/docs/user/x86.rst index 9364b7ed..a65edfcc 100644 --- a/docs/user/x86.rst +++ b/docs/user/x86.rst @@ -22,15 +22,8 @@ The following targets for x86 images exist: These images only differ in the image file format, the content is the same. Therefore there is only a single `x86-generic` sysupgrade image instead of three. - Please note that the `x86-generic` image doesn't include VirtIO support, so another virtual NIC - like `pcnet32` must be chosen when using VirtualBox. - -`x86-kvm` - The `x86-kvm` image uses VirtIO as its harddisk and network driver. - -`x86-xen_domu` - The `x86-xen_domu` target contains the necessary drivers for use in Xen. +`x86-geode` + x86 image for Geode CPUs. `x86-64` - 64bit version of `x86-generic`. Also has VirtIO support, so there's no need for an - `x86-64-kvm` target. + 64bit version of `x86-generic`. diff --git a/include/config b/include/config deleted file mode 100644 index 12f8a7d4..00000000 --- a/include/config +++ /dev/null @@ -1,22 +0,0 @@ -CONFIG_IMAGEOPT=y -# CONFIG_PER_FEED_REPO is not set -# CONFIG_TARGET_ROOTFS_INITRAMFS is not set -CONFIG_DEVEL=y -CONFIG_ALL_KMODS=y - -CONFIG_BUSYBOX_CUSTOM=y -CONFIG_BUSYBOX_CONFIG_SHA512SUM=y -# CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set -CONFIG_BUSYBOX_CONFIG_IP=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_ADDRESS=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_LINK=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_ROUTE=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_TUNNEL=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_RULE=y -CONFIG_BUSYBOX_CONFIG_FEATURE_IP_SHORT_FORMS=y -CONFIG_BUSYBOX_CONFIG_FEATURE_WGET_TIMEOUT=y - -CONFIG_ATH_USER_REGD=y -CONFIG_PACKAGE_ATH_DEBUG=y - -CONFIG_LUCI_SRCDIET=y diff --git a/include/gluon.mk b/include/gluon.mk deleted file mode 100644 index d49dc13f..00000000 --- a/include/gluon.mk +++ /dev/null @@ -1,82 +0,0 @@ -ifneq ($(__gluon_inc),1) -__gluon_inc=1 - -GLUON_SITEDIR ?= $(GLUONDIR)/site -GLUON_BUILDDIR ?= $(GLUONDIR)/build - -GLUON_ORIGOPENWRTDIR := $(GLUONDIR)/openwrt -GLUON_SITE_CONFIG := $(GLUON_SITEDIR)/site.conf - -GLUON_OUTPUTDIR ?= $(GLUONDIR)/output -GLUON_IMAGEDIR ?= $(GLUON_OUTPUTDIR)/images -GLUON_MODULEDIR ?= $(GLUON_OUTPUTDIR)/modules - -GLUON_OPKG_KEY ?= $(GLUON_BUILDDIR)/gluon-opkg-key - -export GLUONDIR GLUON_SITEDIR GLUON_BUILDDIR GLUON_SITE_CONFIG GLUON_OUTPUTDIR GLUON_IMAGEDIR GLUON_MODULEDIR - - -BOARD_BUILDDIR = $(GLUON_BUILDDIR)/$(GLUON_TARGET) -BOARD_KDIR = $(BOARD_BUILDDIR)/kernel - -export BOARD_BUILDDIR - - -LINUX_RELEASE := 2 -export LINUX_RELEASE - - -GLUON_OPENWRTDIR = $(BOARD_BUILDDIR)/openwrt - - -$(GLUON_SITEDIR)/site.mk: - $(error There was no site configuration found. Please check out a site configuration to $(GLUON_SITEDIR)) - --include $(GLUON_SITEDIR)/site.mk - - -GLUON_VERSION := $(shell cd $(GLUONDIR) && git describe --always 2>/dev/null || echo unknown) -export GLUON_VERSION - -GLUON_LANGS ?= en -export GLUON_LANGS - - -ifeq ($(OPENWRT_BUILD),1) -ifeq ($(GLUON_TOOLS),1) - -GLUON_OPENWRT_FEEDS := base packages luci routing telephony management -export GLUON_OPENWRT_FEEDS - -GLUON_SITE_CODE := $(shell $(GLUONDIR)/scripts/site.sh site_code) -export GLUON_SITE_CODE - -ifeq ($(GLUON_RELEASE),) -$(error GLUON_RELEASE not set. GLUON_RELEASE can be set in site.mk or on the command line.) -endif -export GLUON_RELEASE - -endif -endif - - -define merge-lists -$(1) := -$(foreach var,$(2),$(1) := $$(filter-out -% $$(patsubst -%,%,$$(filter -%,$$($(var)))),$$($(1)) $$($(var))) -) -endef - -GLUON_TARGETS := - -define GluonTarget -gluon_target := $(1)$$(if $(2),-$(2)) -GLUON_TARGETS += $$(gluon_target) -GLUON_TARGET_$$(gluon_target)_BOARD := $(1) -GLUON_TARGET_$$(gluon_target)_SUBTARGET := $(2) -endef - -GLUON_DEFAULT_PACKAGES := gluon-core kmod-ipv6 firewall ip6tables -uboot-envtools -wpad-mini hostapd-mini - -override DEFAULT_PACKAGES.router := - -endif #__gluon_inc diff --git a/include/package.mk b/include/package.mk deleted file mode 100644 index 76e109e2..00000000 --- a/include/package.mk +++ /dev/null @@ -1,35 +0,0 @@ -include $(INCLUDE_DIR)/package.mk - -# Annoyingly, make's shell function replaces all newlines with spaces, so we have to do some escaping work. Yuck. -define GluonCheckSite -[ -z "$$GLUONDIR" ] || sed -e 's/-@/\n/g' -e 's/+@/@/g' <<'END__GLUON__CHECK__SITE' | "$$GLUONDIR"/scripts/check_site.sh -$(shell cat $(1) | sed -ne '1h; 1!H; $$ {g; s/@/+@/g; s/\n/-@/g; p}') -END__GLUON__CHECK__SITE -endef - -# Languages supported by LuCi -GLUON_SUPPORTED_LANGS := ca zh_cn en fr de el he hu it ja ms no pl pt_br pt ro ru es sv uk vi - -GLUON_I18N_PACKAGES := $(foreach lang,$(GLUON_SUPPORTED_LANGS),+LUCI_LANG_$(lang):luci-i18n-base-$(lang)) -GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_LUCI_LANG_$(lang)) -GLUON_ENABLED_LANGS := $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_LUCI_LANG_$(lang)),$(lang))) - - -define GluonBuildI18N - mkdir -p $$(PKG_BUILD_DIR)/i18n - for lang in $$(GLUON_ENABLED_LANGS); do \ - if [ -e $(2)/$$$$lang.po ]; then \ - rm -f $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \ - po2lmo $(2)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \ - fi; \ - done -endef - -define GluonInstallI18N - $$(INSTALL_DIR) $(2)/usr/lib/lua/luci/i18n - for lang in $$(GLUON_ENABLED_LANGS); do \ - if [ -e $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo ]; then \ - $$(INSTALL_DATA) $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo $(2)/usr/lib/lua/luci/i18n/$(1).$$$$lang.lmo; \ - fi; \ - done -endef diff --git a/include/toplevel.mk b/include/toplevel.mk deleted file mode 100644 index 087a7a19..00000000 --- a/include/toplevel.mk +++ /dev/null @@ -1,62 +0,0 @@ -# Makefile for OpenWrt -# -# Copyright (C) 2007-2012 OpenWrt.org -# Copyright (C) 2013-2014 Project Gluon -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -RELEASE:=Chaos Calmer -PREP_MK= OPENWRT_BUILD= QUIET=0 - -export IS_TTY=$(shell tty -s && echo 1 || echo 0) - -include $(GLUONDIR)/include/verbose.mk - -REVISION:=$(shell [ -d $(TOPDIR) ] && cd $(TOPDIR) && ./scripts/getver.sh 2>/dev/null) - -HOSTCC ?= gcc -OPENWRTVERSION:=$(RELEASE)$(if $(REVISION), ($(REVISION))) -export RELEASE -export REVISION -export OPENWRTVERSION -export IS_TTY=$(shell tty -s && echo 1 || echo 0) -export LD_LIBRARY_PATH:=$(subst ::,:,$(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):)$(STAGING_DIR_HOST)/lib) -export DYLD_LIBRARY_PATH:=$(subst ::,:,$(if $(DYLD_LIBRARY_PATH),$(DYLD_LIBRARY_PATH):)$(STAGING_DIR_HOST)/lib) -export GIT_CONFIG_PARAMETERS='core.autocrlf=false' -export MAKE_JOBSERVER=$(filter --jobserver%,$(MAKEFLAGS)) - -# prevent perforce from messing with the patch utility -unexport P4PORT P4USER P4CONFIG P4CLIENT - -# prevent user defaults for quilt from interfering -unexport QUILT_PATCHES QUILT_PATCH_OPTS - -unexport C_INCLUDE_PATH CROSS_COMPILE ARCH - -# prevent distro default LPATH from interfering -unexport LPATH - -# make sure that a predefined CFLAGS variable does not disturb packages -export CFLAGS= - -ifneq ($(shell $(HOSTCC) 2>&1 | grep clang),) - export HOSTCC_REAL?=$(HOSTCC) - export HOSTCC_WRAPPER:=$(TOPDIR)/scripts/clang-gcc-wrapper -else - export HOSTCC_WRAPPER:=$(HOSTCC) -endif - -SCAN_COOKIE?=$(shell echo $$$$) -export SCAN_COOKIE - -SUBMAKE:=umask 022; $(SUBMAKE) - -ULIMIT_FIX=_limit=`ulimit -n`; [ "$$_limit" = "unlimited" -o "$$_limit" -ge 1024 ] || ulimit -n 1024; - -FORCE: ; - -.PHONY: FORCE -.NOTPARALLEL: - diff --git a/include/verbose.mk b/include/verbose.mk deleted file mode 100644 index d34f55fc..00000000 --- a/include/verbose.mk +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -ifndef OPENWRT_VERBOSE - OPENWRT_VERBOSE:= -endif -ifeq ("$(origin V)", "command line") - OPENWRT_VERBOSE:=$(V) -endif - -ifeq ($(OPENWRT_VERBOSE),1) - OPENWRT_VERBOSE:=w -endif -ifeq ($(OPENWRT_VERBOSE),99) - OPENWRT_VERBOSE:=s -endif - -ifeq ($(NO_TRACE_MAKE),) -NO_TRACE_MAKE := $(MAKE) V=s$(OPENWRT_VERBOSE) -export NO_TRACE_MAKE -endif - -ifeq ($(IS_TTY),1) - ifneq ($(strip $(NO_COLOR)),1) - _Y:=\\033[33m - _R:=\\033[31m - _N:=\\033[m - endif -endif - -ifeq ($(findstring s,$(OPENWRT_VERBOSE)),) - define MESSAGE - printf "$(_Y)%s$(_N)\n" "$(1)" >&8 - endef - - define ERROR_MESSAGE - printf "$(_R)%s$(_N)\n" "$(1)" >&8 - endef - - ifeq ($(QUIET),1) - ifneq ($(CURDIR),$(TOPDIR)) - _DIR:=$(patsubst $(TOPDIR)/%,%,${CURDIR}) - else - _DIR:= - endif - _NULL:=$(if $(MAKECMDGOALS),$(shell \ - $(call MESSAGE, make[$(MAKELEVEL)]$(if $(_DIR), -C $(_DIR)) $(MAKECMDGOALS)); \ - )) - SUBMAKE=$(MAKE) - else - SILENT:=>/dev/null $(if $(findstring w,$(OPENWRT_VERBOSE)),,2>&1) - export QUIET:=1 - SUBMAKE=cmd() { $(SILENT) $(MAKE) -s $$* < /dev/null || { echo "make $$*: build failed. Please re-run make with V=s to see what's going on"; false; } } 8>&1 9>&2; cmd - endif - - .SILENT: $(MAKECMDGOALS) -else - SUBMAKE=$(MAKE) -w - define MESSAGE - printf "%s\n" "$(1)" - endef - ERROR_MESSAGE=$(MESSAGE) -endif diff --git a/modules b/modules index 1336e245..fefeb87e 100644 --- a/modules +++ b/modules @@ -1,18 +1,20 @@ GLUON_FEEDS='openwrt gluon routing luci' -OPENWRT_REPO=git://git.openwrt.org/15.05/openwrt.git -OPENWRT_COMMIT=eadf19c0b43d2f75f196ea8d875a08c7c348530c +LEDE_REPO=https://git.openwrt.org/openwrt/openwrt.git +LEDE_BRANCH=lede-17.01 +LEDE_COMMIT=0a2c984222d03d940c52c3675849dd6398b34e64 -PACKAGES_OPENWRT_REPO=git://github.com/openwrt/packages.git -PACKAGES_OPENWRT_COMMIT=9622fe984bba3a4547f48bc507ebaba7637eb2b0 -PACKAGES_OPENWRT_BRANCH=for-15.05 +PACKAGES_OPENWRT_REPO=https://github.com/openwrt/packages.git +PACKAGES_OPENWRT_BRANCH=lede-17.01 +PACKAGES_OPENWRT_COMMIT=338690b2f79e2c7090be4e9adbb19b452c9e3c36 -PACKAGES_GLUON_REPO=git://github.com/freifunk-gluon/packages.git -PACKAGES_GLUON_COMMIT=63376e23c81e53c21d3c5250c3fb7444a90dc019 +PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git +PACKAGES_GLUON_COMMIT=be2c35785994e443d895225c7240474a46f64f5e -PACKAGES_ROUTING_REPO=git://github.com/openwrt-routing/packages.git -PACKAGES_ROUTING_COMMIT=2a8338559de5c4b077cde7a83f43f4700a17d5cc +PACKAGES_ROUTING_REPO=https://github.com/openwrt-routing/packages.git +PACKAGES_ROUTING_BRANCH=openwrt-18.06 +PACKAGES_ROUTING_COMMIT=1b9d1c419f0ecefda51922a7845ab2183d6acd76 -PACKAGES_LUCI_REPO=git://github.com/openwrt/luci.git -PACKAGES_LUCI_COMMIT=cdcdfd2594634804ab09dc8105e46116edce0cd6 -PACKAGES_LUCI_BRANCH=for-15.05 +PACKAGES_LUCI_REPO=https://github.com/openwrt/luci.git +PACKAGES_LUCI_BRANCH=lede-17.01 +PACKAGES_LUCI_COMMIT=1f014bd2180b364bec4c3f6457f72a0621884f9a diff --git a/overlay/opkg.mk b/overlay/opkg.mk new file mode 100644 index 00000000..ccbd2573 --- /dev/null +++ b/overlay/opkg.mk @@ -0,0 +1,10 @@ +# LEDE doesn't have a nice way to set the list of feeds in +# /etc/opkg/distfeeds.conf, so we use this overlay file (which is included by +# the opkg package Makefile though LEDE's IncludeOverlay mechanism). + +# The following definitions make /etc/opkg/distfeeds.conf match the one included +# in official LEDE builds (by default, FEEDS_DISABLED contains the original list +# of feeds (which are unused by Gluon), and FEEDS_ENABLED our own feed list). + +FEEDS_ENABLED := $(FEEDS_DISABLED) +FEEDS_DISABLED := diff --git a/package/features b/package/features new file mode 100644 index 00000000..210581d5 --- /dev/null +++ b/package/features @@ -0,0 +1,26 @@ +nodefault 'web-wizard' + +packages 'web-wizard' \ + 'gluon-config-mode-hostname' \ + 'gluon-config-mode-geo-location' \ + 'gluon-config-mode-contact-info' + +packages 'web-wizard & autoupdater' \ + 'gluon-config-mode-autoupdater' + +packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \ + 'gluon-config-mode-mesh-vpn' + + +nodefault 'web-advanced' + +packages 'web-advanced' \ + 'gluon-web-admin' \ + 'gluon-web-network' \ + 'gluon-web-wifi-config' + +packages 'web-advanced & autoupdater' \ + 'gluon-web-autoupdater' + +packages 'status-page & (mesh-batman-adv-14 | mesh-batman-adv-15)' \ + 'gluon-status-page-mesh-batman-adv' diff --git a/package/gluon-alfred/Makefile b/package/gluon-alfred/Makefile index ca3ae327..7c173a77 100644 --- a/package/gluon-alfred/Makefile +++ b/package/gluon-alfred/Makefile @@ -4,29 +4,11 @@ PKG_NAME:=gluon-alfred PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-alfred - SECTION:=gluon - CATEGORY:=Gluon - DEPENDS:=+gluon-core +gluon-respondd +gluon-neighbour-info +micrond +alfred + DEPENDS:=+gluon-core +gluon-respondd +gluon-neighbour-info gluon-mesh-batman-adv +micrond +alfred TITLE:=Configure alfred endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-alfred/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-alfred)) +$(eval $(call BuildPackageGluon,gluon-alfred)) diff --git a/package/gluon-alfred/files/lib/gluon/upgrade/500-enable-alfred b/package/gluon-alfred/files/lib/gluon/upgrade/500-enable-alfred deleted file mode 100755 index d3802d8a..00000000 --- a/package/gluon-alfred/files/lib/gluon/upgrade/500-enable-alfred +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/lua - -local uci = require 'luci.model.uci' -local c = uci.cursor() - - -c:delete('alfred', 'alfred') -c:section('alfred', 'alfred', 'alfred', - { - interface = 'br-client', - mode = 'slave', - batmanif = 'bat0', - start_vis = '1', - run_facters = '0', - } -) - -c:save('alfred') diff --git a/package/gluon-alfred/luasrc/lib/gluon/upgrade/400-alfred-firewall b/package/gluon-alfred/luasrc/lib/gluon/upgrade/400-alfred-firewall new file mode 100755 index 00000000..eaf727cd --- /dev/null +++ b/package/gluon-alfred/luasrc/lib/gluon/upgrade/400-alfred-firewall @@ -0,0 +1,14 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + +uci:section('firewall', 'rule', 'mesh_respondd', { + name = 'mesh_respondd', + src = 'mesh', + src_ip = 'fe80::/64', + dest_port = '16962', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:save('firewall') diff --git a/package/gluon-alfred/luasrc/lib/gluon/upgrade/500-enable-alfred b/package/gluon-alfred/luasrc/lib/gluon/upgrade/500-enable-alfred new file mode 100755 index 00000000..e1a28080 --- /dev/null +++ b/package/gluon-alfred/luasrc/lib/gluon/upgrade/500-enable-alfred @@ -0,0 +1,14 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + +uci:delete('alfred', 'alfred') +uci:section('alfred', 'alfred', 'alfred', { + interface = 'br-client', + mode = 'slave', + batmanif = 'bat0', + start_vis = true, + run_facters = false, +}) + +uci:save('alfred') diff --git a/package/gluon-authorized-keys/Makefile b/package/gluon-authorized-keys/Makefile index 6ef90da3..2995107a 100644 --- a/package/gluon-authorized-keys/Makefile +++ b/package/gluon-authorized-keys/Makefile @@ -3,34 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-authorized-keys PKG_VERSION:=2 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-authorized-keys - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Fill /etc/dropbear/authorized_keys from site.conf DEPENDS:=+gluon-core endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-authorized-keys/install - $(CP) ./files/* $(1)/ -endef - -define Package/gluon-authorized-keys/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-authorized-keys)) +$(eval $(call BuildPackageGluon,gluon-authorized-keys)) diff --git a/package/gluon-authorized-keys/check_site.lua b/package/gluon-authorized-keys/check_site.lua index d1acfabe..7daf2115 100644 --- a/package/gluon-authorized-keys/check_site.lua +++ b/package/gluon-authorized-keys/check_site.lua @@ -1 +1 @@ -need_string_array 'authorized_keys' +need_string_array(in_site({'authorized_keys'})) diff --git a/package/gluon-authorized-keys/files/lib/gluon/upgrade/100-authorized-keys b/package/gluon-authorized-keys/luasrc/lib/gluon/upgrade/100-authorized-keys similarity index 76% rename from package/gluon-authorized-keys/files/lib/gluon/upgrade/100-authorized-keys rename to package/gluon-authorized-keys/luasrc/lib/gluon/upgrade/100-authorized-keys index 643fa076..34efd0b8 100755 --- a/package/gluon-authorized-keys/files/lib/gluon/upgrade/100-authorized-keys +++ b/package/gluon-authorized-keys/luasrc/lib/gluon/upgrade/100-authorized-keys @@ -1,6 +1,6 @@ #!/usr/bin/lua -local site = require 'gluon.site_config' +local site = require 'gluon.site' local file = '/etc/dropbear/authorized_keys' local keys = {} @@ -14,7 +14,7 @@ end pcall(load_keys) local f = io.open(file, 'a') -for _, key in ipairs(site.authorized_keys) do +for _, key in ipairs(site.authorized_keys()) do if not keys[key] then f:write(key .. '\n') end diff --git a/package/gluon-autoupdater/Makefile b/package/gluon-autoupdater/Makefile index 40120fa9..d6e87499 100644 --- a/package/gluon-autoupdater/Makefile +++ b/package/gluon-autoupdater/Makefile @@ -2,40 +2,30 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-autoupdater PKG_VERSION:=4 -PKG_RELEASE:=$(GLUON_BRANCH) -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS := respondd +PKG_CONFIG_DEPENDS := CONFIG_GLUON_BRANCH -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-autoupdater - SECTION:=gluon - CATEGORY:=Gluon DEPENDS:=+gluon-core +libgluonutil +micrond +autoupdater TITLE:=Automatically update firmware endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ +define Package/gluon-autoupdater/config +config GLUON_BRANCH + string "Gluon autoupdater branch" + depends on PACKAGE_gluon-autoupdater + default "" endef define Package/gluon-autoupdater/install - $(CP) ./files/* $(1)/ + $(Gluon/Build/Install) - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/autoupdater.so - - if [ '$(GLUON_BRANCH)' ]; then \ - $(INSTALL_DIR) $(1)/lib/gluon/autoupdater; \ - echo '$(GLUON_BRANCH)' > $(1)/lib/gluon/autoupdater/default_branch; \ - fi +ifneq ($(CONFIG_GLUON_BRANCH),"") + $(INSTALL_DIR) $(1)/lib/gluon/autoupdater + echo '$(call qstrip,$(CONFIG_GLUON_BRANCH))' > $(1)/lib/gluon/autoupdater/default_branch +endif endef -define Package/gluon-autoupdater/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-autoupdater)) +$(eval $(call BuildPackageGluon,gluon-autoupdater)) diff --git a/package/gluon-autoupdater/check_site.lua b/package/gluon-autoupdater/check_site.lua index 9f443fec..de9beef0 100644 --- a/package/gluon-autoupdater/check_site.lua +++ b/package/gluon-autoupdater/check_site.lua @@ -1,14 +1,10 @@ -need_string 'autoupdater.branch' +need_string(in_site({'autoupdater', 'branch'})) -local function check_branch(k, _) - assert_uci_name(k) +need_table({'autoupdater', 'branches'}, function(branch) + need_alphanumeric_key(branch) - local prefix = string.format('autoupdater.branches[%q].', k) - - need_string(prefix .. 'name') - need_string_array(prefix .. 'mirrors') - need_number(prefix .. 'good_signatures') - need_string_array(prefix .. 'pubkeys') -end - -need_table('autoupdater.branches', check_branch) + need_string(in_site(extend(branch, {'name'}))) + need_string_array_match(extend(branch, {'mirrors'}), '^http://') + need_number(in_site(extend(branch, {'good_signatures'}))) + need_string_array_match(in_site(extend(branch, {'pubkeys'})), '^%x+$') +end) diff --git a/package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh b/package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh index 36ddd971..24ef2f90 100644 --- a/package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh +++ b/package/gluon-autoupdater/files/lib/gluon/autoupdater/lib.sh @@ -2,15 +2,15 @@ stop() { - if [ -x /etc/init.d/$1 ]; then + if [ -x /etc/init.d/"$1" ]; then echo "Stopping $1..." - /etc/init.d/$1 stop + /etc/init.d/"$1" stop fi } start_enabled() { - if [ -x /etc/init.d/$1 ] && /etc/init.d/$1 enabled; then + if [ -x /etc/init.d/"$1" ] && /etc/init.d/"$1" enabled; then echo "Starting $1..." - /etc/init.d/$1 start + /etc/init.d/"$1" start fi } diff --git a/package/gluon-autoupdater/files/lib/gluon/upgrade/500-autoupdater b/package/gluon-autoupdater/files/lib/gluon/upgrade/500-autoupdater deleted file mode 100755 index 17006b70..00000000 --- a/package/gluon-autoupdater/files/lib/gluon/upgrade/500-autoupdater +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -local c = uci.cursor() - - -for name, config in pairs(site.autoupdater.branches) do - c:delete('autoupdater', name) - c:section('autoupdater', 'branch', name, - { - name = config.name, - mirror = config.mirrors, - good_signatures = config.good_signatures, - pubkey = config.pubkeys, - } - ) -end - -if not c:get('autoupdater', 'settings') then - local enabled = 0 - local branch = site.autoupdater.branch - - local f = io.open('/lib/gluon/autoupdater/default_branch') - if f then - enabled = 1 - branch = f:read('*line') - f:close() - end - - c:section('autoupdater', 'autoupdater', 'settings', - { - enabled = enabled, - branch = branch, - } - ) -end - -c:set('autoupdater', 'settings', 'version_file', '/lib/gluon/release') - -c:save('autoupdater') - - -local autoupdater_util = require 'autoupdater.util' -autoupdater_util.randomseed() - - --- Perform updates at a random time between 04:00 and 05:00, and once an hour --- a fallback update (used after the regular updates haven't -local minute = math.random(0, 59) - -local f = io.open('/usr/lib/micron.d/autoupdater', 'w') -f:write(string.format('%i 4 * * * /usr/sbin/autoupdater\n', minute)) -f:write(string.format('%i 0-3,5-23 * * * /usr/sbin/autoupdater --fallback\n', minute)) -f:close() diff --git a/package/gluon-autoupdater/luasrc/lib/gluon/upgrade/500-autoupdater b/package/gluon-autoupdater/luasrc/lib/gluon/upgrade/500-autoupdater new file mode 100755 index 00000000..88214a86 --- /dev/null +++ b/package/gluon-autoupdater/luasrc/lib/gluon/upgrade/500-autoupdater @@ -0,0 +1,53 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + + +for name, config in pairs(site.autoupdater.branches()) do + uci:delete('autoupdater', name) + uci:section('autoupdater', 'branch', name, { + name = config.name, + mirror = config.mirrors, + good_signatures = config.good_signatures, + pubkey = config.pubkeys, + }) +end + +if not uci:get('autoupdater', 'settings') then + local enabled = false + local branch = site.autoupdater.branch() + + local f = io.open('/lib/gluon/autoupdater/default_branch') + if f then + enabled = true + branch = f:read('*line') + f:close() + end + + uci:section('autoupdater', 'autoupdater', 'settings', { + enabled = enabled, + branch = branch, + }) +end + +uci:set('autoupdater', 'settings', 'version_file', '/lib/gluon/release') + +uci:save('autoupdater') + + +local urandom = io.open('/dev/urandom', 'r') +local seed1, seed2 = urandom:read(2):byte(1, 2) +math.randomseed(seed1*0x100 + seed2) +urandom:close() + +-- Perform updates at a random time between 04:00 and 05:00, and once an hour +-- a fallback update (used after the regular updates haven't worked for +-- (priority+1) days after a firmware release, for example because the node +-- is always offline at night) +local minute = math.random(0, 59) + +local f = io.open('/usr/lib/micron.d/autoupdater', 'w') +f:write(string.format('%i 4 * * * /usr/sbin/autoupdater\n', minute)) +f:write(string.format('%i 0-3,5-23 * * * /usr/sbin/autoupdater --fallback\n', minute)) +f:close() diff --git a/package/gluon-autoupdater/src/respondd.c b/package/gluon-autoupdater/src/respondd.c index 66b7a928..74468fb1 100644 --- a/package/gluon-autoupdater/src/respondd.c +++ b/package/gluon-autoupdater/src/respondd.c @@ -36,6 +36,8 @@ static struct json_object * get_autoupdater(void) { struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + return NULL; ctx->flags &= ~UCI_FLAG_STRICT; struct uci_package *p; diff --git a/package/gluon-client-bridge/Makefile b/package/gluon-client-bridge/Makefile index 6bbfed64..a2daf34b 100644 --- a/package/gluon-client-bridge/Makefile +++ b/package/gluon-client-bridge/Makefile @@ -3,34 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-client-bridge PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-client-bridge - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Provides a bridge and a wireless interface for clients to connect to - DEPENDS:=+gluon-core + DEPENDS:=+gluon-core +kmod-veth +@GLUON_SPECIALIZE_KERNEL:KERNEL_VETH endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-client-bridge/install - $(CP) ./files/* $(1)/ -endef - -define Package/gluon-client-bridge/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-client-bridge)) +$(eval $(call BuildPackageGluon,gluon-client-bridge)) diff --git a/package/gluon-client-bridge/check_site.lua b/package/gluon-client-bridge/check_site.lua index 3a7d81ee..7922fae5 100644 --- a/package/gluon-client-bridge/check_site.lua +++ b/package/gluon-client-bridge/check_site.lua @@ -1,6 +1,15 @@ -for _, config in ipairs({'wifi24', 'wifi5'}) do - if need_table(config .. '.ap', nil, false) then - need_string(config .. '.ap.ssid') - need_boolean(config .. '.ap.disabled', false) - end +need_string_match(in_domain({'next_node', 'mac'}), '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$', false) + +if need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false) then + need_string_match(in_domain({'prefix4'}), '^%d+.%d+.%d+.%d+/%d+$') +end + +need_string_match(in_domain({'next_node', 'ip6'}), '^[%x:]+$', false) + + +for _, config in ipairs({'wifi24', 'wifi5'}) do + if need_table({config, 'ap'}, nil, false) then + need_string_match(in_domain({config, 'ap', 'ssid'}), '^' .. ('.?'):rep(32) .. '$') + need_boolean({config, 'ap', 'disabled'}, false) + end end diff --git a/package/gluon-client-bridge/files/lib/gluon/upgrade/300-gluon-client-bridge-network b/package/gluon-client-bridge/files/lib/gluon/upgrade/300-gluon-client-bridge-network deleted file mode 100755 index 4a897f74..00000000 --- a/package/gluon-client-bridge/files/lib/gluon/upgrade/300-gluon-client-bridge-network +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/lua - -local sysconfig = require 'gluon.sysconfig' -local uci = require('luci.model.uci').cursor() - - -if not uci:get('network', 'client') then - uci:section('network', 'interface', 'client', - { - type = 'bridge', - } - ) -end - -local ifname = uci:get('network', 'client', 'ifname') - -if type(ifname) == 'string' then - uci:delete('network', 'client', 'ifname') - for x in ifname:gmatch("[^%s]+") do - uci:add_to_set('network', 'client', 'ifname', x) - end -end - -uci:set('network', 'client', 'macaddr', sysconfig.primary_mac) - -uci:save('network') diff --git a/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless b/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless deleted file mode 100755 index 3edb39d8..00000000 --- a/package/gluon-client-bridge/files/lib/gluon/upgrade/320-gluon-client-bridge-wireless +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local util = require 'gluon.util' - -local uci = require('luci.model.uci').cursor() - - -local function is_disabled(config, name) - local disabled = config and config.disabled - if uci:get('wireless', name) then - disabled = uci:get_bool('wireless', name, 'disabled') - end - - return disabled and 1 or 0 -end - -local function configure_client(config, radio, index, suffix) - local name = 'client_' .. radio - local disabled = is_disabled(config, name) - - uci:delete('wireless', name) - - macaddr = util.generate_mac(3*(index-1)) - - if config and macaddr then - uci:section('wireless', 'wifi-iface', name, - { - device = radio, - network = 'client', - mode = 'ap', - ssid = config.ssid, - macaddr = macaddr, - ifname = suffix and 'client' .. suffix, - disabled = disabled, - } - ) - end -end - -local function configure_radio(radio, index, config) - local suffix = radio:match('^radio(%d+)$') - - configure_client(config.ap, radio, index, suffix) -end - -util.iterate_radios(configure_radio) - -uci:save('wireless') diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network new file mode 100755 index 00000000..c79bc3c7 --- /dev/null +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/300-gluon-client-bridge-network @@ -0,0 +1,73 @@ +#!/usr/bin/lua + +local sysconfig = require 'gluon.sysconfig' +local util = require 'gluon.util' + +local uci = require('simple-uci').cursor() + + +local interfaces = uci:get('network', 'client', 'ifname') or {} + +if type(interfaces) == 'string' then + local ifname = interfaces + interfaces = {} + for iface in ifname:gmatch('%S+') do + util.add_to_set(interfaces, iface) + end +end + +if sysconfig.lan_ifname and uci:get_bool('network', 'mesh_lan', 'disabled') then + for lanif in sysconfig.lan_ifname:gmatch('%S+') do + util.add_to_set(interfaces, lanif) + end +end + +util.add_to_set(interfaces, 'local-port') + + +uci:delete('network', 'client') +uci:section('network', 'interface', 'client', { + type = 'bridge', + ifname = interfaces, + proto = 'none', + auto = true, + ipv6 = false, + macaddr = sysconfig.primary_mac, + igmp_snooping = true, + multicast_querier = true, +}) + +uci:save('network') + +-- TODO: remove this line and the next in 2019. Firewall zones have been renamed in 2017. +uci:delete('firewall', 'client') + +uci:section('firewall', 'zone', 'drop', { + name = 'drop', + network = {'client'}, + input = 'DROP', + output = 'DROP', + forward = 'DROP', +}) + +local networks = uci:get_list('firewall', 'local_client', 'network') +util.add_to_set(networks, 'local_node') +uci:set_list('firewall', 'local_client', 'network', networks) + + +local dnsmasq = uci:get_first('dhcp', 'dnsmasq') +uci:set('dhcp', dnsmasq, 'boguspriv', false) +uci:set('dhcp', dnsmasq, 'localise_queries', false) +uci:set('dhcp', dnsmasq, 'rebind_protection', false) + +-- TODO: remove this line and the next two in 2019 the zones were removed in 2017 +uci:delete('dhcp', 'client') +uci:delete('firewall', 'local_node') + +uci:section('dhcp', 'dhcp', 'local_client', { + interface = 'client', + ignore = true, +}) + +uci:save('dhcp') +uci:save('firewall') diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node new file mode 100755 index 00000000..824d8d40 --- /dev/null +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/310-gluon-client-bridge-local-node @@ -0,0 +1,52 @@ +#!/usr/bin/lua + +local client_bridge = require 'gluon.client_bridge' +local site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' + +local uci = require('simple-uci').cursor() + + +local next_node = site.next_node({}) + + +uci:delete('network', 'local_node_dev') +uci:section('network', 'device', 'local_node_dev', { + type = 'veth', + name = 'local-node', + macaddr = client_bridge.next_node_macaddr(), + peer_name = 'local-port', + peer_macaddr = sysconfig.primary_mac, +}) + + +local ip4, ip6 + +if next_node.ip4 then + local plen = site.prefix4():match('/%d+$') + ip4 = next_node.ip4 .. plen +end + +if next_node.ip6 then + ip6 = next_node.ip6 .. '/128' +end + +uci:delete('network', 'local_node') +uci:section('network', 'interface', 'local_node', { + ifname = 'local-node', + proto = 'static', + ipaddr = ip4, + ip6addr = ip6, + ip6deprecated = true, +}) + +uci:save('network') + + +uci:delete('dhcp', 'local_node') +uci:section('dhcp', 'dhcp', 'local_node', { + interface = 'local_node', + ignore = true, +}) + +uci:save('dhcp') diff --git a/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/320-gluon-client-bridge-wireless b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/320-gluon-client-bridge-wireless new file mode 100755 index 00000000..d9ac83f3 --- /dev/null +++ b/package/gluon-client-bridge/luasrc/lib/gluon/upgrade/320-gluon-client-bridge-wireless @@ -0,0 +1,47 @@ +#!/usr/bin/lua + +local util = require 'gluon.util' + +local uci = require('simple-uci').cursor() + + +local function is_disabled(config, name) + if uci:get('wireless', name) then + return uci:get_bool('wireless', name, 'disabled') + end + + return config.disabled(false) +end + +util.foreach_radio(uci, function(radio, index, config) + local radio_name = radio['.name'] + + local name = 'client_' .. radio_name + local suffix = radio_name:match('^radio(%d+)$') + + local ap = config.ap + local disabled = is_disabled(ap, name) + + uci:delete('wireless', name) + + if not ap() then + return + end + + local macaddr = util.get_wlan_mac(uci, radio, index, 1) + if not macaddr then + return + end + + uci:section('wireless', 'wifi-iface', name, { + device = radio_name, + network = 'client', + mode = 'ap', + ssid = ap.ssid(), + macaddr = macaddr, + ifname = suffix and 'client' .. suffix, + disabled = disabled or false, + }) +end) + +uci:save('wireless') diff --git a/package/gluon-client-bridge/luasrc/usr/lib/lua/gluon/client_bridge.lua b/package/gluon-client-bridge/luasrc/usr/lib/lua/gluon/client_bridge.lua new file mode 100644 index 00000000..f3af7504 --- /dev/null +++ b/package/gluon-client-bridge/luasrc/usr/lib/lua/gluon/client_bridge.lua @@ -0,0 +1,8 @@ +local site = require 'gluon.site' + + +module 'gluon.client_bridge' + +function next_node_macaddr() + return site.next_node.mac('16:41:95:40:f7:dc') +end diff --git a/package/gluon-config-mode-autoupdater/Makefile b/package/gluon-config-mode-autoupdater/Makefile index 4303940b..b94d3b45 100644 --- a/package/gluon-config-mode-autoupdater/Makefile +++ b/package/gluon-config-mode-autoupdater/Makefile @@ -3,38 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-autoupdater PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-autoupdater - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Let the user know whether the autoupdater is enabled or not. - DEPENDS:=gluon-config-mode-core-virtual +gluon-autoupdater + TITLE:=Config Mode: Let the user know whether the autoupdater is enabled or not + DEPENDS:=+gluon-config-mode-core +gluon-autoupdater endef -define Package/gluon-config-mode-autoupdater/description - Luci based config mode -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-autoupdater,i18n) -endef - -define Package/gluon-config-mode-autoupdater/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-autoupdater,$(1)) -endef - -$(eval $(call BuildPackage,gluon-config-mode-autoupdater)) +$(eval $(call BuildPackageGluon,gluon-config-mode-autoupdater)) diff --git a/package/gluon-config-mode-autoupdater/files/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua b/package/gluon-config-mode-autoupdater/files/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua deleted file mode 100644 index 3bbe0390..00000000 --- a/package/gluon-config-mode-autoupdater/files/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua +++ /dev/null @@ -1,19 +0,0 @@ -local cbi = require "luci.cbi" -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() - -local M = {} - -function M.section(form) - local enabled = uci:get_bool("autoupdater", "settings", "enabled") - if enabled then - local s = form:section(cbi.SimpleSection, nil, - i18n.translate('This node will automatically update its firmware when a new version is available.')) - end -end - -function M.handle(data) - return -end - -return M diff --git a/package/gluon-config-mode-autoupdater/i18n/de.po b/package/gluon-config-mode-autoupdater/i18n/de.po index 5a55e349..c555b721 100644 --- a/package/gluon-config-mode-autoupdater/i18n/de.po +++ b/package/gluon-config-mode-autoupdater/i18n/de.po @@ -13,5 +13,13 @@ msgstr "" msgid "" "This node will automatically update its firmware when a new version is " "available." -msgstr "Dieser Knoten aktualisiert seine Firmware automatisch, sobald " +msgstr "" +"Dieser Knoten aktualisiert seine Firmware automatisch, sobald " "eine neue Version vorliegt." + +msgid "" +"Automatic updates are disabled. They can be enabled in Advanced " +"settings." +msgstr "" +"Automatische Updates sind deaktiviert. Sie können in den Erweiterten " +"Einstellungen aktiviert werden." diff --git a/package/gluon-config-mode-autoupdater/i18n/fr.po b/package/gluon-config-mode-autoupdater/i18n/fr.po index 7ee64f46..13cf9637 100644 --- a/package/gluon-config-mode-autoupdater/i18n/fr.po +++ b/package/gluon-config-mode-autoupdater/i18n/fr.po @@ -15,3 +15,10 @@ msgid "" "available." msgstr "Ce nœud s'actualisera automatiquement quand une nouvelle " "version sera disponible." + +msgid "" +"Automatic updates are disabled. They can be enabled in Advanced " +"settings." +msgstr "" +"Mises à jour automatiques sont désactivées. Ils peuvent être activés dans " +"Paramètres avancés." diff --git a/package/gluon-config-mode-autoupdater/i18n/gluon-config-mode-autoupdater.pot b/package/gluon-config-mode-autoupdater/i18n/gluon-config-mode-autoupdater.pot index 9e6272cd..aec7cdc5 100644 --- a/package/gluon-config-mode-autoupdater/i18n/gluon-config-mode-autoupdater.pot +++ b/package/gluon-config-mode-autoupdater/i18n/gluon-config-mode-autoupdater.pot @@ -5,3 +5,8 @@ msgid "" "This node will automatically update its firmware when a new version is " "available." msgstr "" + +msgid "" +"Automatic updates are disabled. They can be enabled in Advanced " +"settings." +msgstr "" diff --git a/package/gluon-config-mode-autoupdater/luasrc/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua b/package/gluon-config-mode-autoupdater/luasrc/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua new file mode 100644 index 00000000..856938f1 --- /dev/null +++ b/package/gluon-config-mode-autoupdater/luasrc/lib/gluon/config-mode/wizard/0050-autoupdater-info.lua @@ -0,0 +1,16 @@ +return function(form, uci) + local pkg_i18n = i18n 'gluon-config-mode-autoupdater' + + local enabled = uci:get_bool("autoupdater", "settings", "enabled") + if enabled then + form:section( + Section, nil, + pkg_i18n.translate('This node will automatically update its firmware when a new version is available.') + ) + else + form:section( + Section, nil, + pkg_i18n.translate('Automatic updates are disabled. They can be enabled in Advanced settings.') + ) + end +end diff --git a/package/gluon-config-mode-contact-info/Makefile b/package/gluon-config-mode-contact-info/Makefile index ff9cb57f..ad27ffa2 100644 --- a/package/gluon-config-mode-contact-info/Makefile +++ b/package/gluon-config-mode-contact-info/Makefile @@ -3,34 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-contact-info PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-contact-info - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Set a custom string that will be distributed in the mesh. - DEPENDS:=gluon-config-mode-core-virtual +gluon-node-info + TITLE:=Allows the user to provide contact information to be distributed in the mesh + DEPENDS:=+gluon-config-mode-core +gluon-node-info endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-contact-info,i18n) -endef - -define Package/gluon-config-mode-contact-info/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-contact-info,$(1)) -endef - -$(eval $(call BuildPackage,gluon-config-mode-contact-info)) +$(eval $(call BuildPackageGluon,gluon-config-mode-contact-info)) diff --git a/package/gluon-config-mode-contact-info/check_site.lua b/package/gluon-config-mode-contact-info/check_site.lua new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-config-mode-contact-info/files/lib/gluon/config-mode/wizard/0500-contact-info.lua b/package/gluon-config-mode-contact-info/files/lib/gluon/config-mode/wizard/0500-contact-info.lua deleted file mode 100644 index a2182f95..00000000 --- a/package/gluon-config-mode-contact-info/files/lib/gluon/config-mode/wizard/0500-contact-info.lua +++ /dev/null @@ -1,34 +0,0 @@ -local cbi = require "luci.cbi" -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() - -local M = {} - -function M.section(form) - local s = form:section(cbi.SimpleSection, nil, i18n.translate( - 'You can provide your contact information here to ' - .. 'allow others to contact you. Please note that ' - .. 'this information will be visible publicly ' - .. 'on the internet together with your node\'s coordinates.' - ) - ) - - local o = s:option(cbi.Value, "_contact", i18n.translate("Contact info")) - o.default = uci:get_first("gluon-node-info", "owner", "contact", "") - o.rmempty = true - o.datatype = "string" - o.description = i18n.translate("e.g. E-mail or phone number") - o.maxlen = 140 -end - -function M.handle(data) - if data._contact ~= nil then - uci:set("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact", data._contact) - else - uci:delete("gluon-node-info", uci:get_first("gluon-node-info", "owner"), "contact") - end - uci:save("gluon-node-info") - uci:commit("gluon-node-info") -end - -return M diff --git a/package/gluon-config-mode-contact-info/i18n/de.po b/package/gluon-config-mode-contact-info/i18n/de.po index 719246f4..651fdde4 100644 --- a/package/gluon-config-mode-contact-info/i18n/de.po +++ b/package/gluon-config-mode-contact-info/i18n/de.po @@ -14,14 +14,20 @@ msgid "Contact info" msgstr "Kontakt" msgid "" -"You can provide your contact information here to allow others to contact " -"you. Please note that this information will be visible publicly on " -"the internet together with your node's coordinates." +"Please provide your contact information here to allow others to contact " +"you. Note that this information will be visible publicly on " +"the internet together with your node's coordinates. This means it can " +"be downloaded and processed by anyone. This information is " +"not required to operate a node. If you chose to enter data, it will be " +"stored on this node and can be deleted by yourself at any time." msgstr "" -"Hier kannst du einen öffentlichen Hinweis hinterlegen, um anderen " -"zu ermöglichen, Kontakt mit dir aufzunehmen. Bitte beachte, dass " -"dieser Hinweis auch öffentlich im Internet, zusammen mit den Koordinaten " -"deines Knotens, einsehbar sein wird." +"Bitte hinterlege hier einen Hinweis, um anderen zu ermöglichen, " +"Kontakt mit dir aufzunehmen. Beachte, dass dieser Hinweis auch " +"öffentlich im Internet, zusammen mit den Koordinaten " +"deines Knotens, einsehbar sein wird. Das bedeutet, dass diese Informationen " +"von jedem heruntergeladen und verarbeitet werden können. Für den Betrieb sind diese " +"Informationen nicht erforderlich. Eine Speicherung erfolgt auf diesem Knoten. " +"Die Daten können durch dich in diesem Menü eigenständig gelöscht werden." msgid "e.g. E-mail or phone number" msgstr "z.B. E-Mail oder Telefonnummer" diff --git a/package/gluon-config-mode-contact-info/i18n/fr.po b/package/gluon-config-mode-contact-info/i18n/fr.po index 779e15fe..f20e06cb 100644 --- a/package/gluon-config-mode-contact-info/i18n/fr.po +++ b/package/gluon-config-mode-contact-info/i18n/fr.po @@ -14,12 +14,20 @@ msgid "Contact info" msgstr "Informations de Contact" msgid "" -"You can provide your contact information here to allow others to contact " -"you. Please note that this information will be visible publicly on " -"the internet together with your node's coordinates." +"Please provide your contact information here to allow others to contact " +"you. Note that this information will be visible publicly on " +"the internet together with your node's coordinates. This means it can " +"be downloaded and processed by anyone. This information is " +"not required to operate a node. If you chose to enter data, it will be " +"stored on this node and can be deleted by yourself at any time." msgstr "" -"Ici vous pouvez donner des informations publiques pour permettre aux autres de vous contacter. " -"Ces informations seront affichées en ligne, avec les coordonnées du nœud." +"Entrez vos coordonnées ici si vous souhaitez permettre à d'autres " +"personnes de communiquer avec vous. Ces informations seront affichées " +"en ligne avec les coordonnées du nœud. Il peut être téléchargé " +"et traité par tous. Il n'est pas obligatoire " +"de fournir ces informations pour pouvoir opérer un nœud. Si vous avez " +"choisi d'entrer des données, elles seront stockées sur ce nœud et vous " +"pourrez les effacer par vous-même à tout moment." msgid "e.g. E-mail or phone number" msgstr "Ex : E-mail ou numéro de téléphone" diff --git a/package/gluon-config-mode-contact-info/i18n/gluon-config-mode-contact-info.pot b/package/gluon-config-mode-contact-info/i18n/gluon-config-mode-contact-info.pot index 63939a83..913f38a5 100644 --- a/package/gluon-config-mode-contact-info/i18n/gluon-config-mode-contact-info.pot +++ b/package/gluon-config-mode-contact-info/i18n/gluon-config-mode-contact-info.pot @@ -5,9 +5,12 @@ msgid "Contact info" msgstr "" msgid "" -"You can provide your contact information here to allow others to contact " -"you. Please note that this information will be visible publicly on " -"the internet together with your node's coordinates." +"Please provide your contact information here to allow others to contact " +"you. Note that this information will be visible publicly on " +"the internet together with your node's coordinates. This means it can be " +"downloaded and processed by anyone. This information is " +"not required to operate a node. If you chose to enter data, it will be " +"stored on this node and can be deleted by yourself at any time." msgstr "" msgid "e.g. E-mail or phone number" diff --git a/package/gluon-config-mode-contact-info/luasrc/lib/gluon/config-mode/wizard/0500-contact-info.lua b/package/gluon-config-mode-contact-info/luasrc/lib/gluon/config-mode/wizard/0500-contact-info.lua new file mode 100644 index 00000000..8309d87a --- /dev/null +++ b/package/gluon-config-mode-contact-info/luasrc/lib/gluon/config-mode/wizard/0500-contact-info.lua @@ -0,0 +1,29 @@ +return function(form, uci) + local pkg_i18n = i18n 'gluon-config-mode-contact-info' + local site_i18n = i18n 'gluon-site' + + local site = require 'gluon.site' + + local owner = uci:get_first("gluon-node-info", "owner") + + local help = site_i18n._translate("gluon-config-mode:contact-help") or pkg_i18n.translate( + 'Please provide your contact information here to allow others to contact ' + .. 'you. Note that this information will be visible publicly on ' + .. 'the internet together with your node\'s coordinates. This means it can ' + .. 'be downloaded and processed by anyone. This information is ' + .. 'not required to operate a node. If you chose to enter data, it will be ' + .. 'stored on this node and can be deleted by yourself at any time.' + ) + local s = form:section(Section, nil, help) + + local o = s:option(Value, "contact", pkg_i18n.translate("Contact info"), + site_i18n._translate("gluon-config-mode:contact-note") or pkg_i18n.translate("e.g. E-mail or phone number")) + o.default = uci:get("gluon-node-info", owner, "contact") + o.datatype = 'minlength(1)' + o.optional = true + function o:write(data) + uci:set("gluon-node-info", owner, "contact", data) + end + + return {'gluon-node-info'} +end diff --git a/package/gluon-config-mode-core/Makefile b/package/gluon-config-mode-core/Makefile index 5d700f7f..b9c39487 100644 --- a/package/gluon-config-mode-core/Makefile +++ b/package/gluon-config-mode-core/Makefile @@ -6,35 +6,20 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-core PKG_VERSION:=2 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-core - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci based config mode for user friendly setup of new mesh nodes - DEPENDS:=gluon-setup-mode-virtual +gluon-luci-theme +gluon-lock-password $(GLUON_I18N_PACKAGES) - PROVIDES:=gluon-config-mode-core-virtual -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-core,i18n) + TITLE:=Configuration wizard for user friendly setup of new mesh nodes + DEPENDS:=+gluon-setup-mode +gluon-web-model +gluon-config-mode-theme +uhttpd endef define Package/gluon-config-mode-core/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-core,$(1)) + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/lib/gluon/config-mode/view/ $(1)/lib/gluon/config-mode/www/static/ + $(LN) /lib/gluon/web/i18n $(1)/lib/gluon/config-mode/ + $(LN) /lib/gluon/web/view/{error,model} $(1)/lib/gluon/config-mode/view/ + $(LN) /lib/gluon/web/www/static/gluon-web-model.js $(1)/lib/gluon/config-mode/www/static/ endef -$(eval $(call BuildPackage,gluon-config-mode-core)) +$(eval $(call BuildPackageGluon,gluon-config-mode-core)) diff --git a/package/gluon-config-mode-core/files/lib/gluon/config-mode/reboot/0900-msg-reboot.lua b/package/gluon-config-mode-core/files/lib/gluon/config-mode/reboot/0900-msg-reboot.lua deleted file mode 100644 index bf27c07f..00000000 --- a/package/gluon-config-mode-core/files/lib/gluon/config-mode/reboot/0900-msg-reboot.lua +++ /dev/null @@ -1,3 +0,0 @@ -local i18n = require 'luci.i18n' - -return function () luci.template.render_string(i18n.translate('gluon-config-mode:reboot')) end diff --git a/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/reboot.html b/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/reboot.html new file mode 100644 index 00000000..6c65010b --- /dev/null +++ b/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/reboot.html @@ -0,0 +1,22 @@ +

<%:Your node's setup is now complete.%>

+<% + local fs = require "nixio.fs" + local util = require "nixio.util" + + local parts_dir = "/lib/gluon/config-mode/reboot/" + local files = util.consume(fs.dir(parts_dir) or function() end) + table.sort(files) + + local parts = {} + for _, entry in ipairs(files) do + if entry:sub(1, 1) ~= '.' then + local p = assert(loadfile(parts_dir .. entry)) + setfenv(p, getfenv()) + table.insert(parts, p) + end + end + + for _, p in ipairs(parts) do + p() + end +%> diff --git a/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/welcome.html b/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/welcome.html new file mode 100644 index 00000000..00beaa04 --- /dev/null +++ b/package/gluon-config-mode-core/files/lib/gluon/config-mode/view/wizard/welcome.html @@ -0,0 +1,16 @@ +<%- + local site_i18n = i18n 'gluon-site' + + local sysconfig = require 'gluon.sysconfig' + + local msg = site_i18n._translate('gluon-config-mode:welcome') + if not msg then return end +-%> +

+ <% + renderer.render_string(msg, { + hostname = hostname, + sysconfig = sysconfig, + }) + %> +

diff --git a/package/gluon-config-mode-core/files/lib/gluon/config-mode/www/index.html b/package/gluon-config-mode-core/files/lib/gluon/config-mode/www/index.html new file mode 100644 index 00000000..bda93144 --- /dev/null +++ b/package/gluon-config-mode-core/files/lib/gluon/config-mode/www/index.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50uhttpd b/package/gluon-config-mode-core/files/lib/gluon/setup-mode/rc.d/S50uhttpd similarity index 61% rename from package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50uhttpd rename to package/gluon-config-mode-core/files/lib/gluon/setup-mode/rc.d/S50uhttpd index 53118704..efd1d612 100755 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50uhttpd +++ b/package/gluon-config-mode-core/files/lib/gluon/setup-mode/rc.d/S50uhttpd @@ -9,6 +9,6 @@ UHTTPD_BIN="/usr/sbin/uhttpd" start_service() { procd_open_instance procd_set_param respawn - procd_set_param command "$UHTTPD_BIN" -f -h /lib/gluon/setup-mode/www -x /cgi-bin -A 1 -R -p 0.0.0.0:80 + procd_set_param command "$UHTTPD_BIN" -f -h /lib/gluon/config-mode/www -x /cgi-bin -A 1 -R -p 0.0.0.0:80 procd_close_instance } diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua b/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua deleted file mode 100644 index 68c14746..00000000 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/controller/gluon-config-mode/index.lua +++ /dev/null @@ -1,89 +0,0 @@ ---[[ -Copyright 2013 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -module("luci.controller.gluon-config-mode.index", package.seeall) - -function index() - local uci_state = luci.model.uci.cursor_state() - - if uci_state:get_first("gluon-setup-mode", "setup_mode", "running", "0") == "1" then - local root = node() - if not root.target then - root.target = alias("gluon-config-mode") - root.index = true - end - - page = node() - page.lock = true - page.target = alias("gluon-config-mode") - page.subindex = true - page.index = false - - page = node("gluon-config-mode") - page.title = _("Wizard") - page.target = alias("gluon-config-mode", "wizard") - page.order = 5 - page.setuser = "root" - page.setgroup = "root" - page.index = true - - entry({"gluon-config-mode", "wizard"}, form("gluon-config-mode/wizard")).index = true - entry({"gluon-config-mode", "reboot"}, call("action_reboot")) - end -end - -function action_reboot() - local uci = luci.model.uci.cursor() - - uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", "1") - uci:save("gluon-setup-mode") - uci:commit("gluon-setup-mode") - - local fs = require "nixio.fs" - local util = require "nixio.util" - - local parts_dir = "/lib/gluon/config-mode/reboot/" - local files = util.consume(fs.dir(parts_dir)) - - table.sort(files) - - local parts = {} - - for _, entry in ipairs(files) do - if entry:sub(1, 1) ~= '.' then - local f = dofile(parts_dir .. '/' .. entry) - if f ~= nil then - table.insert(parts, f) - end - end - end - - local hostname = uci:get_first("system", "system", "hostname") - - luci.template.render("gluon/config-mode/reboot", - { - parts = parts, - hostname = hostname, - } - ) - - if nixio.fork() == 0 then - -- Replace stdout with /dev/null - nixio.dup(nixio.open('/dev/null', 'w'), nixio.stdout) - - -- Sleep a little so the browser can fetch everything required to - -- display the reboot page, then reboot the device. - nixio.nanosleep(1) - - nixio.execp("reboot") - end -end diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua b/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua deleted file mode 100644 index 569dd60e..00000000 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/model/cbi/gluon-config-mode/wizard.lua +++ /dev/null @@ -1,42 +0,0 @@ -local wizard_dir = "/lib/gluon/config-mode/wizard/" -local i18n = luci.i18n -local uci = luci.model.uci.cursor() -local fs = require "nixio.fs" -local util = require "nixio.util" -local f, s - -local wizard = {} -local files = {} - -if fs.access(wizard_dir) then - files = util.consume(fs.dir(wizard_dir)) - table.sort(files) -end - -for _, entry in ipairs(files) do - if entry:sub(1, 1) ~= '.' then - table.insert(wizard, dofile(wizard_dir .. '/' .. entry)) - end -end - -f = SimpleForm("wizard") -f.reset = false -f.template = "gluon/cbi/config-mode" - -for _, s in ipairs(wizard) do - s.section(f) -end - -function f.handle(self, state, data) - if state == FORM_VALID then - for _, s in ipairs(wizard) do - s.handle(data) - end - - luci.http.redirect(luci.dispatcher.build_url("gluon-config-mode", "reboot")) - end - - return true -end - -return f diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/cbi/config-mode.htm b/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/cbi/config-mode.htm deleted file mode 100644 index d2210eca..00000000 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/cbi/config-mode.htm +++ /dev/null @@ -1,46 +0,0 @@ -<%- - local sysconfig = require 'gluon.sysconfig' - local i18n = require 'luci.i18n' - local template = require 'luci.template' --%> - -

<%:Welcome!%>

-

- <%= template.render_string(i18n.translate('gluon-config-mode:welcome'), {hostname=hostname, sysconfig=sysconfig}) %> -

- -<% if not self.embedded then %> - -
- - -
-<% end %> -
- <% if self.title and #self.title > 0 then %>

<%=self.title%>

<% end %> - <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> - <% self:render_children() %> -
-
-<%- if self.message then %> -
<%=self.message%>
-<%- end %> -<%- if self.errmessage then %> -
<%=self.errmessage%>
-<%- end %> -<% if not self.embedded then %> -
-<%- - if type(self.hidden) == "table" then - for k, v in pairs(self.hidden) do --%> - -<%- - end - end -%> - - -
- -<% end %> diff --git a/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/config-mode/reboot.htm b/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/config-mode/reboot.htm deleted file mode 100644 index e8f32d99..00000000 --- a/package/gluon-config-mode-core/files/usr/lib/lua/luci/view/gluon/config-mode/reboot.htm +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - <%=hostname%> is rebooting - - - -
-
-

<%:Your node's setup is now complete.%>

- <% for k, v in ipairs(parts) do v() end %> -
-
- - diff --git a/package/gluon-config-mode-core/i18n/de.po b/package/gluon-config-mode-core/i18n/de.po index 58d23894..dd335a47 100644 --- a/package/gluon-config-mode-core/i18n/de.po +++ b/package/gluon-config-mode-core/i18n/de.po @@ -10,7 +10,6 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#, fuzzy msgid "Save & restart" msgstr "Speichern & Neustarten" diff --git a/package/gluon-config-mode-core/i18n/fr.po b/package/gluon-config-mode-core/i18n/fr.po index f4f988cc..4988e251 100644 --- a/package/gluon-config-mode-core/i18n/fr.po +++ b/package/gluon-config-mode-core/i18n/fr.po @@ -9,7 +9,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#, fuzzy + msgid "Save & restart" msgstr "Enregistrer & Redémarer" diff --git a/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/controller/gluon-config-mode/index.lua b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/controller/gluon-config-mode/index.lua new file mode 100644 index 00000000..8801948a --- /dev/null +++ b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/controller/gluon-config-mode/index.lua @@ -0,0 +1,4 @@ +package 'gluon-config-mode-core' + +entry({}, alias("wizard")) +entry({"wizard"}, model("gluon-config-mode/wizard"), _("Wizard"), 5) diff --git a/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/model/gluon-config-mode/wizard.lua b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/model/gluon-config-mode/wizard.lua new file mode 100644 index 00000000..ca400a9e --- /dev/null +++ b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/model/gluon-config-mode/wizard.lua @@ -0,0 +1,75 @@ +local fs = require "nixio.fs" +local util = require "gluon.util" +local nixio_util = require "nixio.util" + +local uci = require("simple-uci").cursor() + +local wizard_dir = "/lib/gluon/config-mode/wizard/" + +local files = nixio_util.consume(fs.dir(wizard_dir) or function() end) +table.sort(files) + +local wizard = {} +for _, entry in ipairs(files) do + if entry:sub(1, 1) ~= '.' then + local f = assert(loadfile(wizard_dir .. entry)) + setfenv(f, getfenv()) + local w = f() + table.insert(wizard, w) + end +end + +local f = Form(translate("Welcome!")) +f.submit = translate('Save & restart') +f.reset = false + +local s = f:section(Section) +s.template = "wizard/welcome" +s.package = "gluon-config-mode-core" + +local commit = {'gluon-setup-mode'} +local run = {} + +for _, w in ipairs(wizard) do + for _, c in ipairs(w(f, uci) or {}) do + if type(c) == 'string' then + if not util.contains(commit, c) then + table.insert(commit, c) + end + elseif type(c) == 'function' then + table.insert(run, c) + else + error('invalid wizard module return') + end + end +end + +function f:write() + local nixio = require "nixio" + + uci:set("gluon-setup-mode", uci:get_first("gluon-setup-mode", "setup_mode"), "configured", true) + + for _, c in ipairs(commit) do + uci:commit(c) + end + for _, r in ipairs(run) do + r() + end + + f.template = "wizard/reboot" + f.package = "gluon-config-mode-core" + f.hidenav = true + + if nixio.fork() == 0 then + -- Replace stdout with /dev/null + nixio.dup(nixio.open('/dev/null', 'w'), nixio.stdout) + + -- Sleep a little so the browser can fetch everything required to + -- display the reboot page, then reboot the device. + nixio.nanosleep(1) + + nixio.execp("reboot") + end +end + +return f diff --git a/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/reboot/0900-msg-reboot.lua b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/reboot/0900-msg-reboot.lua new file mode 100644 index 00000000..d73a9e0b --- /dev/null +++ b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/reboot/0900-msg-reboot.lua @@ -0,0 +1,20 @@ +local site_i18n = i18n 'gluon-site' + +local site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' +local pretty_hostname = require 'pretty_hostname' + +local uci = require("simple-uci").cursor() + +local hostname = pretty_hostname.get(uci) +local contact = uci:get_first('gluon-node-info', 'owner', 'contact') + +local msg = site_i18n._translate('gluon-config-mode:reboot') +if not msg then return end + +renderer.render_string(msg, { + hostname = hostname, + site = site, + sysconfig = sysconfig, + contact = contact, +}) diff --git a/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/www/cgi-bin/config b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/www/cgi-bin/config new file mode 100755 index 00000000..7f7ead23 --- /dev/null +++ b/package/gluon-config-mode-core/luasrc/lib/gluon/config-mode/www/cgi-bin/config @@ -0,0 +1,8 @@ +#!/usr/bin/lua + +require 'gluon.web.cgi' { + base_path = '/lib/gluon/config-mode', + + layout_package = 'gluon-config-mode-theme', + layout_template = 'theme/layout', +} diff --git a/package/gluon-config-mode-domain-select/Makefile b/package/gluon-config-mode-domain-select/Makefile new file mode 100644 index 00000000..b1ded939 --- /dev/null +++ b/package/gluon-config-mode-domain-select/Makefile @@ -0,0 +1,13 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-config-mode-domain-select +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-config-mode-domain-select + TITLE:=UI for changing the node-config + DEPENDS:=+gluon-config-mode-core @GLUON_MULTIDOMAIN +endef + +$(eval $(call BuildPackageGluon,gluon-config-mode-domain-select)) diff --git a/package/gluon-config-mode-domain-select/check_site.lua b/package/gluon-config-mode-domain-select/check_site.lua new file mode 100644 index 00000000..6a6fd47b --- /dev/null +++ b/package/gluon-config-mode-domain-select/check_site.lua @@ -0,0 +1,7 @@ +local valid_domain_codes = table_keys(need_table(in_domain({'domain_names'}))) + +alternatives(function() + need_boolean(in_domain({'hide_domain'}), false) +end, function() + need_array_of(in_domain({'hide_domain'}), valid_domain_codes, false) +end) diff --git a/package/gluon-config-mode-domain-select/luasrc/lib/gluon/config-mode/wizard/0200-domain-select.lua b/package/gluon-config-mode-domain-select/luasrc/lib/gluon/config-mode/wizard/0200-domain-select.lua new file mode 100644 index 00000000..9496e99f --- /dev/null +++ b/package/gluon-config-mode-domain-select/luasrc/lib/gluon/config-mode/wizard/0200-domain-select.lua @@ -0,0 +1,68 @@ + +return function(form, uci) + local site_i18n = i18n 'gluon-site' + + local fs = require 'nixio.fs' + local json = require 'jsonc' + local site = require 'gluon.site' + local util = require 'gluon.util' + + local selected_domain = uci:get('gluon', 'core', 'domain') + local configured = uci:get_first('gluon-setup-mode','setup_mode', 'configured') == '1' or (selected_domain ~= site.default_domain()) + + local function hide_domain_code(domain, code) + if configured and code == selected_domain then + return false + elseif type(domain.hide_domain) == 'table' then + return util.contains(domain.hide_domain, code) + else + return domain.hide_domain + end + end + + local function get_domain_list() + local list = {} + for domain_path in fs.glob('/lib/gluon/domains/*.json') do + local domain_code = domain_path:match('([^/]+)%.json$') + local domain = assert(json.load(domain_path)) + + if not hide_domain_code(domain, domain_code) then + table.insert(list, { + domain_code = domain_code, + domain_name = domain.domain_names[domain_code], + }) + end + end + + table.sort(list, function(a, b) return a.domain_name < b.domain_name end) + return list + end + + local s = form:section(Section, nil, site_i18n.translate('gluon-config-mode:domain-select')) + local o = s:option(ListValue, 'domain', site_i18n.translate('gluon-config-mode:domain')) + + if configured then + o.default = selected_domain + end + + for _, domain in ipairs(get_domain_list()) do + o:value(domain.domain_code, domain.domain_name) + end + + local domain_changed = false + + function o:write(data) + if data ~= selected_domain then + domain_changed = true + uci:set('gluon', 'core', 'domain', data) + end + end + + local function reconfigure() + if domain_changed then + os.execute('gluon-reconfigure') + end + end + + return {'gluon', reconfigure} +end diff --git a/package/gluon-config-mode-geo-location/Makefile b/package/gluon-config-mode-geo-location/Makefile index 03812e54..a020feb9 100644 --- a/package/gluon-config-mode-geo-location/Makefile +++ b/package/gluon-config-mode-geo-location/Makefile @@ -3,39 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-geo-location PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-geo-location - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Set geographic location of a node - DEPENDS:=gluon-config-mode-core-virtual +gluon-node-info + DEPENDS:=+gluon-config-mode-core +gluon-node-info endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-geo-location,i18n) -endef - -define Package/gluon-config-mode-geo-location/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-geo-location,$(1)) -endef - -define Package/gluon-config-mode-geo-location/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-config-mode-geo-location)) +$(eval $(call BuildPackageGluon,gluon-config-mode-geo-location)) diff --git a/package/gluon-config-mode-geo-location/check_site.lua b/package/gluon-config-mode-geo-location/check_site.lua index 509226fe..9d7c26cb 100644 --- a/package/gluon-config-mode-geo-location/check_site.lua +++ b/package/gluon-config-mode-geo-location/check_site.lua @@ -1,3 +1 @@ -if need_table('config_mode', nil, false) and need_table('config_mode.geo_location', nil, false) then - need_boolean('config_mode.geo_location.show_altitude', false) -end +need_boolean(in_site({'config_mode', 'geo_location', 'show_altitude'}), false) diff --git a/package/gluon-config-mode-geo-location/files/lib/gluon/config-mode/wizard/0400-geo-location.lua b/package/gluon-config-mode-geo-location/files/lib/gluon/config-mode/wizard/0400-geo-location.lua deleted file mode 100644 index 9bc70301..00000000 --- a/package/gluon-config-mode-geo-location/files/lib/gluon/config-mode/wizard/0400-geo-location.lua +++ /dev/null @@ -1,76 +0,0 @@ -local cbi = require "luci.cbi" -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() -local site = require 'gluon.site_config' - -local M = {} - -local function show_altitude() - if ((site.config_mode or {}).geo_location or {}).show_altitude ~= false then - return true - end - if uci:get_first("gluon-node-info", "location", "altitude") then - return true - end - return false -end - -function M.section(form) - local text = i18n.translate('If you want the location of your node to ' - .. 'be displayed on the map, you can enter its coordinates here.') - if show_altitude() then - text = text .. ' ' .. i18n.translate('Specifying the altitude is ' - .. 'optional and should only be done if a proper value is known.') - end - local s = form:section(cbi.SimpleSection, nil, text) - - - local o - - o = s:option(cbi.Flag, "_location", i18n.translate("Show node on the map")) - o.default = uci:get_first("gluon-node-info", "location", "share_location", o.disabled) - o.rmempty = false - - o = s:option(cbi.Value, "_latitude", i18n.translate("Latitude")) - o.default = uci:get_first("gluon-node-info", "location", "latitude") - o:depends("_location", "1") - o.rmempty = false - o.datatype = "float" - o.description = i18n.translatef("e.g. %s", "53.873621") - - o = s:option(cbi.Value, "_longitude", i18n.translate("Longitude")) - o.default = uci:get_first("gluon-node-info", "location", "longitude") - o:depends("_location", "1") - o.rmempty = false - o.datatype = "float" - o.description = i18n.translatef("e.g. %s", "10.689901") - - if show_altitude() then - o = s:option(cbi.Value, "_altitude", i18n.translate("Altitude")) - o.default = uci:get_first("gluon-node-info", "location", "altitude") - o:depends("_location", "1") - o.rmempty = true - o.datatype = "float" - o.description = i18n.translatef("e.g. %s", "11.51") - end - -end - -function M.handle(data) - local sname = uci:get_first("gluon-node-info", "location") - - uci:set("gluon-node-info", sname, "share_location", data._location) - if data._location and data._latitude ~= nil and data._longitude ~= nil then - uci:set("gluon-node-info", sname, "latitude", data._latitude:trim()) - uci:set("gluon-node-info", sname, "longitude", data._longitude:trim()) - if data._altitude ~= nil then - uci:set("gluon-node-info", sname, "altitude", data._altitude:trim()) - else - uci:delete("gluon-node-info", sname, "altitude") - end - end - uci:save("gluon-node-info") - uci:commit("gluon-node-info") -end - -return M diff --git a/package/gluon-config-mode-geo-location/i18n/de.po b/package/gluon-config-mode-geo-location/i18n/de.po index 3580732b..c8bc906a 100644 --- a/package/gluon-config-mode-geo-location/i18n/de.po +++ b/package/gluon-config-mode-geo-location/i18n/de.po @@ -17,22 +17,12 @@ msgstr "" "Um deinen Knoten auf der Karte anzeigen zu können, benötigen wir seine " "Koordinaten. Hier hast du die Möglichkeit, diese zu hinterlegen." -msgid "" -"Specifying the altitude is optional and should only be done if a proper " -"value is known." -msgstr "" -"Die Höhenangabe ist optional und sollte nur gesetzt werden, wenn ein " -"exakter Wert bekannt ist." - msgid "Latitude" msgstr "Breitengrad" msgid "Longitude" msgstr "Längengrad" -msgid "Altitude" -msgstr "Höhe" - msgid "Show node on the map" msgstr "Knoten auf der Karte anzeigen" diff --git a/package/gluon-config-mode-geo-location/i18n/fr.po b/package/gluon-config-mode-geo-location/i18n/fr.po index b239c84c..d3d7c6e8 100644 --- a/package/gluon-config-mode-geo-location/i18n/fr.po +++ b/package/gluon-config-mode-geo-location/i18n/fr.po @@ -17,22 +17,12 @@ msgstr "" "Pour Afficher votre nœud sur la Carte nous avons besoin de ses coordonnées. " "Ici vous pouvez entrer sa position." -msgid "" -"Specifying the altitude is optional and should only be done if a proper " -"value is known." -msgstr "" -"La altitude est optionelle et ne devrait que être ajoutée si la valeur " -"exacte est connue." - msgid "Latitude" msgstr "Latitude" msgid "Longitude" msgstr "Longitude" -msgid "Altitude" -msgstr "Hauteur" - msgid "Show node on the map" msgstr "Afficher le nœud sur la carte" diff --git a/package/gluon-config-mode-geo-location/i18n/gluon-config-mode-geo-location.pot b/package/gluon-config-mode-geo-location/i18n/gluon-config-mode-geo-location.pot index 48f26f70..7acf7f28 100644 --- a/package/gluon-config-mode-geo-location/i18n/gluon-config-mode-geo-location.pot +++ b/package/gluon-config-mode-geo-location/i18n/gluon-config-mode-geo-location.pot @@ -6,20 +6,12 @@ msgid "" "enter its coordinates here." msgstr "" -msgid "" -"Specifying the altitude is optional and should only be done if a proper " -"value is known." -msgstr "" - msgid "Latitude" msgstr "" msgid "Longitude" msgstr "" -msgid "Altitude" -msgstr "" - msgid "Show node on the map" msgstr "" diff --git a/package/gluon-config-mode-geo-location/luasrc/lib/gluon/config-mode/wizard/0400-geo-location.lua b/package/gluon-config-mode-geo-location/luasrc/lib/gluon/config-mode/wizard/0400-geo-location.lua new file mode 100644 index 00000000..718e59ee --- /dev/null +++ b/package/gluon-config-mode-geo-location/luasrc/lib/gluon/config-mode/wizard/0400-geo-location.lua @@ -0,0 +1,63 @@ +return function(form, uci) + local pkg_i18n = i18n 'gluon-config-mode-geo-location' + local site_i18n = i18n 'gluon-site' + + local site = require 'gluon.site' + + local location = uci:get_first("gluon-node-info", "location") + + local function show_altitude() + if site.config_mode.geo_location.show_altitude(true) then + return true + end + + return uci:get_bool("gluon-node-info", location, "altitude") + end + + local text = site_i18n._translate("gluon-config-mode:geo-location-help") or pkg_i18n.translate( + 'If you want the location of your node to ' .. + 'be displayed on the map, you can enter its coordinates here.' + ) + if show_altitude() then + text = text .. ' ' .. site_i18n.translate("gluon-config-mode:altitude-help") + end + + local s = form:section(Section, nil, text) + + local o + + local share_location = s:option(Flag, "location", pkg_i18n.translate("Show node on the map")) + share_location.default = uci:get_bool("gluon-node-info", location, "share_location") + function share_location:write(data) + uci:set("gluon-node-info", location, "share_location", data) + end + + o = s:option(Value, "latitude", pkg_i18n.translate("Latitude"), pkg_i18n.translatef("e.g. %s", "53.873621")) + o.default = uci:get("gluon-node-info", location, "latitude") + o:depends(share_location, true) + o.datatype = "float" + function o:write(data) + uci:set("gluon-node-info", location, "latitude", data) + end + + o = s:option(Value, "longitude", pkg_i18n.translate("Longitude"), pkg_i18n.translatef("e.g. %s", "10.689901")) + o.default = uci:get("gluon-node-info", location, "longitude") + o:depends(share_location, true) + o.datatype = "float" + function o:write(data) + uci:set("gluon-node-info", location, "longitude", data) + end + + if show_altitude() then + o = s:option(Value, "altitude", site_i18n.translate("gluon-config-mode:altitude-label"), pkg_i18n.translatef("e.g. %s", "11.51")) + o.default = uci:get("gluon-node-info", location, "altitude") + o:depends(share_location, true) + o.datatype = "float" + o.optional = true + function o:write(data) + uci:set("gluon-node-info", location, "altitude", data) + end + end + + return {'gluon-node-info'} +end diff --git a/package/gluon-config-mode-hostname/Makefile b/package/gluon-config-mode-hostname/Makefile index 803f018f..fdf3acd9 100644 --- a/package/gluon-config-mode-hostname/Makefile +++ b/package/gluon-config-mode-hostname/Makefile @@ -3,34 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-hostname PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-hostname - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Set the hostname - DEPENDS:=gluon-config-mode-core-virtual + DEPENDS:=+gluon-config-mode-core endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-hostname,i18n) -endef - -define Package/gluon-config-mode-hostname/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-hostname,$(1)) -endef - -$(eval $(call BuildPackage,gluon-config-mode-hostname)) +$(eval $(call BuildPackageGluon,gluon-config-mode-hostname)) diff --git a/package/gluon-config-mode-hostname/check_site.lua b/package/gluon-config-mode-hostname/check_site.lua new file mode 100644 index 00000000..29b5edd6 --- /dev/null +++ b/package/gluon-config-mode-hostname/check_site.lua @@ -0,0 +1 @@ +need_boolean(in_site({'config_mode', 'hostname', 'optional'}), false) diff --git a/package/gluon-config-mode-hostname/files/lib/gluon/config-mode/wizard/0100-hostname.lua b/package/gluon-config-mode-hostname/files/lib/gluon/config-mode/wizard/0100-hostname.lua deleted file mode 100644 index cf8bbf89..00000000 --- a/package/gluon-config-mode-hostname/files/lib/gluon/config-mode/wizard/0100-hostname.lua +++ /dev/null @@ -1,21 +0,0 @@ -local cbi = require "luci.cbi" -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() - -local M = {} - -function M.section(form) - local s = form:section(cbi.SimpleSection, nil, nil) - local o = s:option(cbi.Value, "_hostname", i18n.translate("Node name")) - o.value = uci:get_first("system", "system", "hostname") - o.rmempty = false - o.datatype = "hostname" -end - -function M.handle(data) - uci:set("system", uci:get_first("system", "system"), "hostname", data._hostname) - uci:save("system") - uci:commit("system") -end - -return M diff --git a/package/gluon-config-mode-hostname/i18n/de.po b/package/gluon-config-mode-hostname/i18n/de.po index f1d2a765..fa5a6e0f 100644 --- a/package/gluon-config-mode-hostname/i18n/de.po +++ b/package/gluon-config-mode-hostname/i18n/de.po @@ -1,14 +1,22 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-03-19 00:54+0100\n" "Last-Translator: Matthias Schiffer \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Node name" msgstr "Name dieses Knotens" + +msgid "" +"The node name is used solely for identification of your node, e.g. on a node " +"map. It does not affect the name (SSID) of the broadcasted WLAN." +msgstr "" +"Der Knotenname dient ausschließlich zur Identifikation deines Knotens, z.B. " +"auf einer Knotenkarte. Er hat keinen Einfluss auf den Namen (SSID) des " +"ausgestrahlten WLANs." diff --git a/package/gluon-config-mode-hostname/i18n/fr.po b/package/gluon-config-mode-hostname/i18n/fr.po index 79702c06..133992d9 100644 --- a/package/gluon-config-mode-hostname/i18n/fr.po +++ b/package/gluon-config-mode-hostname/i18n/fr.po @@ -1,14 +1,22 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-08-12 23:30+0100\n" "Last-Translator:Tobias Bernot \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Node name" msgstr "Nom du nœud" + +msgid "" +"The node name is used solely for identification of your node, e.g. on a node " +"map. It does not affect the name (SSID) of the broadcasted WLAN." +msgstr "" +"Le nom du nœud est utilisé uniquement pour l'identification de votre nœud, " +"par ex. sur un carte des nœuds. Il n'a aucune influence sur le nom du Wi-" +"Fi(SSID) rayonné." diff --git a/package/gluon-config-mode-hostname/i18n/gluon-config-mode-hostname.pot b/package/gluon-config-mode-hostname/i18n/gluon-config-mode-hostname.pot index dbaafc0b..eabf0a28 100644 --- a/package/gluon-config-mode-hostname/i18n/gluon-config-mode-hostname.pot +++ b/package/gluon-config-mode-hostname/i18n/gluon-config-mode-hostname.pot @@ -3,3 +3,8 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "Node name" msgstr "" + +msgid "" +"The node name is used solely for identification of your node, e.g. on a node " +"map. It does not affect the name (SSID) of the broadcasted WLAN." +msgstr "" diff --git a/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua b/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua new file mode 100644 index 00000000..d078b4de --- /dev/null +++ b/package/gluon-config-mode-hostname/luasrc/lib/gluon/config-mode/wizard/0100-hostname.lua @@ -0,0 +1,35 @@ +return function(form, uci) + local pkg_i18n = i18n 'gluon-config-mode-hostname' + local site_i18n = i18n 'gluon-site' + + local pretty_hostname = require 'pretty_hostname' + local site = require 'gluon.site' + local util = require 'gluon.util' + + local help = site_i18n._translate("gluon-config-mode:hostname-help") or pkg_i18n.translate( + 'The node name is used solely for identification of your node, e.g. on a ' + .. 'node map. It does not affect the name (SSID) of the broadcasted WLAN.' + ) + form:section(Section, nil, help) + + local current_hostname = pretty_hostname.get(uci) + local default_hostname = util.default_hostname() + local configured = uci:get_first('gluon-setup-mode', 'setup_mode', 'configured', false) or (current_hostname ~= default_hostname) + + local s = form:section(Section) + local o = s:option(Value, "hostname", pkg_i18n.translate("Node name")) + o.datatype = 'minlength(1)' + if site.config_mode.hostname.optional(true) then + o.optional = true + o.placeholder = default_hostname + end + if configured then + o.default = current_hostname + end + + function o:write(data) + pretty_hostname.set(uci, data or default_hostname) + end + + return {'system'} +end diff --git a/package/gluon-config-mode-mesh-vpn/Makefile b/package/gluon-config-mode-mesh-vpn/Makefile index 35d53ea7..0c3a752d 100644 --- a/package/gluon-config-mode-mesh-vpn/Makefile +++ b/package/gluon-config-mode-mesh-vpn/Makefile @@ -3,34 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-mesh-vpn PKG_VERSION:=2 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - +include ../gluon.mk define Package/gluon-config-mode-mesh-vpn - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Toggle mesh-vpn and bandwidth limit - DEPENDS:=gluon-config-mode-core-virtual +gluon-mesh-vpn-fastd + DEPENDS:=+gluon-config-mode-core +gluon-mesh-vpn-core endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-config-mode-mesh-vpn,i18n) -endef - -define Package/gluon-config-mode-mesh-vpn/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-config-mode-mesh-vpn,$(1)) -endef - -$(eval $(call BuildPackage,gluon-config-mode-mesh-vpn)) +$(eval $(call BuildPackageGluon,gluon-config-mode-mesh-vpn)) diff --git a/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua deleted file mode 100644 index c6e06975..00000000 --- a/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua +++ /dev/null @@ -1,26 +0,0 @@ -local uci = luci.model.uci.cursor() -local meshvpn_enabled = uci:get("fastd", "mesh_vpn", "enabled", "0") - -if meshvpn_enabled ~= "1" then - return nil -else - local i18n = require "luci.i18n" - local util = require "luci.util" - local site = require 'gluon.site_config' - local sysconfig = require 'gluon.sysconfig' - - local pubkey = util.trim(util.exec("/etc/init.d/fastd show_key " .. "mesh_vpn")) - local hostname = uci:get_first("system", "system", "hostname") - local contact = uci:get_first("gluon-node-info", "owner", "contact") - - local msg = i18n.translate('gluon-config-mode:pubkey') - - return function () - luci.template.render_string(msg, { pubkey=pubkey - , hostname=hostname - , site=site - , sysconfig=sysconfig - , contact=contact - }) - end -end diff --git a/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua deleted file mode 100644 index f0172421..00000000 --- a/package/gluon-config-mode-mesh-vpn/files/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua +++ /dev/null @@ -1,64 +0,0 @@ -local cbi = require "luci.cbi" -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() - -local M = {} - -function M.section(form) - local msg = i18n.translate('Your internet connection can be used to establish an ' .. - 'encrypted connection with other nodes. ' .. - 'Enable this option if there are no other nodes reachable ' .. - 'over WLAN in your vicinity or you want to make a part of ' .. - 'your connection\'s bandwidth available for the network. You can limit how ' .. - 'much bandwidth the node will use at most.') - local s = form:section(cbi.SimpleSection, nil, msg) - - local o - - o = s:option(cbi.Flag, "_meshvpn", i18n.translate("Use internet connection (mesh VPN)")) - o.default = uci:get_bool("fastd", "mesh_vpn", "enabled") and o.enabled or o.disabled - o.rmempty = false - - o = s:option(cbi.Flag, "_limit_enabled", i18n.translate("Limit bandwidth")) - o:depends("_meshvpn", "1") - o.default = uci:get_bool("simple-tc", "mesh_vpn", "enabled") and o.enabled or o.disabled - o.rmempty = false - - o = s:option(cbi.Value, "_limit_ingress", i18n.translate("Downstream (kbit/s)")) - o:depends("_limit_enabled", "1") - o.value = uci:get("simple-tc", "mesh_vpn", "limit_ingress") - o.rmempty = false - o.datatype = "uinteger" - - o = s:option(cbi.Value, "_limit_egress", i18n.translate("Upstream (kbit/s)")) - o:depends("_limit_enabled", "1") - o.value = uci:get("simple-tc", "mesh_vpn", "limit_egress") - o.rmempty = false - o.datatype = "uinteger" -end - -function M.handle(data) - uci:set("fastd", "mesh_vpn", "enabled", data._meshvpn) - uci:save("fastd") - uci:commit("fastd") - - -- checks for nil needed due to o:depends(...) - if data._limit_enabled ~= nil then - uci:set("simple-tc", "mesh_vpn", "interface") - uci:set("simple-tc", "mesh_vpn", "enabled", data._limit_enabled) - uci:set("simple-tc", "mesh_vpn", "ifname", "mesh-vpn") - - if data._limit_ingress ~= nil then - uci:set("simple-tc", "mesh_vpn", "limit_ingress", data._limit_ingress:trim()) - end - - if data._limit_egress ~= nil then - uci:set("simple-tc", "mesh_vpn", "limit_egress", data._limit_egress:trim()) - end - - uci:save("simple-tc") - uci:commit("simple-tc") - end -end - -return M diff --git a/package/gluon-config-mode-mesh-vpn/i18n/de.po b/package/gluon-config-mode-mesh-vpn/i18n/de.po index 8c613aa0..c2e6b35c 100644 --- a/package/gluon-config-mode-mesh-vpn/i18n/de.po +++ b/package/gluon-config-mode-mesh-vpn/i18n/de.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2015-03-19 22:05+0100\n" -"Last-Translator: Matthias Schiffer \n" +"PO-Revision-Date: 2015-10-07 00:32+0100\n" +"Last-Translator: Cyrus Fox \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" @@ -23,14 +23,14 @@ msgid "Use internet connection (mesh VPN)" msgstr "Internetverbindung nutzen (Mesh-VPN)" msgid "" -"Your internet connection can be used to establish an encrypted connection " +"Your internet connection can be used to establish a VPN connection " "with other nodes. Enable this option if there are no other nodes reachable " "over WLAN in your vicinity or you want to make a part of your connection's " "bandwidth available for the network. You can limit how much bandwidth the " "node will use at most." msgstr "" -"Dein Knoten kann deine Internetverbindung nutzen um darüber eine " -"verschlüsselte Verbindung zu anderen Knoten aufzubauen. Die dafür " +"Dein Knoten kann deine Internetverbindung nutzen, um darüber eine " +"VPN-Verbindung zu anderen Knoten aufzubauen. Die dafür " "genutzte Bandbreite kannst du beschränken. Aktiviere die Option, falls keine " "per WLAN erreichbaren Nachbarknoten in deiner Nähe sind oder du deine " "Internetverbindung für das Mesh-Netzwerk zur Verfügung stellen möchtest." diff --git a/package/gluon-config-mode-mesh-vpn/i18n/fr.po b/package/gluon-config-mode-mesh-vpn/i18n/fr.po index fc854613..0c324f32 100644 --- a/package/gluon-config-mode-mesh-vpn/i18n/fr.po +++ b/package/gluon-config-mode-mesh-vpn/i18n/fr.po @@ -1,12 +1,12 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-08-12 23:30+0100\n" "Last-Translator:Tobias Bernot \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -23,14 +23,9 @@ msgid "Use internet connection (mesh VPN)" msgstr "Utiliser la connection internet (Mesh-VPN)" msgid "" -"Your internet connection can be used to establish an encrypted connection " -"with other nodes. Enable this option if there are no other nodes reachable " -"over WLAN in your vicinity or you want to make a part of your connection's " +"Your internet connection can be used to establish a VPN connection with " +"other nodes. Enable this option if there are no other nodes reachable over " +"WLAN in your vicinity or you want to make a part of your connection's " "bandwidth available for the network. You can limit how much bandwidth the " "node will use at most." msgstr "" -"Votre nœud peut partager votre accès internet grâce une communication encryptée " -"avec d'autres nœuds. Vous pouvez limiter la bande passante utilisée par ceci. " -"Active cette option, si vous n'avez pas d'autres nœuds atteignables par WLAN " -"ou si vous voulez partager votre bande passante pour le réseau MESH." - diff --git a/package/gluon-config-mode-mesh-vpn/i18n/gluon-config-mode-mesh-vpn.pot b/package/gluon-config-mode-mesh-vpn/i18n/gluon-config-mode-mesh-vpn.pot index 52e2eef8..b6722919 100644 --- a/package/gluon-config-mode-mesh-vpn/i18n/gluon-config-mode-mesh-vpn.pot +++ b/package/gluon-config-mode-mesh-vpn/i18n/gluon-config-mode-mesh-vpn.pot @@ -14,7 +14,7 @@ msgid "Use internet connection (mesh VPN)" msgstr "" msgid "" -"Your internet connection can be used to establish an encrypted connection " +"Your internet connection can be used to establish a VPN connection " "with other nodes. Enable this option if there are no other nodes reachable " "over WLAN in your vicinity or you want to make a part of your connection's " "bandwidth available for the network. You can limit how much bandwidth the " diff --git a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua new file mode 100644 index 00000000..16282eba --- /dev/null +++ b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/reboot/0100-mesh-vpn.lua @@ -0,0 +1,49 @@ +local site_i18n = i18n 'gluon-site' + +local uci = require("simple-uci").cursor() +local fs = require "nixio.fs" + +local platform = require 'gluon.platform' +local site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' +local util = require "gluon.util" + +local pretty_hostname = require 'pretty_hostname' + + +local has_fastd = fs.access('/lib/gluon/mesh-vpn/fastd') +local has_tunneldigger = fs.access('/lib/gluon/mesh-vpn/tunneldigger') + + +local hostname = pretty_hostname.get(uci) +local contact = uci:get_first("gluon-node-info", "owner", "contact") + +local pubkey +local msg + + +if has_tunneldigger then + local tunneldigger_enabled = uci:get_bool("tunneldigger", "mesh_vpn", "enabled") + if not tunneldigger_enabled then + msg = site_i18n._translate('gluon-config-mode:novpn') + end +elseif has_fastd then + local fastd_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled") + if fastd_enabled then + pubkey = util.trim(util.exec("/etc/init.d/fastd show_key mesh_vpn")) + msg = site_i18n._translate('gluon-config-mode:pubkey') + else + msg = site_i18n._translate('gluon-config-mode:novpn') + end +end + +if not msg then return end + +renderer.render_string(msg, { + pubkey = pubkey, + hostname = hostname, + site = site, + platform = platform, + sysconfig = sysconfig, + contact = contact, +}) diff --git a/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua new file mode 100644 index 00000000..1ad50794 --- /dev/null +++ b/package/gluon-config-mode-mesh-vpn/luasrc/lib/gluon/config-mode/wizard/0300-mesh-vpn.lua @@ -0,0 +1,63 @@ +local fs = require "nixio.fs" + +local has_fastd = fs.access('/lib/gluon/mesh-vpn/fastd') +local has_tunneldigger = fs.access('/lib/gluon/mesh-vpn/tunneldigger') + +return function(form, uci) + if not (has_fastd or has_tunneldigger) then + return + end + + local pkg_i18n = i18n 'gluon-config-mode-mesh-vpn' + + local msg = pkg_i18n.translate( + 'Your internet connection can be used to establish a ' .. + 'VPN connection with other nodes. ' .. + 'Enable this option if there are no other nodes reachable ' .. + 'over WLAN in your vicinity or you want to make a part of ' .. + 'your connection\'s bandwidth available for the network. You can limit how ' .. + 'much bandwidth the node will use at most.' + ) + + local s = form:section(Section, nil, msg) + + local o + + local meshvpn = s:option(Flag, "meshvpn", pkg_i18n.translate("Use internet connection (mesh VPN)")) + meshvpn.default = uci:get_bool("fastd", "mesh_vpn", "enabled") or uci:get_bool("tunneldigger", "mesh_vpn", "enabled") + function meshvpn:write(data) + if has_fastd then + uci:set("fastd", "mesh_vpn", "enabled", data) + end + if has_tunneldigger then + uci:set("tunneldigger", "mesh_vpn", "enabled", data) + end + end + + local limit = s:option(Flag, "limit_enabled", pkg_i18n.translate("Limit bandwidth")) + limit:depends(meshvpn, true) + limit.default = uci:get_bool("simple-tc", "mesh_vpn", "enabled") + function limit:write(data) + uci:set("simple-tc", "mesh_vpn", "interface") + uci:set("simple-tc", "mesh_vpn", "enabled", data) + uci:set("simple-tc", "mesh_vpn", "ifname", "mesh-vpn") + end + + o = s:option(Value, "limit_ingress", pkg_i18n.translate("Downstream (kbit/s)")) + o:depends(limit, true) + o.default = uci:get("simple-tc", "mesh_vpn", "limit_ingress") + o.datatype = "uinteger" + function o:write(data) + uci:set("simple-tc", "mesh_vpn", "limit_ingress", data) + end + + o = s:option(Value, "limit_egress", pkg_i18n.translate("Upstream (kbit/s)")) + o:depends(limit, true) + o.default = uci:get("simple-tc", "mesh_vpn", "limit_egress") + o.datatype = "uinteger" + function o:write(data) + uci:set("simple-tc", "mesh_vpn", "limit_egress", data) + end + + return {'fastd', 'tunneldigger', 'simple-tc'} +end diff --git a/package/gluon-config-mode-theme/Makefile b/package/gluon-config-mode-theme/Makefile new file mode 100644 index 00000000..38858f0c --- /dev/null +++ b/package/gluon-config-mode-theme/Makefile @@ -0,0 +1,16 @@ +# Copyright (C) 2013 Nils Schneider +# This is free software, licensed under the Apache 2.0 license. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-config-mode-theme +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-config-mode-theme + TITLE:=Gluon config mode theme for gluon-web + DEPENDS:=+gluon-core +gluon-web +endef + +$(eval $(call BuildPackageGluon,gluon-config-mode-theme)) diff --git a/package/gluon-config-mode-theme/files/lib/gluon/config-mode/view/theme/layout.html b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/view/theme/layout.html new file mode 100644 index 00000000..874419a7 --- /dev/null +++ b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/view/theme/layout.html @@ -0,0 +1,152 @@ +<%# +Copyright 2008 Steven Barth +Copyright 2008-2010 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +-%> +<% + local uci = require("simple-uci").cursor() + local fs = require "nixio.fs" + local pretty_hostname = require "pretty_hostname" + + local hostname = pretty_hostname.get(uci) + local release = fs.readfile("/lib/gluon/release") + + local root = node() + local rnode = node(unpack(request)) + + local category = request[1] + local cattree = category and node(category) + + local function node_visible(node) + return ( + node.title and + node.target and + (not node.hidden) + ) + end + + local function node_children(node) + if not node then return {} end + + local ret = {} + for k, v in pairs(node.nodes) do + if node_visible(v) then + table.insert(ret, k) + end + end + + table.sort(ret, + function(a, b) + return (node.nodes[a].order or 100) + < (node.nodes[b].order or 100) + end + ) + return ret + end + + local categories = node_children(root) + + local function append(xs, x) + local r = {unpack(xs)} + r[#r+1] = x + return r + end + + local function title(node) + return i18n(node.pkg).translate(node.title) + end + + local function subtree(prefix, node, name, ...) + if not node then return end + + local children = node_children(node) + if #children == 0 then return end + + %> +
+
    + <% + for i, v in ipairs(children) do + local child = node.nodes[v] + local active = (v == name) + %> +
  • + <%|title(child)%> +
  • + <% + end + %> +
+
+ <% + subtree(append(prefix, name), node.nodes[name], ...) + %> +
+ <% + end + + local function menutree(path, ...) + subtree({path}, root.nodes[category], ...) + end + + http:prepare_content("application/xhtml+xml") +-%> + + + + + + <%| hostname .. ((rnode and rnode.title) and ' - ' .. title(rnode) or '') %> + + + + + +
+ <% + if not hidenav then + menutree(unpack(request)) + end + %> + +
+ + + <% + ok, err = pcall(renderer.render, content, scope, pkg) + if not ok then + renderer.render('error/500', {message = err}, 'gluon-web') + end + %> + +
+
+ + diff --git a/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css new file mode 100644 index 00000000..e270b30d --- /dev/null +++ b/package/gluon-config-mode-theme/files/lib/gluon/config-mode/www/static/gluon.css @@ -0,0 +1 @@ +.lang_he{direction:RTL;unicode-bidi:embed}.hidden{display:none}html{min-height:100%;height:auto;position:relative}body,input,select,option{font-family:'Open Sans', Arial, sans-serif;font-size:12pt}body{color:#4d4e53;line-height:1.5em;margin:0;display:flex;flex-direction:column;min-height:100vh;background-color:#f3f3f3}a img{border:none;text-decoration:none}.tabmenu1{text-align:center}ul.tabmenu{list-style:none;padding:0;margin:2em 0;display:inline-flex}ul.tabmenu li{white-space:nowrap;margin:0 0.5em;padding:0;text-align:center}ul.tabmenu li a{display:block;text-decoration:none;padding:1em;margin:0;color:#333;border-radius:2em}ul.tabmenu li a:hover{background:#ffe9b3}ul.tabmenu li.active a{font-weight:bold;background:white;color:#333}abbr,acronym{font-style:normal;font-variant:normal}abbr[title],acronym[title]{border-bottom:1px dotted;cursor:help}a:link abbr[title],a:visited abbr[title],a:link acronym[title],a:visited acronym[title]{cursor:pointer}code{font-family:monospace;white-space:pre}#maincontent ul{margin-left:2em}.clear{clear:both}.error{color:#ff0000;background-color:white}#menubar{display:flex;background:#dc0067;color:#ffffff}#menubar a:link.topcat,#menubar a:visited.topcat{position:relative;display:block;padding:0.5em;text-decoration:none;font-size:80%;font-weight:normal;color:white}#menubar a:link.topcat:hover,#menubar a:link.topcat:focus,#menubar a:visited.topcat:hover,#menubar a:visited.topcat:focus{background:#ffb400;color:black}#menubar a:link.topcat.active,#menubar a:visited.topcat.active{background:#ffb400;color:black;font-weight:bold}#menubar div.hostinfo{position:relative;margin:0;padding:0.5em;flex:1;font-weight:bold;font-size:80%}#menubar div.hostinfo a:link,#menubar div.hostinfo a:visited{text-decoration:none;font-weight:bold;color:white}#menubar div.hostinfo a:link:hover,#menubar div.hostinfo a:link:focus,#menubar div.hostinfo a:visited:hover,#menubar div.hostinfo a:visited:focus{text-decoration:underline}#topmenu{list-style:none;margin:0;padding:0}#topmenu li{display:inline-block}#maincontent{padding:0 1em 2em;max-width:60em;min-width:40em;margin:1em auto}#maincontent p{margin-bottom:1em}.gluon-section{margin:0;padding:0;border:none;margin-bottom:1.3em}.gluon-section:last-child{margin-bottom:0.7em}.gluon-section legend{font-size:1.4em;font-weight:bold;position:relative;padding:0;margin-bottom:0.5em}.gluon-section h2{margin:0em 0 0.5em -0.5em !important}.gluon-section h3{text-decoration:none !important;font-weight:bold !important;color:#555555 !important;margin:0.25em !important;font-size:100% !important}.gluon-section-descr{margin-bottom:2em}input:placeholder{color:#aaaaaa}input:-webkit-input-placeholder{color:#aaaaaa}input:-moz-placeholder{color:#aaaaaa}input:-ms-input-placeholder{color:#aaaaaa}input[type=checkbox]{display:none}input[type=checkbox]+label{display:inline-block;position:relative;width:1em;height:1em;margin:0}input[type=checkbox]:checked+label:after{content:'✔';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.5em;width:100%;text-align:center;font-size:1.7em}input[type=radio]{display:none}input[type=radio]+label{display:inline-block;position:relative;width:0.8em;height:0.8em;padding:0.5em;margin:0.2em 0.2em 0.2em 0.1em;border:none;background:#ffe199;vertical-align:middle;border-radius:50%}input[type=radio]:checked+label:after{content:'•';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.4em;width:100%;text-align:center;font-size:2em}input[type=submit],input[type=reset],input[type=image],input[type=button]{cursor:pointer}select,input,textarea,input[type=checkbox]+label{color:#003247;border:none;background:#ffe199;border-radius:3pt;padding:0.5em;margin-top:1px;margin-bottom:2px;box-sizing:content-box;outline:0}option{color:#003247;background:#ffe199}input[type=image]{border:none}select,input[type=text],input[type=password]{min-width:20em}input.gluon-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;user-select:none;font-size:100%;padding:0.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#E6E6E6;text-decoration:none;border-radius:2px;transition:0.1s linear box-shadow;margin-left:0.5em;background-repeat:no-repeat}input.gluon-button::-moz-focus-inner{padding:0;border:0}input.gluon-button:active{box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset}input.gluon-button:focus{outline:0}input.gluon-button:hover,input.gluon-button:focus{background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}input.gluon-button[disabled]{border:none;background-image:none;opacity:0.40;cursor:not-allowed;box-shadow:none}input.gluon-button-reset{background-color:#e30;color:#fff}input.gluon-button-submit{background-color:#009ee0;color:#fff}.gluon-input-invalid{background:#e30 !important;color:white}div.gluon-section-remove input{border-bottom:none}textarea{margin-left:-1px;margin-bottom:0.5em}.gluon-section .gluon-rowstyle-1 h3{background-color:#eeeeff;color:#555555}.gluon-rowstyle-2{color:#000000}div.gluon-value{display:flex;flex-direction:row;margin-bottom:0.5em}.gluon-section-node .gluon-value:last-child{margin-bottom:0}.gluon-value-title{flex:2;text-align:right;padding-top:0.39em;padding-right:1em;font-weight:bold}div.gluon-value-field{flex:3;position:relative}div.gluon-value-field input,div.gluon-value-field select,div.gluon-value-field input+label{position:relative}div.gluon-value-field-text{flex:3;padding-top:0.39em}div.gluon-value-field-long{flex:10;position:relative;margin-top:0.65em}div.gluon-value-field-long input,div.gluon-value-field-long select,div.gluon-value-field-long input+label{position:relative}div.gluon-value-field-long-after{flex:2}div.gluon-value-description{font-size:8pt}div.gluon-section-create{clear:left;white-space:nowrap;vertical-align:top}div.gluon-section-create .gluon-button{margin:0.25em}input.gluon-section-create-name{margin-right:-0.25em}div.gluon-map-descr{margin-bottom:1em}.gluon-map-descr:empty,.gluon-section-descr:empty{display:none}.gluon-map-descr,.gluon-section-descr,.gluon-page-actions{padding:1em;background:#ececec}.gluon-page-actions{text-align:right;display:flex;flex-flow:row-reverse}div.gluon-optionals{padding:0.25em;border-bottom:1px dotted #bbbbbb}div.gluon-section-remove{float:right}.gluon-section-node{clear:both;position:relative;border:none}.gluon-section-node-tabbed{border-top-left-radius:0}div.gluon-error{font-size:95%;font-weight:bold;color:#ff0000;background-color:#ffffff}.gluon-value-error input,.gluon-value-error select{background-color:#ffcccc}.gluon-section-error{color:red;background-color:white;font-size:95%;border:1px dotted red;margin:3px;padding:3px}.gluon-value-field var{color:#2222FF}.gluon-add:after,.gluon-remove:after{cursor:pointer;display:inline-block;text-align:center;vertical-align:middle;font-size:180%;width:1.2em;height:1em}.gluon-add{color:#008000;position:relative;left:21em}input+.gluon-add{left:0;top:0.04em}.gluon-add:first-child{top:0.53em;left:-0.08em}.gluon-add:after{content:'+'}.gluon-remove{color:#800000;position:relative;top:-0.03em}.gluon-remove:after{content:'–'}.left{text-align:left !important}.right{text-align:right !important}.inline{display:inline}.error500{border:1px dotted #ff0000;background-color:#ffffff;color:#000000;padding:0.5em}.errorbox{border:1px solid #FF0000;background-color:#FFCCCC;padding:5px;margin-bottom:5px}.errorbox a{color:#000000 !important}.the-key{text-align:left;font-size:1.4em;background:#ffe9b3;border:3pt dashed #dc0067;margin-bottom:0.5em;padding:0.5em} diff --git a/package/gluon-config-mode-theme/i18n/de.po b/package/gluon-config-mode-theme/i18n/de.po new file mode 100644 index 00000000..b18a346d --- /dev/null +++ b/package/gluon-config-mode-theme/i18n/de.po @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2013-03-29 12:13+0200\n" +"Last-Translator: Matthias Schiffer \n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "JavaScript required!" +msgstr "JavaScript benötigt!" + +msgid "" +"You must enable JavaScript in your browser or the web interface will not " +"work properly." +msgstr "Bitte aktiviere JavaScript in deinem Browser, damit das Webinterface " +"korrekt funktionieren kann." diff --git a/package/gluon-config-mode-theme/i18n/fr.po b/package/gluon-config-mode-theme/i18n/fr.po new file mode 100644 index 00000000..95e73b1a --- /dev/null +++ b/package/gluon-config-mode-theme/i18n/fr.po @@ -0,0 +1,19 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2013-12-22 17:11+0200\n" +"Last-Translator: goofy \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "JavaScript required!" +msgstr "" + +msgid "" +"You must enable JavaScript in your browser or the web interface will not " +"work properly." +msgstr "" diff --git a/package/gluon-config-mode-theme/i18n/gluon-config-mode-theme.pot b/package/gluon-config-mode-theme/i18n/gluon-config-mode-theme.pot new file mode 100644 index 00000000..1676d857 --- /dev/null +++ b/package/gluon-config-mode-theme/i18n/gluon-config-mode-theme.pot @@ -0,0 +1,10 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "JavaScript required!" +msgstr "" + +msgid "" +"You must enable JavaScript in your browser or the web interface will not " +"work properly." +msgstr "" diff --git a/package/gluon-config-mode-theme/sass/gluon.scss b/package/gluon-config-mode-theme/sass/gluon.scss new file mode 100644 index 00000000..8b548e8e --- /dev/null +++ b/package/gluon-config-mode-theme/sass/gluon.scss @@ -0,0 +1,640 @@ +/* + ATTENTION: This file is not compiled when building gluon. + The compiled version is at ../files/lib/gluon/config-mode/www/static/gluon.css + + Use sass like this to update it: + + sass --sourcemap=none -C -t compressed sass/gluon.scss files/lib/gluon/config-mode/www/static/gluon.css + + When commiting changes to this file make sure to commit the respective + changes to the compilid version within the same commit! +*/ + +@charset "utf-8"; + +$ffyellow: #ffb400; +$ffmagenta: #dc0067; +$ffzusatz: #009ee0; +$red: #ee3300; + +@mixin button { + &::-moz-focus-inner { + padding: 0; + border: 0; + } + + display: inline-block; + zoom: 1; + line-height: normal; + white-space: nowrap; + vertical-align: baseline; + text-align: center; + cursor: pointer; + user-select: none; + + + font-size: 100%; + padding: 0.5em 1em; + color: rgba(0, 0, 0, 0.80); + border: none rgba(0, 0, 0, 0); + background-color: #E6E6E6; + text-decoration: none; + border-radius: 2px; + + /* Transitions */ + transition: 0.1s linear box-shadow; + + &:active { + box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset; + } + + &:focus { + outline: 0; + } + + &:hover, &:focus { + background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10)); + } + + &[disabled] { + border: none; + background-image: none; + opacity: 0.40; + cursor: not-allowed; + box-shadow: none; + } +} + +@mixin button-primary { + background-color: $ffzusatz; + color: #fff; +} + +.lang_he { + direction: RTL; + unicode-bidi: embed; +} + +.hidden { + display: none; +} + +html { + min-height: 100%; + height: auto; + position:relative; +} + +body, input, select, option { + font-family: 'Open Sans', Arial, sans-serif; + font-size: 12pt; +} + +body { + color: rgb(77, 78, 83); + line-height: 1.5em; + margin: 0; + display: flex; + flex-direction: column; + min-height: 100vh; + background-color: #f3f3f3; +} + +a img { + border: none; + text-decoration: none; +} + +.tabmenu1 { + text-align: center; +} + +ul.tabmenu { + list-style: none; + padding: 0; + margin: 2em 0; + display: inline-flex; +} + +ul.tabmenu li { + white-space: nowrap; + margin: 0 0.5em; + padding: 0; + text-align: center; + + a { + display: block; + text-decoration: none; + padding: 1em; + margin: 0; + color: #333; + border-radius: 2em; + + &:hover { + background: lighten($ffyellow, 35); + } + } + + &.active a { + font-weight: bold; + background: white; + color: #333; + } +} + +abbr, +acronym { + font-style: normal; + font-variant: normal; +} + +abbr[title], +acronym[title] { + border-bottom: 1px dotted; + cursor: help; +} + +a:link abbr[title], +a:visited abbr[title], +a:link acronym[title], +a:visited acronym[title] { + cursor: pointer; +} + +code { + font-family: monospace; + white-space: pre; +} + +#maincontent ul { + margin-left: 2em; +} + +.clear { + clear: both; +} + +.error { + color: #ff0000; + background-color: white; +} + +#menubar { + display: flex; + background: $ffmagenta; + color: #ffffff; +} + +#menubar a:link.topcat, +#menubar a:visited.topcat { + position: relative; + display: block; + padding: 0.5em; + text-decoration: none; + font-size: 80%; + font-weight: normal; + color: white; + + &:hover, &:focus { + background: $ffyellow; + color: black; + } + + &.active { + background: $ffyellow; + color: black; + font-weight: bold; + } +} + +#menubar div.hostinfo { + position: relative; + margin: 0; + padding: 0.5em; + flex: 1; + font-weight: bold; + font-size: 80%; +} + +#menubar div.hostinfo a { + &:link, &:visited { + text-decoration: none; + font-weight: bold; + color: white; + + &:hover, &:focus { + text-decoration: underline; + } + } +} + +#topmenu { + list-style: none; + margin: 0; + padding: 0; +} + +#topmenu li { + display: inline-block; +} + +#maincontent { + padding: 0 1em 2em; + max-width: 60em; + min-width: 40em; + margin: 1em auto; +} + +#maincontent p { + margin-bottom: 1em; +} + +.gluon-section { + margin: 0; + padding: 0; + border: none; + margin-bottom: 1.3em; +} + +.gluon-section:last-child { + margin-bottom: 0.7em; +} + +.gluon-section legend { + font-size: 1.4em; + font-weight: bold; + position: relative; + padding: 0; + margin-bottom: 0.5em; +} + +.gluon-section h2 { + margin: 0em 0 0.5em -0.5em !important; +} + +.gluon-section h3 { + text-decoration: none !important; + font-weight: bold !important; + color: #555555 !important; + margin: 0.25em !important; + font-size: 100% !important; +} + +.gluon-section-descr { + margin-bottom: 2em; +} + +input:placeholder { + color: #aaaaaa; +} + +input:-webkit-input-placeholder { + color: #aaaaaa; +} + +input:-moz-placeholder { + color: #aaaaaa; +} + +input:-ms-input-placeholder { + color: #aaaaaa; +} + +input[type=checkbox] { + display: none; + + & + label { + display: inline-block; + position: relative; + width: 1em; + height: 1em; + margin: 0; + } + + &:checked + label:after { + content: '✔'; + color: $ffmagenta; + vertical-align: middle; + position: absolute; + top: 50%; + left: 0; + margin-top: -0.5em; + width: 100%; + text-align: center; + font-size: 1.7em; + } +} + +input[type=radio] { + display: none; + + & + label { + display: inline-block; + position: relative; + width: 0.8em; + height: 0.8em; + padding: 0.5em; + margin: 0.2em 0.2em 0.2em 0.1em; + border: none; + background: lighten($ffyellow, 30); + vertical-align: middle; + border-radius: 50%; + } + + &:checked + label:after { + content: '•'; + color: $ffmagenta; + vertical-align: middle; + position: absolute; + top: 50%; + left: 0; + margin-top: -0.4em; + width: 100%; + text-align: center; + font-size: 2em; + } +} + +input[type=submit], +input[type=reset], +input[type=image], +input[type=button] { + cursor: pointer; +} + +select, +input, +textarea, +input[type=checkbox] + label { + color: darken($ffzusatz, 30); + border: none; + background: lighten($ffyellow, 30); + border-radius: 3pt; + padding: 0.5em; + margin-top: 1px; + margin-bottom: 2px; + box-sizing: content-box; + outline: 0; +} + +option { + color: darken($ffzusatz, 30); + background: lighten($ffyellow, 30); +} + +input[type=image] { + border: none; +} + +select, +input[type=text], +input[type=password] { + min-width: 20em; +} + +input.gluon-button { + @include button; + + margin-left: 0.5em; + background-repeat: no-repeat; +} + +input.gluon-button-reset { + background-color: $red; + color: #fff; +} +input.gluon-button-submit { + @include button-primary; +} + +.gluon-input-invalid { + background: $red !important; + color: white; +} + +div.gluon-section-remove input { + border-bottom: none; +} + +textarea { + margin-left: -1px; + margin-bottom: 0.5em; +} + +.gluon-section .gluon-rowstyle-1 h3 { + background-color: #eeeeff; + color: #555555; +} + +.gluon-rowstyle-2 { + color: #000000; +} + +div.gluon-value { + display: flex; + flex-direction: row; + margin-bottom: 0.5em; +} + +.gluon-section-node .gluon-value:last-child { + margin-bottom: 0; +} + +.gluon-value-title { + flex: 2; + text-align: right; + padding-top: 0.39em; + padding-right: 1em; + font-weight: bold; +} + +div.gluon-value-field { + flex: 3; + position: relative; + + input, select, input + label { + position: relative; + } +} + +div.gluon-value-field-text { + flex: 3; + padding-top: 0.39em; +} + +div.gluon-value-field-long { + flex: 10; + position: relative; + margin-top: 0.65em; + + input, select, input + label { + position: relative; + } +} + +div.gluon-value-field-long-after { + flex: 2; +} + +div.gluon-value-description { + font-size: 8pt; +} + +div.gluon-section-create { + clear: left; + white-space: nowrap; + vertical-align: top; +} + +div.gluon-section-create .gluon-button { + margin: 0.25em; +} + +input.gluon-section-create-name { + margin-right: -0.25em; +} + +div.gluon-map-descr { + margin-bottom: 1em; +} + +.gluon-map-descr:empty, .gluon-section-descr:empty { + display: none; +} + +.gluon-map-descr, .gluon-section-descr, .gluon-page-actions { + padding: 1em; + background: #ececec; +} + +.gluon-page-actions { + text-align: right; + display: flex; + flex-flow: row-reverse; +} + +div.gluon-optionals { + padding: 0.25em; + border-bottom: 1px dotted #bbbbbb; +} + +div.gluon-section-remove { + float: right; +} + +.gluon-section-node { + clear: both; + position: relative; + border: none; +} + +.gluon-section-node-tabbed { + border-top-left-radius: 0; +} + +div.gluon-error { + font-size: 95%; + font-weight: bold; + color: #ff0000; + background-color: #ffffff; +} + +.gluon-value-error input, +.gluon-value-error select { + background-color: #ffcccc; +} + +.gluon-section-error { + color: red; + background-color: white; + font-size: 95%; + border: 1px dotted red; + margin: 3px; + padding: 3px; +} + +.gluon-value-field var { + color: #2222FF; +} + +.gluon-add:after, .gluon-remove:after { + cursor: pointer; + display: inline-block; + text-align: center; + vertical-align: middle; + font-size: 180%; + width: 1.2em; + height: 1em; +} + +.gluon-add { + color: #008000; + + position: relative; + left: 21em; + + input + & { + left: 0; + top: 0.04em; + } + + &:first-child { + top: 0.53em; + left: -0.08em; + } + + &:after { + content: '+'; + } +} + +.gluon-remove { + color: #800000; + + position: relative; + top: -0.03em; + + &:after { + content: '–'; + } +} + +.left { + text-align: left !important; +} + +.right { + text-align: right !important; +} + +.inline { + display: inline; +} + +.error500 { + border: 1px dotted #ff0000; + background-color: #ffffff; + color: #000000; + padding: 0.5em; +} + +.errorbox { + border: 1px solid #FF0000; + background-color: #FFCCCC; + padding: 5px; + margin-bottom: 5px; +} + +.errorbox a { + color: #000000 !important; +} + + +.the-key { + text-align: left; + font-size: 1.4em; + background: lighten($ffyellow, 35); + border: 3pt dashed $ffmagenta; + margin-bottom: 0.5em; + padding: 0.5em +} diff --git a/package/gluon-core/Config.in b/package/gluon-core/Config.in new file mode 100644 index 00000000..9def3c29 --- /dev/null +++ b/package/gluon-core/Config.in @@ -0,0 +1,338 @@ +config KERNEL_NET_IP_TUNNEL + bool + +config KERNEL_NET_UDP_TUNNEL + bool + +config KERNEL_VXLAN + bool + select KERNEL_NET_IP_TUNNEL + select KERNEL_NET_UDP_TUNNEL + +config KERNEL_VETH + bool + + +# for fastd + +config KERNEL_TUN + bool + + +# for tunneldigger + +config KERNEL_L2TP_V3 + bool + +config KERNEL_L2TP_IP + bool + +config KERNEL_L2TP_ETH + bool + +config KERNEL_L2TP + bool + select KERNEL_L2TP_V3 + select KERNEL_L2TP_IP + select KERNEL_L2TP_ETH + + +# for simple-tc + +config KERNEL_NET_SCHED + bool + +config KERNEL_NET_CLS + bool + select KERNEL_NET_SCHED + +config KERNEL_NET_CLS_ACT + bool + select KERNEL_NET_CLS + +config KERNEL_NET_CLS_BASIC + bool + select KERNEL_NET_CLS + +config KERNEL_NET_SCH_TBF + bool + select KERNEL_NET_SCHED + +config KERNEL_NET_SCH_INGRESS + bool + select KERNEL_NET_CLS_ACT + + +# for batman-adv + +config KERNEL_DUMMY + bool + +config KERNEL_CRC16 + bool + +config KERNEL_LIBCRC32C + bool + + +# Netfilter modules used by ebtables and fw3 + +config KERNEL_NETFILTER + bool + +config KERNEL_NETFILTER_ADVANCED + bool + select KERNEL_NETFILTER + +config KERNEL_NETFILTER_XTABLES + bool + select KERNEL_NETFILTER_ADVANCED + +config KERNEL_BRIDGE_NF_EBTABLES + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_BRIDGE_EBT_T_FILTER + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_T_NAT + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_ARP + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_IP + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_IP6 + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_LIMIT + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_MARK + bool + select KERNEL_BRIDGE_NF_EBTABLES + +config KERNEL_BRIDGE_EBT_MARK_T + bool + select KERNEL_BRIDGE_NF_EBTABLES + + +# Not all of the following modules are really required for Gluon, but fw3 pulls +# them in, so we add them to the kernel config to reduce the number of loaded +# modules + +# kmod-nf-conntrack + +config KERNEL_NF_CONNTRACK + bool + select KERNEL_NETFILTER_ADVANCED + +config KERNEL_NF_CONNTRACK_RTCACHE + bool + select KERNEL_NF_CONNTRACK + +config KERNEL_NF_CONNTRACK_IPV4 + bool + select KERNEL_NF_CONNTRACK + + +# kmod-nf-conntrack6 + +config KERNEL_NF_CONNTRACK_IPV6 + bool + select KERNEL_NF_CONNTRACK + + +# kmod-nf-ipt + +config KERNEL_NF_REJECT_IPV4 + bool + select KERNEL_NETFILTER_ADVANCED + +config KERNEL_IP_NF_IPTABLES + bool + select KERNEL_NETFILTER_XTABLES + select KERNEL_NF_REJECT_IPV4 + + +# kmod-nf-ipt6 + +config KERNEL_NF_REJECT_IPV6 + bool + select KERNEL_NETFILTER_ADVANCED + +config KERNEL_IP6_NF_IPTABLES + bool + select KERNEL_NETFILTER_XTABLES + select KERNEL_NF_REJECT_IPV6 + + +# kmod-nf-nat + +config KERNEL_NF_NAT + bool + select KERNEL_NF_CONNTRACK + +config KERNEL_NF_NAT_REDIRECT + bool + select KERNEL_NF_NAT + +config KERNEL_NF_NAT_IPV4 + bool + select KERNEL_NETFILTER_ADVANCED + select KERNEL_NF_NAT + +config KERNEL_NF_NAT_MASQUERADE_IPV4 + bool + select KERNEL_NF_NAT_IPV4 + + +# kmod-ipt-core + +config KERNEL_IP_NF_FILTER + bool + select KERNEL_IP_NF_IPTABLES + +config KERNEL_IP_NF_MANGLE + bool + select KERNEL_IP_NF_IPTABLES + +config KERNEL_IP_NF_TARGET_REJECT + bool + select KERNEL_IP_NF_FILTER + +config KERNEL_NETFILTER_XT_MATCH_LIMIT + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_MAC + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_MULTIPORT + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_COMMENT + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_TIME + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MARK + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_TARGET_LOG + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_TARGET_TCPMSS + bool + select KERNEL_NETFILTER_XTABLES + +# kmod-ip6tables + +config KERNEL_IP6_NF_FILTER + bool + select KERNEL_IP6_NF_IPTABLES + +config KERNEL_IP6_NF_MANGLE + bool + select KERNEL_IP6_NF_IPTABLES + +config KERNEL_IP6_NF_TARGET_REJECT + bool + select KERNEL_IP6_NF_IPTABLES + + +# kmod-ipt-conntrack + +config KERNEL_NETFILTER_XT_MATCH_STATE + bool + select KERNEL_NETFILTER_XTABLES + select KERNEL_NF_CONNTRACK + +config KERNEL_NETFILTER_XT_MATCH_CONNTRACK + bool + select KERNEL_NETFILTER_XTABLES + select KERNEL_NF_CONNTRACK + + +# kmod-ipt-nat + +config KERNEL_IP_NF_NAT + bool + select KERNEL_NF_NAT + select KERNEL_IP_NF_IPTABLES + +config KERNEL_IP_NF_TARGET_MASQUERADE + bool + select KERNEL_NF_NAT_MASQUERADE_IPV4 + select KERNEL_IP_NF_NAT + +config KERNEL_IP_NF_TARGET_REDIRECT + bool + select KERNEL_NF_NAT + select KERNEL_IP_NF_NAT + + +# kmod-ipt-extra + +config KERNEL_NETFILTER_XT_MATCH_ADDRTYPE + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_OWNER + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_PKTTYPE + bool + select KERNEL_NETFILTER_XTABLES + +config KERNEL_NETFILTER_XT_MATCH_QUOTA + bool + select KERNEL_NETFILTER_XTABLES + + +config GLUON_SPECIALIZE_KERNEL + bool "Specialize kernel for Gluon" + select KERNEL_VXLAN + select KERNEL_NF_CONNTRACK_RTCACHE + select KERNEL_NF_CONNTRACK_IPV4 + select KERNEL_NF_CONNTRACK_IPV6 + select KERNEL_IP_NF_IPTABLES + select KERNEL_IP6_NF_IPTABLES + select KERNEL_NF_NAT_REDIRECT + select KERNEL_NF_NAT_IPV4 + select KERNEL_NF_NAT_MASQUERADE_IPV4 + select KERNEL_IP_NF_FILTER + select KERNEL_IP_NF_MANGLE + select KERNEL_IP_NF_TARGET_REJECT + select KERNEL_IP6_NF_FILTER + select KERNEL_IP6_NF_MANGLE + select KERNEL_IP6_NF_TARGET_REJECT + select KERNEL_NETFILTER_XT_MATCH_LIMIT + select KERNEL_NETFILTER_XT_MATCH_MAC + select KERNEL_NETFILTER_XT_MATCH_MULTIPORT + select KERNEL_NETFILTER_XT_MATCH_COMMENT + select KERNEL_NETFILTER_XT_MATCH_TIME + select KERNEL_NETFILTER_XT_MARK + select KERNEL_NETFILTER_XT_TARGET_LOG + select KERNEL_NETFILTER_XT_TARGET_TCPMSS + select KERNEL_NETFILTER_XT_MATCH_STATE + select KERNEL_NETFILTER_XT_MATCH_CONNTRACK + select KERNEL_IP_NF_NAT + select KERNEL_IP_NF_TARGET_MASQUERADE + select KERNEL_IP_NF_TARGET_REDIRECT diff --git a/package/gluon-core/Makefile b/package/gluon-core/Makefile index 725fb737..c0600c1f 100644 --- a/package/gluon-core/Makefile +++ b/package/gluon-core/Makefile @@ -1,46 +1,35 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-core -PKG_VERSION:=3 -PKG_RELEASE:=$(GLUON_VERSION) + +GLUON_VERSION = $(shell git describe --always --dirty=+ 2>/dev/null || echo unknown) +PKG_VERSION:=$(if $(DUMP),x,$(GLUON_VERSION)) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -include $(GLUONDIR)/include/package.mk +include ../gluon.mk +include $(INCLUDE_DIR)/cmake.mk define Package/gluon-core - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Base files of Gluon - DEPENDS:=+gluon-site +libgluonutil +lua-platform-info +lua-hash +luci-base +luci-lib-jsonc +odhcp6c +firewall + DEPENDS:= \ + +gluon-site +libgluonutil +libiwinfo-lua +lua-platform-info +lua-simple-uci +lua-hash +lua-jsonc \ + +luci-lib-nixio +vxlan +odhcp6c +firewall +pretty-hostname endef - define Package/gluon-core/description Gluon community wifi mesh firmware framework: core endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile +define Package/gluon-core/config + source "$(SOURCE)/Config.in" endef define Package/gluon-core/install - $(CP) ./files/* $(1)/ - $(SED) 's/__GLUON_OPENWRT_FEEDS__/{$(GLUON_OPENWRT_FEEDS:%="%",)}/' $(1)/lib/gluon/upgrade/500-opkg + $(Gluon/Build/Install) $(INSTALL_DIR) $(1)/lib/gluon - echo "$(GLUON_VERSION)" > $(1)/lib/gluon/gluon-version + echo '$(GLUON_VERSION)' > $(1)/lib/gluon/gluon-version endef -define Package/gluon-core/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-core)) +$(eval $(call BuildPackageGluon,gluon-core)) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 1647d778..0977b086 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -1,32 +1,80 @@ -need_string 'site_code' -need_string 'site_name' +need_string(in_site({'site_code'})) +need_string(in_site({'site_name'})) -if need_table('opkg', nil, false) then - need_string('opkg.openwrt', false) +-- this_domain() returns nil when multidomain support is disabled +if this_domain() then + function need_domain_name(path) + need_string(path) + need(path, function(default_domain) + local f = io.open(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/domains/' .. default_domain .. '.json') + if not f then return false end + f:close() + return true + end, nil, 'be a valid domain name') + end + need_domain_name(in_site({'default_domain'})) - function check_repo(k, _) - -- this is not actually a uci name, but using the same naming rules here is fine - assert_uci_name(k) - - need_string(string.format('opkg.extra[%q]', k)) - end - - need_table('opkg.extra', check_repo, false) + need_table(in_domain({'domain_names'}), function(domain) + need_alphanumeric_key(domain) + need_string(domain) + end) + need_string(in_domain({'domain_names', this_domain()})) end -need_string('hostname_prefix', false) -need_string 'timezone' +need_string_match(in_domain({'domain_seed'}), '^' .. ('%x'):rep(64) .. '$') -need_string_array('ntp_servers', false) +need_string({'opkg', 'lede'}, false) +need_table({'opkg', 'extra'}, function(extra_repo) + need_alphanumeric_key(extra_repo) + need_string(extra_repo) +end, false) -need_string_match('prefix4', '^%d+.%d+.%d+.%d+/%d+$') -need_string_match('prefix6', '^[%x:]+/%d+$') +need_string(in_site({'hostname_prefix'}), false) +need_string(in_site({'timezone'})) + +need_string_array({'ntp_servers'}, false) + +need_string_match(in_domain({'prefix6'}), '^[%x:]+/64$') for _, config in ipairs({'wifi24', 'wifi5'}) do - if need_table(config, nil, false) then - need_string('regdom') -- regdom is only required when wifi24 or wifi5 is configured + if need_table({config}, nil, false) then + need_string(in_site({'regdom'})) -- regdom is only required when wifi24 or wifi5 is configured - need_number(config .. '.channel') - end + need_number({config, 'channel'}) + + local rates = {1000, 2000, 5500, 6000, 9000, 11000, 12000, 18000, 24000, 36000, 48000, 54000} + local supported_rates = need_array_of(in_site({config, 'supported_rates'}), rates, false) + need_array_of({config, 'basic_rate'}, supported_rates or rates, supported_rates ~= nil) + + if need_table({config, 'ibss'}, nil, false) then + need_string_match(in_domain({config, 'ibss', 'ssid'}), '^' .. ('.?'):rep(32) .. '$') + need_string_match(in_domain({config, 'ibss', 'bssid'}), '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$') + need_one_of({config, 'ibss', 'mcast_rate'}, supported_rates or rates, false) + need_number({config, 'ibss', 'vlan'}, false) + need_boolean({config, 'ibss', 'disabled'}, false) + end + + if need_table({config, 'mesh'}, nil, false) then + need_string_match(in_domain({config, 'mesh', 'id'}), '^' .. ('.?'):rep(32) .. '$') + need_one_of({config, 'mesh', 'mcast_rate'}, supported_rates or rates, false) + need_boolean({config, 'mesh', 'disabled'}, false) + end + end end + +need_boolean(in_site({'poe_passthrough'}), false) + +if need_table({'dns'}, nil, false) then + need_string_array_match({'dns', 'servers'}, '^[%x:]+$') +end + +need_string_array(in_domain({'next_node', 'name'}), false) +need_string_match(in_domain({'next_node', 'ip6'}), '^[%x:]+$', false) +need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false) + +need_boolean(in_domain({'mesh', 'vxlan'}), false) + +need_boolean(in_site({'mesh_on_wan'}), false) +need_boolean(in_site({'mesh_on_lan'}), false) +need_boolean(in_site({'single_as_lan'}), false) diff --git a/package/gluon-core/files/etc/config/gluon b/package/gluon-core/files/etc/config/gluon new file mode 100644 index 00000000..270547ac --- /dev/null +++ b/package/gluon-core/files/etc/config/gluon @@ -0,0 +1 @@ +config core 'core' diff --git a/package/gluon-core/files/etc/hotplug.d/ieee80211/01-gluon-core-codel-memusage b/package/gluon-core/files/etc/hotplug.d/ieee80211/01-gluon-core-codel-memusage new file mode 100755 index 00000000..07da10c9 --- /dev/null +++ b/package/gluon-core/files/etc/hotplug.d/ieee80211/01-gluon-core-codel-memusage @@ -0,0 +1,8 @@ +#!/bin/sh + +if [ "${ACTION}" = 'add' ]; then + RAM=$(awk '/MemTotal/ {print $2}' /proc/meminfo) + if [ "$RAM" -le $((32*1024)) ]; then + echo 'fq_memory_limit 262144' > "/sys/kernel/debug/ieee80211/$DEVICENAME/aqm" + fi +fi diff --git a/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf b/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf new file mode 100644 index 00000000..12d569a0 --- /dev/null +++ b/package/gluon-core/files/etc/sysctl.d/30-gluon-core.conf @@ -0,0 +1 @@ +vm.panic_on_oom=1 diff --git a/package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade b/package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade index a12ce78e..bd3a51d7 100755 --- a/package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade +++ b/package/gluon-core/files/etc/uci-defaults/zzz-gluon-upgrade @@ -1,5 +1,5 @@ #!/bin/sh -for script in /lib/gluon/upgrade/*; do - "$script" -done +gluon-reconfigure + +exit 0 diff --git a/package/gluon-core/files/lib/gluon/core/mesh/setup.d/.keep b/package/gluon-core/files/lib/gluon/core/mesh/setup.d/.keep new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-core/files/lib/gluon/core/mesh/teardown.d/.keep b/package/gluon-core/files/lib/gluon/core/mesh/teardown.d/.keep new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-core/files/lib/gluon/upgrade/020-interfaces b/package/gluon-core/files/lib/gluon/upgrade/020-interfaces deleted file mode 100755 index 34e1c8bb..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/020-interfaces +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/lua - -local sysconfig = require 'gluon.sysconfig' -local gluon_util = require 'gluon.util' -local platform = require 'gluon.platform' - -local uci = require('luci.model.uci').cursor() - - -if not (sysconfig.lan_ifname or sysconfig.wan_ifname) then - local function iface_exists(name) - return (gluon_util.exec('ip', 'link', 'show', 'dev', (name:gsub('%..*$', ''))) == 0) - end - - - local lan_ifname = uci:get('network', 'lan', 'ifname') - local wan_ifname = uci:get('network', 'wan', 'ifname') - - if platform.match('ar71xx', 'generic', {'cpe510', 'nanostation-m', 'nanostation-m-xw', 'unifi-outdoor-plus', 'uap-pro', 'unifiac-pro'}) then - lan_ifname, wan_ifname = wan_ifname, lan_ifname - end - - if wan_ifname and iface_exists(wan_ifname) then - sysconfig.wan_ifname = wan_ifname - sysconfig.lan_ifname = lan_ifname - else - sysconfig.wan_ifname = lan_ifname - end - - - uci:delete('network', 'lan') - uci:delete('network', 'wan') - - uci:save('network') -end diff --git a/package/gluon-core/files/lib/gluon/upgrade/030-system b/package/gluon-core/files/lib/gluon/upgrade/030-system deleted file mode 100755 index 0086a5dc..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/030-system +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/lua - -local sysconfig = require 'gluon.sysconfig' - --- Initial -if not sysconfig.gluon_version then - local site = require 'gluon.site_config' - local util = require 'gluon.util' - local uci = require('luci.model.uci').cursor() - - local system = uci:get_first('system', 'system') - - uci:set('system', system, 'hostname', (site.hostname_prefix or '') .. util.node_id()) - uci:set('system', system, 'timezone', site.timezone) - - uci:save('system') -end diff --git a/package/gluon-core/files/lib/gluon/upgrade/100-core-reset-sysctl b/package/gluon-core/files/lib/gluon/upgrade/100-core-reset-sysctl new file mode 100755 index 00000000..6f6f4316 --- /dev/null +++ b/package/gluon-core/files/lib/gluon/upgrade/100-core-reset-sysctl @@ -0,0 +1,8 @@ +#!/bin/sh + +# This script can be removed after Gluon v2018.2 + +# Check for a random line that always was in /etc/sysctl.conf +if grep -qxF 'net.ipv4.ip_forward=1' /etc/sysctl.conf; then + echo '# Defaults are configured in /etc/sysctl.d/* and can be customized in this file' >/etc/sysctl.conf +fi diff --git a/package/gluon-core/files/lib/gluon/upgrade/100-dnsmasq b/package/gluon-core/files/lib/gluon/upgrade/100-dnsmasq deleted file mode 100755 index 3636fbf6..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/100-dnsmasq +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -if [ -e /etc/dnsmasq.conf ]; then - sed -i -e '/^conf-dir=\/lib\/gluon\/dnsmasq\.d$/d' -e '/^conf-dir=\/var\/gluon\/dnsmasq\.d$/d' /etc/dnsmasq.conf -fi diff --git a/package/gluon-core/files/lib/gluon/upgrade/110-network b/package/gluon-core/files/lib/gluon/upgrade/110-network deleted file mode 100755 index bf87d47f..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/110-network +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/lua - -local uci = require('luci.model.uci').cursor() -local sysctl = require 'gluon.sysctl' -local sysconfig = require 'gluon.sysconfig' - - -uci:section('network', 'interface', 'wan', - { - ifname = sysconfig.wan_ifname, - type = 'bridge', - igmp_snooping = 0, - peerdns = 0, - auto = 1, - } -) - -if not uci:get('network', 'wan', 'proto') then - uci:set('network', 'wan', 'proto', 'dhcp') -end - - -uci:section('network', 'interface', 'wan6', - { - ifname = 'br-wan', - peerdns = 0, - ip6table = 1, - sourcefilter = 0, - } -) - -if not uci:get('network', 'wan6', 'proto') then - uci:set('network', 'wan6', 'proto', 'dhcpv6') -end - - -uci:section('network', 'rule6', 'wan6_lookup', - { - mark = '0x01/0x01', - lookup = 1, - } -) - -uci:section('network', 'route6', 'wan6_unreachable', - { - type = 'unreachable', - interface = 'loopback', - target = '::/0', - gateway = '::', - table = 1, - metric = 65535, - } -) - -uci:save('network') - - -uci:section('firewall', 'rule', 'wan_igmp', - { - name = 'Allow-IGMP', - src = 'wan', - proto = 'igmp', - family = 'ipv4', - target = 'ACCEPT', - } -) - -uci:section('firewall', 'rule', 'wan_mld', - { - name = 'Allow-MLD', - src = 'wan', - proto = 'icmp', - src_ip = 'fe80::/10', - icmp_type = { '130/0', '131/0', '132/0', '143/0', }, - family = 'ipv6', - target = 'ACCEPT', - } -) - -uci:save('firewall') - - -sysctl.set('net.ipv6.conf.all.accept_ra', 0) -sysctl.set('net.ipv6.conf.default.accept_ra', 0) diff --git a/package/gluon-core/files/lib/gluon/upgrade/120-ntp-servers b/package/gluon-core/files/lib/gluon/upgrade/120-ntp-servers deleted file mode 100755 index f38c1f5d..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/120-ntp-servers +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -if not site.ntp_servers or #site.ntp_servers == 0 then - os.exit(0) -end - -local c = uci.cursor() -c:delete('system', 'ntp', 'server') -c:set_list('system', 'ntp', 'server', site.ntp_servers) -c:save('system') diff --git a/package/gluon-core/files/lib/gluon/upgrade/130-reboot-on-oom b/package/gluon-core/files/lib/gluon/upgrade/130-reboot-on-oom deleted file mode 100755 index 48cfc5a8..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/130-reboot-on-oom +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/lua - -local sysctl = require 'gluon.sysctl' - -sysctl.set('vm.panic_on_oom', 1) diff --git a/package/gluon-core/files/lib/gluon/upgrade/140-firewall-rules b/package/gluon-core/files/lib/gluon/upgrade/140-firewall-rules deleted file mode 100755 index abd45381..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/140-firewall-rules +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -local c = uci.cursor() - - -local function reject_input_on_wan(zone) - if zone.name == 'wan' then - c:set('firewall', zone['.name'], 'input', 'REJECT') - c:set('firewall', zone['.name'], 'conntrack', '1') - end - - return true -end -c:foreach('firewall', 'zone', reject_input_on_wan) - -c:section('firewall', 'rule', 'wan_ssh', - { - name = 'wan_ssh', - src = 'wan', - dest_port = '22', - proto = 'tcp', - target = 'ACCEPT', - } -) - -c:save('firewall') diff --git a/package/gluon-core/files/lib/gluon/upgrade/200-wireless b/package/gluon-core/files/lib/gluon/upgrade/200-wireless deleted file mode 100755 index 5a4ec0a4..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/200-wireless +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/lua - -local util = require 'gluon.util' -local uci = require('luci.model.uci').cursor() -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - --- Initial -if not sysconfig.gluon_version then - uci:delete_all('wireless', 'wifi-iface') -end - -local function get_channel(radio, config) - if uci:get_first('gluon-core', 'wireless', 'preserve_channels') then - return uci:get('wireless', radio, 'channel') or config.channel - else - return config.channel - end -end - -local function configure_radio(radio, index, config) - if config then - local channel = get_channel(radio, config) - - uci:delete('wireless', radio, 'disabled') - - uci:set('wireless', radio, 'channel', channel) - uci:set('wireless', radio, 'htmode', 'HT20') - uci:set('wireless', radio, 'country', site.regdom) - end -end - -util.iterate_radios(configure_radio) - -uci:save('wireless') diff --git a/package/gluon-core/files/lib/gluon/upgrade/500-opkg b/package/gluon-core/files/lib/gluon/upgrade/500-opkg deleted file mode 100755 index 4380050c..00000000 --- a/package/gluon-core/files/lib/gluon/upgrade/500-opkg +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/lua - -local fs = require 'nixio.fs' -local site = require 'gluon.site_config' -local util = require 'luci.util' - - -local subst = {} - -subst['%%v'] = util.trim(fs.readfile('/etc/openwrt_version')) -subst['%%n'], subst['%%S'] = util.exec('. /etc/openwrt_release; echo $DISTRIB_CODENAME; echo $DISTRIB_TARGET'):match('([^\n]*)\n([^\n]*)') -subst['%%GS'] = site.site_code -subst['%%GV'] = util.trim(fs.readfile('/lib/gluon/gluon-version')) -subst['%%GR'] = util.trim(fs.readfile('/lib/gluon/release')) - -function replace_patterns(url) - for k, v in pairs(subst) do - url = url:gsub(k, v) - end - - return url -end - - -if site.opkg then - if site.opkg.openwrt then - local url = replace_patterns(site.opkg.openwrt) - local f = io.open('/etc/opkg/distfeeds.conf', 'w') - - for _, v in ipairs(__GLUON_OPENWRT_FEEDS__) do - f:write(replace_patterns(string.format('src/gz %%n_%s %s/%s\n', v, site.opkg.openwrt, v))) - end - - f:close() - end - - if site.opkg.extra and next(site.opkg.extra) then - local f = io.open('/etc/opkg/gluon.conf', 'w') - - for k, v in pairs(site.opkg.extra) do - f:write(string.format('src/gz %s %s\n', k, replace_patterns(v))) - end - - f:close() - - else - os.remove('/etc/opkg/gluon.conf') - end -end diff --git a/package/gluon-core/files/lib/netifd/proto/gluon_mesh.sh b/package/gluon-core/files/lib/netifd/proto/gluon_mesh.sh new file mode 100755 index 00000000..52d6abec --- /dev/null +++ b/package/gluon-core/files/lib/netifd/proto/gluon_mesh.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_gluon_mesh_init_config() { + proto_config_add_boolean fixed_mtu + proto_config_add_boolean transitive +} + +proto_gluon_mesh_setup() { + export CONFIG="$1" + export IFNAME="$2" + + local fixed_mtu transitive + json_get_vars fixed_mtu transitive + + export FIXED_MTU="${fixed_mtu:-0}" + export TRANSITIVE="${transitive:-0}" + + for script in /lib/gluon/core/mesh/setup.d/*; do + [ ! -x "$script" ] || "$script" + done + + proto_init_update "$IFNAME" 1 + + proto_add_data + json_add_boolean fixed_mtu "$FIXED_MTU" + json_add_boolean transitive "$TRANSITIVE" + [ "$IFNAME" != 'br-wan' ] && json_add_string zone 'mesh' + proto_close_data + proto_send_update "$CONFIG" + + for script in /lib/gluon/core/mesh/post-setup.d/*; do + [ ! -x "$script" ] || "$script" + done +} + +proto_gluon_mesh_teardown() { + export CONFIG="$1" + export IFNAME="$2" + + for script in /lib/gluon/core/mesh/teardown.d/*; do + [ ! -x "$script" ] || "$script" + done +} + +add_protocol gluon_mesh diff --git a/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh b/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh new file mode 100755 index 00000000..4a44a30e --- /dev/null +++ b/package/gluon-core/files/lib/netifd/proto/gluon_wired.sh @@ -0,0 +1,72 @@ +#!/bin/sh + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_gluon_wired_init_config() { + proto_config_add_boolean transitive + proto_config_add_int index +} + +xor2() { + echo -n "${1:0:1}" + echo -n "${1:1:1}" | tr '0123456789abcdef' '23016745ab89efcd' +} + +interface_linklocal() { + local macaddr="$(ubus call network.device status '{"name": "'"$1"'"}' | jsonfilter -e '@.macaddr')" + local oldIFS="$IFS"; IFS=':'; set -- $macaddr; IFS="$oldIFS" + + echo "fe80::$(xor2 "$1")$2:$3ff:fe$4:$5$6" +} + +proto_gluon_wired_setup() { + local config="$1" + local ifname="$2" + + local meshif="$config" + + local vxlan="$(lua -e 'print(require("gluon.site").mesh.vxlan(true))')" + + local transitive index + json_get_vars transitive index + + proto_init_update "$ifname" 1 + proto_send_update "$config" + + if [ "$vxlan" = 'true' ]; then + meshif="vx_$config" + + json_init + json_add_string name "$meshif" + [ -n "$index" ] && json_add_string macaddr "$(lua -lgluon.util -e "print(gluon.util.generate_mac($index))")" + json_add_string proto 'vxlan6' + json_add_string tunlink "$config" + json_add_string ip6addr "$(interface_linklocal "$ifname")" + json_add_string peer6addr 'ff02::15c' + json_add_int vid "$(lua -lgluon.util -e 'print(tonumber(gluon.util.domain_seed_bytes("gluon-mesh-vxlan", 3), 16))')" + json_add_boolean rxcsum '0' + json_add_boolean txcsum '0' + json_close_object + ubus call network add_dynamic "$(json_dump)" + fi + + json_init + json_add_string name "${config}_mesh" + json_add_string ifname "@${meshif}" + json_add_string proto 'gluon_mesh' + json_add_boolean fixed_mtu 1 + [ -n "$transitive" ] && json_add_boolean transitive "$transitive" + json_close_object + ubus call network add_dynamic "$(json_dump)" +} + +proto_gluon_wired_teardown() { + local config="$1" + + proto_init_update "*" 0 + proto_send_update "$config" +} + +add_protocol gluon_wired diff --git a/package/gluon-core/files/usr/bin/gluon-list-mesh-interfaces b/package/gluon-core/files/usr/bin/gluon-list-mesh-interfaces new file mode 100755 index 00000000..9b450f90 --- /dev/null +++ b/package/gluon-core/files/usr/bin/gluon-list-mesh-interfaces @@ -0,0 +1,2 @@ +#!/bin/sh +ubus call network.interface dump | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device" diff --git a/package/gluon-core/files/usr/bin/gluon-reconfigure b/package/gluon-core/files/usr/bin/gluon-reconfigure new file mode 100755 index 00000000..6e7add98 --- /dev/null +++ b/package/gluon-core/files/usr/bin/gluon-reconfigure @@ -0,0 +1,17 @@ +#!/bin/sh + +cd /lib/gluon/upgrade || exit 1 + +err=0 + +for script in *; do + echo "Configuring: ${script}" + ./"$script" || err=1 +done + +if [ $err -eq 1 ]; then + echo 'One or more upgrade scripts failed. Please review the above error messages.' + exit 1 +fi + +exit 0 diff --git a/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua b/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua deleted file mode 100644 index 4c0a2d22..00000000 --- a/package/gluon-core/files/usr/lib/lua/gluon/site_config.lua +++ /dev/null @@ -1,27 +0,0 @@ -local function get_site_config() - local config = '/lib/gluon/site.json' - - local json = require 'luci.jsonc' - local ltn12 = require 'luci.ltn12' - - local file = assert(io.open(config)) - - local decoder = json.new() - ltn12.pump.all(ltn12.source.file(file), decoder:sink()) - - file:close() - - return assert(decoder:get()) -end - -local setmetatable = setmetatable - -module 'gluon.site_config' - -setmetatable(_M, - { - __index = get_site_config(), - } -) - -return _M diff --git a/package/gluon-core/files/usr/lib/lua/gluon/sysctl.lua b/package/gluon-core/files/usr/lib/lua/gluon/sysctl.lua deleted file mode 100644 index 44b0c217..00000000 --- a/package/gluon-core/files/usr/lib/lua/gluon/sysctl.lua +++ /dev/null @@ -1,8 +0,0 @@ -local util = require 'gluon.util' - - -module 'gluon.sysctl' - -function set(name, value) - util.replace_prefix('/etc/sysctl.conf', name .. '=', name .. '=' .. value .. '\n') -end diff --git a/package/gluon-core/files/usr/lib/lua/gluon/users.lua b/package/gluon-core/files/usr/lib/lua/gluon/users.lua deleted file mode 100644 index 8e618d88..00000000 --- a/package/gluon-core/files/usr/lib/lua/gluon/users.lua +++ /dev/null @@ -1,33 +0,0 @@ -local util = require 'gluon.util' - -local os = os -local string = string - - -module 'gluon.users' - -function add_user(username, uid, gid) - util.lock('/var/lock/passwd') - util.replace_prefix('/etc/passwd', username .. ':', string.format('%s:*:%u:%u::/var:/bin/false\n', username, uid, gid)) - util.replace_prefix('/etc/shadow', username .. ':', string.format('%s:*:0:0:99999:7:::\n', username)) - util.unlock('/var/lock/passwd') -end - -function remove_user(username) - util.lock('/var/lock/passwd') - util.replace_prefix('/etc/passwd', username .. ':') - util.replace_prefix('/etc/shadow', username .. ':') - util.unlock('/var/lock/passwd') -end - -function add_group(groupname, gid) - util.lock('/var/lock/group') - util.replace_prefix('/etc/group', groupname .. ':', string.format('%s:x:%u:\n', groupname, gid)) - util.unlock('/var/lock/group') -end - -function remove_group(groupname) - util.lock('/var/lock/group') - util.replace_prefix('/etc/group', groupname .. ':') - util.unlock('/var/lock/group') -end diff --git a/package/gluon-core/files/usr/lib/lua/gluon/util.lua b/package/gluon-core/files/usr/lib/lua/gluon/util.lua deleted file mode 100644 index 72b6220d..00000000 --- a/package/gluon-core/files/usr/lib/lua/gluon/util.lua +++ /dev/null @@ -1,129 +0,0 @@ --- Writes all lines from the file input to the file output except those starting with prefix --- Doesn't close the output file, but returns the file object -local function do_filter_prefix(input, output, prefix) - local f = io.open(output, 'w+') - local l = prefix:len() - - for line in io.lines(input) do - if line:sub(1, l) ~= prefix then - f:write(line, '\n') - end - end - - return f -end - - -local function escape_args(ret, arg0, ...) - if not arg0 then - return ret - end - - return escape_args(ret .. "'" .. string.gsub(arg0, "'", "'\\''") .. "' ", ...) -end - - -local os = os -local string = string -local tonumber = tonumber -local ipairs = ipairs -local table = table - -local nixio = require 'nixio' -local hash = require 'hash' -local sysconfig = require 'gluon.sysconfig' -local site = require 'gluon.site_config' -local uci = require('luci.model.uci').cursor() - - -module 'gluon.util' - -function exec(...) - return os.execute(escape_args('', 'exec', ...)) -end - --- Removes all lines starting with a prefix from a file, optionally adding a new one -function replace_prefix(file, prefix, add) - local tmp = file .. '.tmp' - local f = do_filter_prefix(file, tmp, prefix) - if add then - f:write(add) - end - f:close() - os.rename(tmp, file) -end - -function readline(fd) - local line = fd:read('*l') - fd:close() - return line -end - -function lock(file) - exec('lock', file) -end - -function unlock(file) - exec('lock', '-u', file) -end - -function node_id() - return string.gsub(sysconfig.primary_mac, ':', '') -end - --- Generates a (hopefully) unique MAC address --- The parameter defines the ID to add to the mac addr --- --- IDs defined so far: --- 0: client0; mesh-vpn --- 1: mesh0 --- 2: ibss0 --- 3: client1; mesh-on-wan --- 4: mesh1 --- 5: ibss1 --- 6: mesh-on-lan --- 7: unused -function generate_mac(i) - if i > 7 or i < 0 then return nil end -- max allowed id (0b111) - - local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12) - local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)') - - m1 = tonumber(m1, 16) - m6 = tonumber(m6, 16) - - m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit - m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit - - -- It's necessary that the first 45 bits of the mac do - -- not vary on a single hardware interface, since some chips are using - -- a hardware mac filter. (e.g 'ramips-rt305x') - - m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) - m6 = m6 + i -- add virtual interface id - - return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) -end - --- Iterate over all radios defined in UCI calling --- f(radio, index, site.wifiX) for each radio found while passing --- site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones. -function iterate_radios(f) - local radios = {} - - uci:foreach('wireless', 'wifi-device', - function(s) - table.insert(radios, s['.name']) - end - ) - - for index, radio in ipairs(radios) do - local hwmode = uci:get('wireless', radio, 'hwmode') - - if hwmode == '11g' or hwmode == '11ng' then - f(radio, index, site.wifi24) - elseif hwmode == '11a' or hwmode == '11na' then - f(radio, index, site.wifi5) - end - end -end diff --git a/package/gluon-core/files/lib/gluon/upgrade/001-upgrade b/package/gluon-core/luasrc/lib/gluon/upgrade/001-upgrade similarity index 100% rename from package/gluon-core/files/lib/gluon/upgrade/001-upgrade rename to package/gluon-core/luasrc/lib/gluon/upgrade/001-upgrade diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/005-site-domain b/package/gluon-core/luasrc/lib/gluon/upgrade/005-site-domain new file mode 100755 index 00000000..04c81292 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/005-site-domain @@ -0,0 +1,27 @@ +#!/usr/bin/lua + +local fs = require 'nixio.fs' + + +if not fs.access('/lib/gluon/domains/') then + return +end + + +local uci = require('simple-uci').cursor() + +local domain = uci:get('gluon', 'core', 'domain') +if domain and not fs.access('/lib/gluon/domains/' .. domain .. '.json') then + io.stderr:write(string.format("Warning: invalid mesh domain '%s' configured, resetting to default...\n", domain)) + domain = nil +end + +if domain then return end + + +-- We can't use gluon.site yet, as it depends on gluon.core.domain to be set +local json = require 'jsonc' +local site = assert(json.load('/lib/gluon/site.json')) + +uci:set('gluon', 'core', 'domain', site.default_domain) +uci:commit('gluon') diff --git a/package/gluon-core/files/lib/gluon/upgrade/010-primary-mac b/package/gluon-core/luasrc/lib/gluon/upgrade/010-primary-mac similarity index 61% rename from package/gluon-core/files/lib/gluon/upgrade/010-primary-mac rename to package/gluon-core/luasrc/lib/gluon/upgrade/010-primary-mac index 144ee700..9ad9b820 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/010-primary-mac +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/010-primary-mac @@ -8,33 +8,43 @@ if sysconfig.primary_mac then end +local util = require 'gluon.util' local platform = require 'gluon.platform' local fs = require 'nixio.fs' -local util = require 'luci.util' local try_files = { '/sys/class/net/eth0/address' } -if not util.contains({'x86', 'brcm2708'}, platform.get_target()) then +if not ( + util.contains({'x86', 'brcm2708'}, platform.get_target()) or + platform.match('ar71xx', 'mikrotik') +) then table.insert(try_files, 1, '/sys/class/ieee80211/phy0/macaddress') end if platform.match('ar71xx', 'generic', {'tl-wdr3600', 'tl-wdr4300'}) then table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress') +elseif platform.match('ramips', 'mt7621', {'dir-860l-b1'}) then + table.insert(try_files, 1, '/sys/class/ieee80211/phy1/macaddress') elseif platform.match('ar71xx', 'generic', {'unifi-outdoor-plus', 'carambola2', + 'a40', 'a60', 'mr600', 'mr600v2', 'mr900', 'mr900v2', - 'mr1750', - 'om2p', 'om2pv2', - 'om2p-hs', 'om2p-hsv2', + 'mr1750', 'mr1750v2', + 'om2p', 'om2pv2', 'om2pv4', + 'om2p-hs', 'om2p-hsv2', 'om2p-hsv3', + 'om2p-hsv4', 'om2p-lc', 'om5p', 'om5p-an', - 'om5p-ac', 'om5p-acv2'}) then + 'om5p-ac', 'om5p-acv2', + 'archer-c7-v4'}) then table.insert(try_files, 1, '/sys/class/net/eth0/address') -elseif platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c7'}) then +elseif platform.match('ar71xx', 'generic', {'archer-c5', 'archer-c58-v1', + 'archer-c59-v1', 'archer-c60-v1', + 'archer-c7'}) then table.insert(try_files, 1, '/sys/class/net/eth1/address') end diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces new file mode 100755 index 00000000..47757699 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces @@ -0,0 +1,64 @@ +#!/usr/bin/lua + +local sysconfig = require 'gluon.sysconfig' + +-- Are we already set up? +if sysconfig.lan_ifname or sysconfig.wan_ifname then + os.exit(0) +end + + +local util = require 'gluon.util' +local platform = require 'gluon.platform' +local site = require 'gluon.site' + +local fs = require 'nixio.fs' +local uci = require('simple-uci').cursor() + + +local function iface_exists(ifaces) + if not ifaces then return nil end + + for iface in ifaces:gmatch('%S+') do + if fs.access('/sys/class/net/' .. iface:gsub('%..*$', '')) then + return ifaces + end + end +end + + +local lan_ifname = iface_exists(uci:get('network', 'lan', 'ifname')) +local wan_ifname = iface_exists(uci:get('network', 'wan', 'ifname')) + +if platform.match('ar71xx', 'generic', { + 'cpe210', + 'cpe510', + 'wbs210', + 'wbs510', + 'airgateway', + 'nanostation-m', + 'nanostation-m-xw', + 'unifi-outdoor-plus', + 'uap-pro', + 'unifiac-pro', +}) then + lan_ifname, wan_ifname = wan_ifname, lan_ifname +end + +if wan_ifname and lan_ifname then + sysconfig.wan_ifname = wan_ifname + sysconfig.lan_ifname = lan_ifname +else + local single_ifname = lan_ifname or wan_ifname + if site.single_as_lan(false) then + sysconfig.lan_ifname = single_ifname + else + sysconfig.wan_ifname = single_ifname + end +end + + +uci:delete('network', 'lan') +uci:delete('network', 'wan') + +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/030-system b/package/gluon-core/luasrc/lib/gluon/upgrade/030-system new file mode 100755 index 00000000..29432e4c --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/030-system @@ -0,0 +1,21 @@ +#!/usr/bin/lua + +local sysconfig = require 'gluon.sysconfig' + +-- Initial +if sysconfig.gluon_version then + os.exit(0) +end + + +local site = require 'gluon.site' +local util = require 'gluon.util' +local uci = require('simple-uci').cursor() +local pretty_hostname = require 'pretty_hostname' + +local system = uci:get_first('system', 'system') + +pretty_hostname.set(uci, util.default_hostname()) +uci:set('system', system, 'timezone', site.timezone()) + +uci:save('system') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/110-network b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network new file mode 100755 index 00000000..79c50d27 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/110-network @@ -0,0 +1,69 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() +local sysconfig = require 'gluon.sysconfig' + + +uci:section('network', 'interface', 'wan', { + ifname = sysconfig.wan_ifname, + type = 'bridge', + igmp_snooping = true, + multicast_querier = false, + peerdns = false, + auto = true, +}) + +if not uci:get('network', 'wan', 'proto') then + uci:set('network', 'wan', 'proto', 'dhcp') +end + + +uci:section('network', 'interface', 'wan6', { + ifname = 'br-wan', + peerdns = false, + ip6table = 1, + sourcefilter = false, + reqprefix = 'no', +}) + +if not uci:get('network', 'wan6', 'proto') then + uci:set('network', 'wan6', 'proto', 'dhcpv6') +end + + +uci:section('network', 'rule6', 'wan6_lookup', { + mark = '0x01/0x01', + lookup = 1, +}) + +uci:section('network', 'route6', 'wan6_unreachable', { + type = 'unreachable', + interface = 'loopback', + target = '::/0', + gateway = '::', + table = 1, + metric = 65535, +}) + +uci:save('network') + + +uci:section('firewall', 'rule', 'wan_igmp', { + name = 'Allow-IGMP', + src = 'wan', + proto = 'igmp', + family = 'ipv4', + target = 'ACCEPT', +}) + +uci:section('firewall', 'rule', 'wan_mld', { + name = 'Allow-MLD', + src = 'wan', + proto = 'icmp', + src_ip = 'fe80::/10', + icmp_type = { '130/0', '131/0', '132/0', '143/0', }, + family = 'ipv6', + target = 'ACCEPT', +}) + +uci:save('firewall') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/120-ntp-servers b/package/gluon-core/luasrc/lib/gluon/upgrade/120-ntp-servers new file mode 100755 index 00000000..e3718b68 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/120-ntp-servers @@ -0,0 +1,13 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' + +if #site.ntp_servers({}) == 0 then + os.exit(0) +end + + +local uci = require('simple-uci').cursor() +uci:delete('system', 'ntp', 'server') +uci:set_list('system', 'ntp', 'server', site.ntp_servers({})) +uci:save('system') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules b/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules new file mode 100755 index 00000000..ae374e33 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/140-firewall-rules @@ -0,0 +1,102 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + + +local defaults = uci:get_first('firewall', 'defaults') +uci:set('firewall', defaults, 'input', 'REJECT') + + +local function reject_input_on_wan(zone) + if zone.name == 'wan' then + uci:set('firewall', zone['.name'], 'input', 'REJECT') + uci:set('firewall', zone['.name'], 'conntrack', true) + end + + return true +end + +uci:foreach('firewall', 'zone', reject_input_on_wan) + +for _, zone in ipairs({'mesh', 'local_client', 'wired_mesh'}) do + -- Other packages assign interfaces to these zones + uci:section('firewall', 'zone', zone, { + name = zone, + network = {}, + input = 'REJECT', + output = 'ACCEPT', + forward = 'REJECT', + }) + + uci:section('firewall', 'rule', zone .. '_ICMPv6_in', { + src = zone, + proto = 'icmp', + icmp_type = { + 'echo-request', + 'echo-reply', + 'destination-unreachable', + 'packet-too-big', + 'time-exceeded', + 'bad-header', + 'unknown-header-type', + 'router-solicitation', + 'neighbour-solicitation', + 'router-advertisement', + 'neighbour-advertisement', + '130/0', -- Multicast Listener Query + '131/0', -- Multicast Listener Report + '132/0', -- Multicast Listener Done + '143/0', -- MLDv2 + }, + limit = '1000/sec', + family = 'ipv6', + target = 'ACCEPT', + }) + + -- Can be removed soon: was never in a release + uci:delete('firewall', zone .. '_ICMPv6_out') +end + +uci:section('firewall', 'rule', 'local_client_ICMPv4_in', { + src = 'local_client', + proto = 'icmp', + icmp_type = { + 'echo-request', + }, + family = 'ipv4', + target = 'ACCEPT', +}) + + +-- allow inbound SSH from anywhere +for _, zone in ipairs({ 'wan', 'local_client', 'mesh' }) do + uci:section('firewall', 'rule', zone .. '_ssh', { + name = zone .. '_ssh', + src = zone, + dest_port = '22', + proto = 'tcp', + target = 'ACCEPT', + }) +end + + +-- We can't put mesh_wan into this zone, as mesh_wan is the same +-- interface as wan, which has its own zone +uci:set('firewall', 'wired_mesh', 'network', {'mesh_lan'}) + +-- VXLAN for wired meshing +for _, zone in ipairs({'wired_mesh', 'wan'}) do + uci:section('firewall', 'rule', zone .. '_vxlan', { + name = zone .. '_vxlan', + src = zone, + family = 'ipv6', + src_ip = 'fe80::/64', + proto = 'udp', + dest_port = '4789', + target = 'ACCEPT', + }) + uci:reorder('firewall', zone .. '_vxlan', 0) +end + + +uci:save('firewall') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/150-poe-passthrough b/package/gluon-core/luasrc/lib/gluon/upgrade/150-poe-passthrough new file mode 100755 index 00000000..e8737259 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/150-poe-passthrough @@ -0,0 +1,16 @@ +#!/usr/bin/lua + +local sysconfig = require 'gluon.sysconfig' +local site = require 'gluon.site' + +if sysconfig.gluon_version or not site.poe_passthrough(false) then + os.exit(0) +end + + +local uci = require('simple-uci').cursor() + +if uci:get('system', 'poe_passthrough') then + uci:set('system', 'poe_passthrough', 'value', true) + uci:save('system') +end diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless new file mode 100755 index 00000000..72abfde4 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/200-wireless @@ -0,0 +1,210 @@ +#!/usr/bin/lua + +local util = require 'gluon.util' +local site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' +local iwinfo = require 'iwinfo' + +local uci = require('simple-uci').cursor() + +-- Initial +if not sysconfig.gluon_version then + uci:delete_all('wireless', 'wifi-iface') +end + +local function get_channel(radio, config) + local channel + if uci:get_first('gluon-core', 'wireless', 'preserve_channels') then + channel = radio.channel + end + + return channel or config.channel() +end + +local function get_htmode(radio) + local phy = util.find_phy(radio) + if iwinfo.nl80211.hwmodelist(phy).ac then + return 'VHT20' + else + return 'HT20' + end +end + +local function is_disabled(name) + if uci:get('wireless', name) then + return uci:get_bool('wireless', name, 'disabled') + else + return false + end +end + +-- Returns the first argument that is not nil; don't call without any non-nil arguments! +local function first_non_nil(first, ...) + if first ~= nil then + return first + else + return first_non_nil(...) + end +end + + +local function configure_ibss(config, radio, index, suffix, disabled) + local radio_name = radio['.name'] + local name = 'ibss_' .. radio_name + + uci:delete('network', name) + uci:delete('network', name .. '_vlan') + uci:delete('wireless', name) + + if not config then + return + end + + local macaddr = util.get_wlan_mac(uci, radio, index, 3) + if not macaddr then + return + end + + if config.vlan then + uci:section('network', 'interface', name, { + proto = 'none', + }) + + uci:section('network', 'interface', name .. '_vlan', { + ifname = '@' .. name .. '.' .. config.vlan, + proto = 'gluon_mesh', + }) + else + uci:section('network', 'interface', name, { + proto = 'gluon_mesh', + }) + end + + uci:section('wireless', 'wifi-iface', name, { + device = radio_name, + network = name, + mode = 'adhoc', + ssid = config.ssid, + bssid = config.bssid, + macaddr = macaddr, + mcast_rate = config.mcast_rate, + ifname = suffix and 'ibss' .. suffix, + disabled = disabled, + }) +end + +local function configure_mesh(config, radio, index, suffix, disabled) + local radio_name = radio['.name'] + local name = 'mesh_' .. radio_name + + local macfilter = uci:get('wireless', name, 'macfilter') + local maclist = uci:get('wireless', name, 'maclist') + + uci:delete('network', name) + uci:delete('network', name .. '_vlan') + uci:delete('wireless', name) + + if not config then + return + end + + local macaddr = util.get_wlan_mac(uci, radio, index, 2) + if not macaddr then + return + end + + uci:section('network', 'interface', name, { + proto = 'gluon_mesh', + }) + + uci:section('wireless', 'wifi-iface', name, { + device = radio_name, + network = name, + mode = 'mesh', + mesh_id = config.id, + mesh_fwding = false, + macaddr = macaddr, + mcast_rate = config.mcast_rate, + ifname = suffix and 'mesh' .. suffix, + disabled = disabled, + macfilter = macfilter, + maclist = maclist, + }) +end + +local function fixup_wan(radio, index) + local radio_name = radio['.name'] + local name = 'wan_' .. radio_name + + if not uci:get('wireless', name) then + return + end + + local macaddr = util.get_wlan_mac(uci, radio, index, 4) + if not macaddr then + return + end + + uci:set('wireless', name, 'macaddr', macaddr) +end + +util.foreach_radio(uci, function(radio, index, config) + local radio_name = radio['.name'] + + if not config() then + uci:set('wireless', radio_name, 'disabled', true) + return + end + + local suffix = radio_name:match('^radio(%d+)$') + if not suffix then + return + end + + local channel = get_channel(radio, config) + local htmode = get_htmode(radio) + + uci:delete('wireless', radio_name, 'disabled') + + uci:set('wireless', radio_name, 'channel', channel) + uci:set('wireless', radio_name, 'htmode', htmode) + uci:set('wireless', radio_name, 'country', site.regdom()) + + uci:set_list('wireless', radio_name, 'supported_rates', config.supported_rates()) + uci:set_list('wireless', radio_name, 'basic_rate', config.basic_rate()) + + + local ibss_disabled = is_disabled('ibss_' .. radio_name) + local mesh_disabled = is_disabled('mesh_' .. radio_name) + + configure_ibss(config.ibss(), radio, index, suffix, + first_non_nil( + ibss_disabled, + mesh_disabled, + config.ibss.disabled(false) + ) + ) + configure_mesh(config.mesh(), radio, index, suffix, + first_non_nil( + mesh_disabled, + ibss_disabled, + config.mesh.disabled(false) + ) + ) + + fixup_wan(radio, index) +end) + + +if uci:get('system', 'rssid_wlan0') then + if uci:get('wireless', 'mesh_radio0') then + uci:set('system', 'rssid_wlan0', 'dev', 'mesh0') + else + uci:set('system', 'rssid_wlan0', 'dev', 'ibss0') + end + + uci:save('system') +end + +uci:save('wireless') +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan b/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan new file mode 100755 index 00000000..e8600ee8 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/210-interface-wan @@ -0,0 +1,30 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + +local old_proto = uci:get('network', 'mesh_wan', 'proto') + +uci:section('network', 'interface', 'mesh_wan', { + ifname = 'br-wan', + proto = 'gluon_wired', + index = 0, +}) + +local enable = site.mesh_on_wan(false) +local old_auto = uci:get('network', 'mesh_wan', 'auto') +local old_disabled = uci:get('network', 'mesh_wan', 'disabled') +if old_auto ~= nil or old_disabled ~= nil then + enable = old_auto ~= '0' and old_disabled ~= '1' +end +uci:set('network', 'mesh_wan', 'disabled', not enable) + +if uci:get('network', 'mesh_wan', 'transitive') == nil then + uci:set('network', 'mesh_wan', 'transitive', true) +end + +uci:delete('network', 'mesh_wan', 'auto') +uci:delete('network', 'mesh_wan', 'fixed_mtu') +uci:delete('network', 'mesh_wan', 'legacy') + +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan b/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan new file mode 100755 index 00000000..a6fb4127 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/220-interface-lan @@ -0,0 +1,58 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local util = require 'gluon.util' +local sysconfig = require 'gluon.sysconfig' + +local uci = require('simple-uci').cursor() + +if not sysconfig.lan_ifname then + os.exit(0) +end + +local old_proto = uci:get('network', 'mesh_lan', 'proto') + +uci:section('network', 'interface', 'mesh_lan', { + ifname = sysconfig.lan_ifname, + igmp_snooping = false, + proto = 'gluon_wired', + index = 4, +}) + +if sysconfig.lan_ifname:match(' ') then + uci:set('network', 'mesh_lan', 'type', 'bridge') +else + uci:delete('network', 'mesh_lan', 'type') +end + +local enable = site.mesh_on_lan(false) +local old_auto = uci:get('network', 'mesh_lan', 'auto') +local old_disabled = uci:get('network', 'mesh_lan', 'disabled') +if old_auto ~= nil or old_disabled ~= nil then + enable = old_auto ~= '0' and old_disabled ~= '1' +end + +if enable then + local interfaces = uci:get_list('network', 'client', 'ifname') + + if interfaces then + for lanif in sysconfig.lan_ifname:gmatch('%S+') do + if util.contains(interfaces, lanif) then + enable = false + break + end + end + end +end + +uci:set('network', 'mesh_lan', 'disabled', not enable) + +if uci:get('network', 'mesh_lan', 'transitive') == nil then + uci:set('network', 'mesh_lan', 'transitive', true) +end + +uci:delete('network', 'mesh_lan', 'auto') +uci:delete('network', 'mesh_lan', 'fixed_mtu') +uci:delete('network', 'mesh_lan', 'legacy') + +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/500-opkg b/package/gluon-core/luasrc/lib/gluon/upgrade/500-opkg new file mode 100755 index 00000000..81e437b5 --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/500-opkg @@ -0,0 +1,75 @@ +#!/usr/bin/lua + +local fs = require 'nixio.fs' + +if not fs.access('/etc/opkg/distfeeds.conf') then + os.exit(0) +end + + +local site = require 'gluon.site' +local util = require 'gluon.util' + + +local subst = {} + + +local f = io.popen('. /etc/openwrt_release; echo "$DISTRIB_CODENAME"; echo "$DISTRIB_RELEASE"; echo "$DISTRIB_TARGET"; echo "$DISTRIB_ARCH"') +subst['%%n'] = f:read() +subst['%%v'] = f:read():gsub('-SNAPSHOT', '') +subst['%%S'] = f:read() +subst['%%A'] = f:read() +f:close() + +subst['%%GS'] = site.site_code() +subst['%%GV'] = util.trim(fs.readfile('/lib/gluon/gluon-version')) +subst['%%GR'] = util.trim(fs.readfile('/lib/gluon/release')) + +local prefix = subst['%%n'] .. '_' + + +local function replace_patterns(url) + for k, v in pairs(subst) do + url = url:gsub(k, v) + end + + return url +end + + +local lede = site.opkg.lede() +local extra = site.opkg.extra({}) + + +local distfeeds = {} +for line in io.lines('/etc/opkg/distfeeds.conf') do + table.insert(distfeeds, line) +end + +local f = io.open('/etc/opkg/distfeeds.conf', 'w') + +for _, line in ipairs(distfeeds) do + local name = line:match('^src/gz%s' .. prefix .. '(%S+)%s') + if name == 'core' then + f:write('# ' .. line .. '\n') + elseif name and lede then + f:write(string.format('src/gz %s %s/%s\n', prefix .. name, replace_patterns(lede), name)) + else + f:write(line .. '\n') + end +end + +f:close() + +if next(extra) then + local f = io.open('/etc/opkg/gluon.conf', 'w') + + for k, v in pairs(extra) do + f:write(string.format('src/gz %s %s\n', k, replace_patterns(v))) + end + + f:close() + +else + os.remove('/etc/opkg/gluon.conf') +end diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/800-migrate-batadv b/package/gluon-core/luasrc/lib/gluon/upgrade/800-migrate-batadv new file mode 100755 index 00000000..ddd03c0a --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/800-migrate-batadv @@ -0,0 +1,24 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + +local function migrate_iface(iface) + if iface.proto ~= 'batadv' or iface.mesh ~= 'bat0' then + return + end + + local s = iface['.name'] + + uci:set('network', s, 'proto', 'gluon_mesh') + uci:set('network', s, 'fixed_mtu', true) + + if iface.mesh_no_rebroadcast then + uci:set('network', s, 'transitive', iface.mesh_no_rebroadcast) + end + + uci:delete('network', s, 'mesh') + uci:delete('network', s, 'mesh_no_rebroadcast') +end + +uci:foreach('network', 'interface', migrate_iface) +uci:save('network') diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config new file mode 100755 index 00000000..18b44d3f --- /dev/null +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/820-dns-config @@ -0,0 +1,46 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + +local dns = site.dns({}) +local next_node = site.next_node({}) + +local dnsmasq = uci:get_first("dhcp", "dnsmasq") + +uci:set('dhcp', dnsmasq, 'localise_queries', true) +uci:set('dhcp', dnsmasq, 'localservice', false) + +uci:set('dhcp', dnsmasq, 'server', dns.servers) +uci:delete('dhcp', dnsmasq, 'cachesize') + +uci:delete('firewall', 'client_dns') +if dns.servers then + -- allow inbound traffic for dns from client zone + uci:section('firewall', 'rule', 'client_dns', { + src = 'local_client', + dest_port = '53', + proto = 'tcpudp', + target = 'ACCEPT', + }) +end + +local function set_dns_record(name, ip, sectionname) + if not ip then return end + uci:section('dhcp', 'domain', sectionname, { + name = name, + ip = ip, + }) +end + +uci:delete_all('dhcp', 'domain', function(s) + return (s['.name'] and string.match(s['.name'], "^nextnode[46]")) +end) + +for i, name in ipairs(next_node.name or {}) do + set_dns_record(name, next_node.ip4, 'nextnode4_' .. i) + set_dns_record(name, next_node.ip6, 'nextnode6_' .. i) +end + +uci:save('dhcp') +uci:save('firewall') diff --git a/package/gluon-core/files/lib/gluon/upgrade/999-version b/package/gluon-core/luasrc/lib/gluon/upgrade/999-version similarity index 89% rename from package/gluon-core/files/lib/gluon/upgrade/999-version rename to package/gluon-core/luasrc/lib/gluon/upgrade/999-version index 9731692e..608545b7 100755 --- a/package/gluon-core/files/lib/gluon/upgrade/999-version +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/999-version @@ -3,7 +3,7 @@ local sysconfig = require 'gluon.sysconfig' local fs = require 'nixio.fs' -local util = require 'luci.util' +local util = require 'gluon.util' -- Save the Gluon version in the sysconfig so we know which version we diff --git a/package/gluon-core/luasrc/usr/bin/gluon-show-site b/package/gluon-core/luasrc/usr/bin/gluon-show-site new file mode 100755 index 00000000..df3b56fa --- /dev/null +++ b/package/gluon-core/luasrc/usr/bin/gluon-show-site @@ -0,0 +1,6 @@ +#!/usr/bin/lua + +local json = require 'jsonc' +local site = require 'gluon.site' + +print(json.stringify(site(), true)) diff --git a/package/gluon-core/files/usr/lib/lua/gluon/platform.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua similarity index 79% rename from package/gluon-core/files/usr/lib/lua/gluon/platform.lua rename to package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua index 3d56f081..5b4f559a 100644 --- a/package/gluon-core/files/usr/lib/lua/gluon/platform.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua @@ -1,5 +1,5 @@ local platform_info = require 'platform_info' -local util = require 'luci.util' +local util = require 'gluon.util' local setmetatable = setmetatable @@ -21,11 +21,9 @@ function match(target, subtarget, boards) return false end - if not util.contains(boards, get_board_name()) then + if boards and not util.contains(boards, get_board_name()) then return false end return true end - - diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/site_config.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/site_config.lua new file mode 100644 index 00000000..533fdf71 --- /dev/null +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/site_config.lua @@ -0,0 +1,11 @@ +local site = require 'gluon.site' + +local setmetatable = setmetatable + +module 'gluon.site_config' + +setmetatable(_M, { + __index = site(), +}) + +return _M diff --git a/package/gluon-core/files/usr/lib/lua/gluon/sysconfig.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua similarity index 96% rename from package/gluon-core/files/usr/lib/lua/gluon/sysconfig.lua rename to package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua index ff61f05b..fabfe05f 100644 --- a/package/gluon-core/files/usr/lib/lua/gluon/sysconfig.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/sysconfig.lua @@ -13,7 +13,7 @@ end local function set(_, name, val) if val then local f = io.open(sysconfigdir .. name, 'w+') - f:write(val) + f:write(val, '\n') f:close() else os.remove(sysconfigdir .. name) diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/users.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/users.lua new file mode 100644 index 00000000..1dbc3728 --- /dev/null +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/users.lua @@ -0,0 +1,20 @@ +local util = require 'gluon.util' + +local os = os +local string = string + + +module 'gluon.users' + +function remove_user(username) + os.execute('exec lock /var/lock/passwd') + util.replace_prefix('/etc/passwd', username .. ':') + util.replace_prefix('/etc/shadow', username .. ':') + os.execute('exec lock -u /var/lock/passwd') +end + +function remove_group(groupname) + os.execute('exec lock /var/lock/group') + util.replace_prefix('/etc/group', groupname .. ':') + os.execute('exec lock -u /var/lock/group') +end diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua new file mode 100644 index 00000000..1becb9c1 --- /dev/null +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -0,0 +1,246 @@ +-- Writes all lines from the file input to the file output except those starting with prefix +-- Doesn't close the output file, but returns the file object +local function do_filter_prefix(input, output, prefix) + local f = io.open(output, 'w+') + local l = prefix:len() + + for line in io.lines(input) do + if line:sub(1, l) ~= prefix then + f:write(line, '\n') + end + end + + return f +end + + +local io = io +local os = os +local string = string +local tonumber = tonumber +local ipairs = ipairs +local pairs = pairs +local table = table + +local nixio = require 'nixio' +local hash = require 'hash' +local sysconfig = require 'gluon.sysconfig' +local site = require 'gluon.site' +local fs = require 'nixio.fs' + + +module 'gluon.util' + +function trim(str) + return str:gsub("^%s*(.-)%s*$", "%1") +end + +function contains(table, value) + for k, v in pairs(table) do + if value == v then + return k + end + end + return false +end + +function add_to_set(t, itm) + for _,v in ipairs(t) do + if v == itm then return false end + end + table.insert(t, itm) + return true +end + +function remove_from_set(t, itm) + local i = 1 + local changed = false + while i <= #t do + if t[i] == itm then + table.remove(t, i) + changed = true + else + i = i + 1 + end + end + return changed +end + +-- Removes all lines starting with a prefix from a file, optionally adding a new one +function replace_prefix(file, prefix, add) + local tmp = file .. '.tmp' + local f = do_filter_prefix(file, tmp, prefix) + if add then + f:write(add) + end + f:close() + os.rename(tmp, file) +end + +function readline(fd) + local line = fd:read('*l') + fd:close() + return line +end + +function exec(command) + local pp = io.popen(command) + local data = pp:read("*a") + pp:close() + + return data +end + +function node_id() + return string.gsub(sysconfig.primary_mac, ':', '') +end + +function default_hostname() + return site.hostname_prefix('') .. node_id() +end + +function domain_seed_bytes(key, length) + local ret = '' + local v = '' + local i = 0 + + -- Inspired by HKDF key expansion, but much simpler, as we don't need + -- cryptographic strength + while ret:len() < 2*length do + i = i + 1 + v = hash.md5(v .. key .. site.domain_seed():lower() .. i) + ret = ret .. v + end + + return ret:sub(0, 2*length) +end + +function get_mesh_devices(uconn) + local dump = uconn:call("network.interface", "dump", {}) + local devices = {} + for _, interface in ipairs(dump.interface) do + if ( (interface.proto == "gluon_mesh") and interface.up ) then + table.insert(devices, interface.device) + end + end + return devices +end + +local function find_phy_by_path(path) + for phy in fs.glob('/sys/devices/' .. path .. '/ieee80211/phy*') do + return phy:match('([^/]+)$') + end + + for phy in fs.glob('/sys/devices/platform/' .. path .. '/ieee80211/phy*') do + return phy:match('([^/]+)$') + end +end + +local function find_phy_by_macaddr(macaddr) + local addr = macaddr:lower() + for file in fs.glob('/sys/class/ieee80211/*/macaddress') do + if trim(fs.readfile(file)) == addr then + return file:match('([^/]+)/macaddress$') + end + end +end + +function find_phy(config) + if not config or config.type ~= 'mac80211' then + return nil + elseif config.path then + return find_phy_by_path(config.path) + elseif config.macaddr then + return find_phy_by_macaddr(config.macaddr) + else + return nil + end +end + +local function get_addresses(uci, radio) + local phy = find_phy(radio) + if not phy then + return function() end + end + + return io.lines('/sys/class/ieee80211/' .. phy .. '/addresses') +end + +-- Generates a (hopefully) unique MAC address +-- The parameter defines the ID to add to the MAC address +-- +-- IDs defined so far: +-- 0: client0; WAN +-- 1: mesh0 +-- 2: ibss0 +-- 3: wan_radio0 (private WLAN); batman-adv primary address +-- 4: client1; LAN +-- 5: mesh1 +-- 6: ibss1 +-- 7: wan_radio1 (private WLAN); mesh VPN +function generate_mac(i) + if i > 7 or i < 0 then return nil end -- max allowed id (0b111) + + local hashed = string.sub(hash.md5(sysconfig.primary_mac), 0, 12) + local m1, m2, m3, m4, m5, m6 = string.match(hashed, '(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)') + + m1 = tonumber(m1, 16) + m6 = tonumber(m6, 16) + + m1 = nixio.bit.bor(m1, 0x02) -- set locally administered bit + m1 = nixio.bit.band(m1, 0xFE) -- unset the multicast bit + + -- It's necessary that the first 45 bits of the MAC address don't + -- vary on a single hardware interface, since some chips are using + -- a hardware MAC filter. (e.g 'rt305x') + + m6 = nixio.bit.band(m6, 0xF8) -- zero the last three bits (space needed for counting) + m6 = m6 + i -- add virtual interface id + + return string.format('%02x:%s:%s:%s:%s:%02x', m1, m2, m3, m4, m5, m6) +end + +local function get_wlan_mac_from_driver(uci, radio, vif) + local primary = sysconfig.primary_mac:lower() + + local i = 1 + for addr in get_addresses(uci, radio) do + if addr:lower() ~= primary then + if i == vif then + return addr + end + + i = i + 1 + end + end +end + +function get_wlan_mac(uci, radio, index, vif) + local addr = get_wlan_mac_from_driver(uci, radio, vif) + if addr then + return addr + end + + return generate_mac(4*(index-1) + (vif-1)) +end + +-- Iterate over all radios defined in UCI calling +-- f(radio, index, site.wifiX) for each radio found while passing +-- site.wifi24 for 2.4 GHz devices and site.wifi5 for 5 GHz ones. +function foreach_radio(uci, f) + local radios = {} + + uci:foreach('wireless', 'wifi-device', function(radio) + table.insert(radios, radio) + end) + + for index, radio in ipairs(radios) do + local hwmode = radio.hwmode + + if hwmode == '11g' or hwmode == '11ng' then + f(radio, index, site.wifi24) + elseif hwmode == '11a' or hwmode == '11na' then + f(radio, index, site.wifi5) + end + end +end diff --git a/package/gluon-core/src/CMakeLists.txt b/package/gluon-core/src/CMakeLists.txt new file mode 100644 index 00000000..aee77452 --- /dev/null +++ b/package/gluon-core/src/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.0) + +project(gluon-core C) + +add_library(site MODULE site.c) +set_property(TARGET site PROPERTY PREFIX "") +set_property(TARGET site PROPERTY COMPILE_FLAGS "-Wall -std=c99") +target_link_libraries(site gluonutil lua lua-jsonc) + +install(TARGETS site + LIBRARY DESTINATION lib/lua/gluon +) diff --git a/package/gluon-core/src/site.c b/package/gluon-core/src/site.c new file mode 100644 index 00000000..971d44cf --- /dev/null +++ b/package/gluon-core/src/site.c @@ -0,0 +1,113 @@ +#include "libgluonutil.h" +#include "lua-jsonc.h" + +#include +#include +#include + + +#define UDATA "gluon.site" + + +static struct json_object * gluon_site_udata(lua_State *L, int narg) { + return *(struct json_object **)luaL_checkudata(L, narg, UDATA); +} + +static void gluon_site_push_none(lua_State *L) { + lua_pushlightuserdata(L, gluon_site_push_none); + lua_rawget(L, LUA_REGISTRYINDEX); +} + +static void gluon_site_do_wrap(lua_State *L, struct json_object *obj) { + struct json_object **objp = lua_newuserdata(L, sizeof(struct json_object *)); + *objp = json_object_get(obj); + luaL_getmetatable(L, UDATA); + lua_setmetatable(L, -2); +} + +static void gluon_site_wrap(lua_State *L, struct json_object *obj) { + if (obj) + gluon_site_do_wrap(L, obj); + else + gluon_site_push_none(L); +} + + +static int gluon_site_index(lua_State *L) { + struct json_object *obj = gluon_site_udata(L, 1); + const char *key; + lua_Number lua_index; + size_t index; + struct json_object *v = NULL; + + switch (json_object_get_type(obj)) { + case json_type_object: + key = lua_tostring(L, 2); + if (key) + json_object_object_get_ex(obj, key, &v); + break; + + case json_type_array: + index = lua_index = lua_tonumber(L, 2); + if (lua_index == (lua_Number)index && index >= 1) + v = json_object_array_get_idx(obj, index-1); + break; + + case json_type_string: + case json_type_null: + break; + + case json_type_boolean: + case json_type_int: + case json_type_double: + luaL_error(L, "attempt to index a number or boolean value"); + __builtin_unreachable(); + } + + gluon_site_wrap(L, v); + return 1; +} + +static int gluon_site_call(lua_State *L) { + struct json_object *obj = gluon_site_udata(L, 1); + + if (obj) { + lua_jsonc_push_json(L, obj); + } else { + if (lua_isnone(L, 2)) + lua_pushnil(L); + else + lua_pushvalue(L, 2); + } + + return 1; +} + +static int gluon_site_gc(lua_State *L) { + json_object_put(gluon_site_udata(L, 1)); + return 0; +} + +static const luaL_reg R[] = { + { "__index", gluon_site_index }, + { "__call", gluon_site_call }, + { "__gc", gluon_site_gc }, + {} +}; + +int luaopen_gluon_site(lua_State *L) { + luaL_newmetatable(L, UDATA); + luaL_register(L, NULL, R); + lua_pop(L, 1); + + /* Create "none" object */ + lua_pushlightuserdata(L, gluon_site_push_none); + gluon_site_do_wrap(L, NULL); + lua_rawset(L, LUA_REGISTRYINDEX); + + struct json_object *site = gluonutil_load_site_config(); + gluon_site_wrap(L, site); + json_object_put(site); + + return 1; +} diff --git a/package/gluon-ebtables-filter-multicast/Makefile b/package/gluon-ebtables-filter-multicast/Makefile index 93b7f9a5..dc579a2a 100644 --- a/package/gluon-ebtables-filter-multicast/Makefile +++ b/package/gluon-ebtables-filter-multicast/Makefile @@ -4,15 +4,11 @@ PKG_NAME:=gluon-ebtables-filter-multicast PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-ebtables-filter-multicast - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Ebtables filters for multicast packets - DEPENDS:=+gluon-core +gluon-ebtables + DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv endef define Package/gluon-ebtables-filter-multicast/description @@ -23,18 +19,4 @@ define Package/gluon-ebtables-filter-multicast/description Allowed protocols are: DHCP, DHCPv6, ARP, ICMP, ICMPv6, BitTorrent local peer discovery, BABEL and OSPF endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-ebtables-filter-multicast/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-ebtables-filter-multicast)) +$(eval $(call BuildPackageGluon,gluon-ebtables-filter-multicast)) diff --git a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/100-mcast-chain b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/100-mcast-chain deleted file mode 100644 index ec0013a3..00000000 --- a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/100-mcast-chain +++ /dev/null @@ -1 +0,0 @@ -chain('MULTICAST_OUT', 'DROP') diff --git a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-arp b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-arp index 8af1900a..bbc621c6 100644 --- a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-arp +++ b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-arp @@ -1,3 +1,7 @@ +# Bridge loop avoidance +rule 'MULTICAST_OUT -p ARP --arp-opcode Reply --arp-gratuitous --arp-mac-dst ff:43:05:00:00:00/ff:ff:ff:fc:00:00 -j RETURN' +rule 'MULTICAST_OUT -p ARP --arp-opcode Reply --arp-gratuitous --arp-mac-dst ff:43:05:05:00:00/ff:ff:ff:ff:00:00 -j RETURN' + rule 'MULTICAST_OUT -p ARP --arp-opcode Reply --arp-ip-src 0.0.0.0 -j DROP' rule 'MULTICAST_OUT -p ARP --arp-opcode Request --arp-ip-dst 0.0.0.0 -j DROP' rule 'MULTICAST_OUT -p ARP -j RETURN' diff --git a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-icmpv6 b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-icmpv6 index 8d3b7ec2..0058ed86 100644 --- a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-icmpv6 +++ b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/110-mcast-allow-icmpv6 @@ -1,5 +1,3 @@ -rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type echo-request -j DROP' -rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 139 -j DROP' -rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j RETURN' - -rule 'MULTICAST_OUT -p IPv6 --ip6-protocol 0 -j RETURN' -- hop-by-hop +rule 'MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type echo-request -j RETURN' +rule 'MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 139 -j RETURN' -- ICMP Node Information Query +rule 'MULTICAST_OUT_ICMPV6 -j ACCEPT' diff --git a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/300-mcast b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/300-mcast deleted file mode 100644 index c52f122f..00000000 --- a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/300-mcast +++ /dev/null @@ -1,2 +0,0 @@ -rule 'FORWARD --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT' -rule 'OUTPUT --logical-out br-client -o bat0 -d Multicast -j MULTICAST_OUT' diff --git a/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/355-mcast-drop b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/355-mcast-drop new file mode 100644 index 00000000..46ac01a5 --- /dev/null +++ b/package/gluon-ebtables-filter-multicast/files/lib/gluon/ebtables/355-mcast-drop @@ -0,0 +1 @@ +rule ('MULTICAST_OUT -j DROP') diff --git a/package/gluon-ebtables-filter-ra-dhcp/Makefile b/package/gluon-ebtables-filter-ra-dhcp/Makefile index ea6a737d..c650bb89 100644 --- a/package/gluon-ebtables-filter-ra-dhcp/Makefile +++ b/package/gluon-ebtables-filter-ra-dhcp/Makefile @@ -4,15 +4,11 @@ PKG_NAME:=gluon-ebtables-filter-ra-dhcp PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-ebtables-filter-ra-dhcp - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Ebtables filters for Router Advertisement and DHCP packets - DEPENDS:=+gluon-core +gluon-ebtables + DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv endef define Package/gluon-ebtables-filter-ra-dhcp/description @@ -22,18 +18,4 @@ define Package/gluon-ebtables-filter-ra-dhcp/description client network, and not vice-versa. endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-ebtables-filter-ra-dhcp/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-ebtables-filter-ra-dhcp)) +$(eval $(call BuildPackageGluon,gluon-ebtables-filter-ra-dhcp)) diff --git a/package/gluon-ebtables-limit-arp/Makefile b/package/gluon-ebtables-limit-arp/Makefile new file mode 100644 index 00000000..f7bdc48d --- /dev/null +++ b/package/gluon-ebtables-limit-arp/Makefile @@ -0,0 +1,47 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-ebtables-limit-arp +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-ebtables-limit-arp + TITLE:=Ebtables limiter for ARP packets + DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_LIMIT \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_MARK \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_MARK_T +endef + +define Package/gluon-ebtables-limit-arp/description + Gluon community wifi mesh firmware framework: Ebtables rules to + rate-limit ARP packets. + + This package adds filters to limit the amount of ARP Requests + devices are allowed to send into the mesh. The limits are 6 packets + per minute per client device, by MAC address, and 1 per second per + node in total. + + A burst of up to 50 ARP Requests is allowed until the rate-limiting + takes effect (see --limit-burst in the ebtables manpage). + + Furthermore, ARP Requests with a target IP already present in the + batman-adv DAT Cache are excluded from the rate-limiting, + both regarding counting and filtering, as batman-adv will respond + locally with no burden for the mesh. Therefore, this limiter + should not affect popular target IPs, like gateways. + + However it should mitigate the problem of curious people or + smart devices scanning the whole IP range. Which could create + a significant amount of overhead for all participants so far. +endef + +define Package/gluon-ebtables-limit-arp/install + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/usr/sbin/ + $(CP) $(PKG_BUILD_DIR)/gluon-arp-limiter $(1)/usr/sbin/gluon-arp-limiter +endef + +$(eval $(call BuildPackageGluon,gluon-ebtables-limit-arp)) diff --git a/package/gluon-ebtables-limit-arp/files/etc/init.d/gluon-arp-limiter b/package/gluon-ebtables-limit-arp/files/etc/init.d/gluon-arp-limiter new file mode 100755 index 00000000..553b4e20 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/files/etc/init.d/gluon-arp-limiter @@ -0,0 +1,14 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +START=20 +STOP=90 + +start_service() { + procd_open_instance + procd_set_param command /usr/sbin/gluon-arp-limiter + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + + procd_set_param stderr 1 + procd_close_instance +} diff --git a/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/100-arp-limit-chains b/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/100-arp-limit-chains new file mode 100644 index 00000000..b39b35c8 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/100-arp-limit-chains @@ -0,0 +1,3 @@ +chain('ARP_LIMIT', 'DROP') +chain('ARP_LIMIT_DATCHECK', 'RETURN') +chain('ARP_LIMIT_TLCHECK', 'RETURN') diff --git a/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/320-arp-limit-rules b/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/320-arp-limit-rules new file mode 100644 index 00000000..416bdd96 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/files/lib/gluon/ebtables/320-arp-limit-rules @@ -0,0 +1,6 @@ +rule('ARP_LIMIT -j ARP_LIMIT_DATCHECK') +rule('ARP_LIMIT --mark 0x2/0x2 -j RETURN') +rule('ARP_LIMIT -j ARP_LIMIT_TLCHECK') +rule('ARP_LIMIT --limit 1/sec --limit-burst 50 -j RETURN') + +rule('FORWARD -p ARP --logical-out br-client -o bat0 --arp-op Request -j ARP_LIMIT') diff --git a/package/gluon-ebtables-limit-arp/src/LICENSE b/package/gluon-ebtables-limit-arp/src/LICENSE new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/package/gluon-ebtables-limit-arp/src/Makefile b/package/gluon-ebtables-limit-arp/src/Makefile new file mode 100644 index 00000000..8d361c77 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/Makefile @@ -0,0 +1,14 @@ +# Copyright (c) 2017 Linus Lüssing +# +# SPDX-License-Identifier: GPL-2.0+ +# License-Filename: LICENSE + +all: gluon-arp-limiter + +CFLAGS += -Wall + +gluon-arp-limiter: gluon-arp-limiter.c addr_store.c lookup3.c mac.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) + +clean: + rm -f gluon-arp-limiter diff --git a/package/gluon-ebtables-limit-arp/src/addr_store.c b/package/gluon-ebtables-limit-arp/src/addr_store.c new file mode 100644 index 00000000..1eb4aef6 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/addr_store.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#include +#include +#include +#include +#include "addr_store.h" +#include "gluon-arp-limiter.h" +#include "lookup3.h" + +static struct addr_list *addr_node_alloc(void *addr, + struct addr_store *store) +{ + struct addr_list *node; + size_t addr_len = store->addr_len; + + node = malloc(sizeof(struct addr_list) + addr_len); + if (!node) + return NULL; + + memcpy(node->addr, addr, addr_len); + node->next = NULL; + node->tic = clock; + + return node; +} + +static struct addr_list *addr_list_search(void *addr, + size_t addr_len, + struct addr_list *list) +{ + struct addr_list *node = list; + struct addr_list *ret = NULL; + + if (!node) + goto out; + + do { + // Found it! + if (!memcmp(node->addr, addr, addr_len)) { + ret = node; + break; + } + + node = node->next; + } while (node); + +out: + return ret; +} + +static void addr_list_add(struct addr_list *node, struct addr_list **list) +{ + node->next = *list; + *list = node; +} + +static struct addr_list **addr_store_get_bucket(void *addr, + struct addr_store *store) +{ + int len = store->addr_len / sizeof(uint32_t); + int idx; + uint32_t ret; + + ret = hashword(addr, len, 0); + idx = ret % ADDR_STORE_NUM_BUCKETS; + + return &store->buckets[idx]; +} + +int addr_store_add(void *addr, struct addr_store *store) +{ + struct addr_list **bucket = addr_store_get_bucket(addr, store); + struct addr_list *node = addr_list_search(addr, store->addr_len, + *bucket); + + if (node) { + node->tic = clock; + return -EEXIST; + } + + node = addr_node_alloc(addr, store); + if (!node) { + printf("Error: Out of memory\n"); + return -ENOMEM; + } + + addr_list_add(node, bucket); + return 0; +} + +int addr_store_init(size_t addr_len, + void (*destructor)(struct addr_list *), + char *(*ntoa)(void *), + struct addr_store *store) +{ + int i; + + store->addr_len = addr_len; + store->destructor = destructor; + store->ntoa = ntoa; + + for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) + store->buckets[i] = NULL; + + return 0; +} + +static char *addr_ntoa(void *addr, struct addr_store *store) +{ + return store->ntoa(addr); +} + +static void addr_store_dump(struct addr_store *store) +{ + int i; + struct addr_list *node; + + for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) { + node = store->buckets[i]; + + if (node) + printf("Bucket #%i:\n", i); + + while (node) { + printf("\t%s\n", addr_ntoa(node->addr, store)); + node = node->next; + } + } +} + +void addr_store_cleanup(struct addr_store *store) +{ + struct addr_list *node, *prev; + int i; + + for (i = 0; i < ADDR_STORE_NUM_BUCKETS; i++) { + node = store->buckets[i]; + prev = NULL; + + while (node) { + if (node->tic != clock) { + store->destructor(node); + + if (prev) { + prev->next = node->next; + free(node); + node = prev->next; + } else { + store->buckets[i] = node->next; + free(node); + node = store->buckets[i]; + } + } else { + prev = node; + node = node->next; + } + } + } + + addr_store_dump(store); +} diff --git a/package/gluon-ebtables-limit-arp/src/addr_store.h b/package/gluon-ebtables-limit-arp/src/addr_store.h new file mode 100644 index 00000000..d3eaa78d --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/addr_store.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#ifndef _ADDR_STORE_H_ +#define _ADDR_STORE_H_ + +#define ADDR_STORE_NUM_BUCKETS 32 + +struct addr_list { + struct addr_list *next; + int tic; + char addr[0]; +}; + +struct addr_store { + struct addr_list *buckets[ADDR_STORE_NUM_BUCKETS]; + size_t addr_len; + void (*destructor)(struct addr_list *); + char *(*ntoa)(void *); +}; + +int addr_store_init(size_t addr_len, + void (*destructor)(struct addr_list *), + char *(*ntoa)(void *), + struct addr_store *store); +int addr_store_add(void *addr, struct addr_store *store); +void addr_store_cleanup(struct addr_store *store); + +#endif /* _ADDR_STORE_H_ */ diff --git a/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c b/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c new file mode 100644 index 00000000..9c764006 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#include +#include +#include +#include +#include +#include +#include +#include "addr_store.h" +#include "gluon-arp-limiter.h" +#include "mac.h" + +#define BATCTL_DC "/usr/sbin/batctl dc -H -n" +#define BATCTL_TL "/usr/sbin/batctl tl -H -n" +#define EBTABLES "/usr/sbin/ebtables-tiny" + +#define BUILD_BUG_ON(check) ((void)sizeof(int[1-2*!!(check)])) + +static struct addr_store ip_store; +static struct addr_store mac_store; + +char *addr_mac_ntoa(void *addr) +{ + return mac_ntoa((struct mac_addr *)addr); +} + +char *addr_inet_ntoa(void *addr) +{ + return inet_ntoa(*((struct in_addr *)addr)); +} + +static void ebt_ip_call(char *mod, struct in_addr ip) +{ + char str[196]; + int ret; + + snprintf(str, sizeof(str), + EBTABLES " %s ARP_LIMIT_DATCHECK -p ARP --arp-ip-dst %s -j mark --mark-or 0x2 --mark-target RETURN", + mod, inet_ntoa(ip)); + + ret = system(str); + if (ret) + fprintf(stderr, + "%i: Calling ebtables for DAT failed with status %i\n", + clock, ret); +} + +static void ip_node_destructor(struct addr_list *node) +{ + struct in_addr *ip = (struct in_addr *)node->addr; + + ebt_ip_call("-D", *ip); +} + +static void ebt_mac_limit_call(char *mod, struct mac_addr *mac) +{ + char str[128]; + int ret; + + snprintf(str, sizeof(str), + EBTABLES " %s ARP_LIMIT_TLCHECK --source %s --limit 6/min --limit-burst 50 -j RETURN", + mod, mac_ntoa(mac)); + + ret = system(str); + if (ret) + fprintf(stderr, + "%i: Calling ebtables for TL failed with status %i\n", + clock, ret); +} + +static void ebt_mac_ret_call(char *mod, struct mac_addr *mac, int add) +{ + char str[128]; + int ret; + + snprintf(str, sizeof(str), + EBTABLES " %s ARP_LIMIT_TLCHECK %s --source %s -j DROP", + mod, add ? "2" : "", mac_ntoa(mac)); + + ret = system(str); + if (ret) + fprintf(stderr, + "%i: Calling ebtables for TL failed with status %i\n", + clock, ret); +} + +static void ebt_mac_call(char *mod, struct mac_addr *mac) +{ + if (!strncmp(mod, "-D", strlen(mod))) { + ebt_mac_ret_call(mod, mac, 0); + ebt_mac_limit_call(mod, mac); + } else { + ebt_mac_limit_call(mod, mac); + ebt_mac_ret_call(mod, mac, 1); + } +} + +static void mac_node_destructor(struct addr_list *node) +{ + struct mac_addr *mac = (struct mac_addr *)node->addr; + + ebt_mac_call("-D", mac); +} + +static int dat_parse_line(const char *line, struct in_addr *ip) +{ + int ret; + char *p; + char *tok; + + p = strpbrk(line, "0123456789"); + if (!p) { + fprintf(stderr, "Error: Can't find integer in: %s\n", line); + return -EINVAL; + } + + tok = strtok(p, " "); + if (!tok) { + fprintf(stderr, "Error: Can't find end of string': %s\n", line); + return -EINVAL; + } + + ret = inet_aton(p, ip); + if (!ret) { + fprintf(stderr, "Error: inet_aton failed on: %s\n", p); + return -EINVAL; + } + + return 0; +} + +static void ebt_add_ip(struct in_addr ip) +{ + int ret = addr_store_add(&ip, &ip_store); + + /* already stored or out-of-memory */ + if (ret) + return; + + ebt_ip_call("-I", ip); +} + +static void ebt_add_mac(struct mac_addr *mac) +{ + int ret = addr_store_add(mac, &mac_store); + + /* already stored or out-of-memory */ + if (ret) + return; + + ebt_mac_call("-I", mac); +} + +static void ebt_dat_update(void) +{ + FILE *fp; + char line[256]; + char *pline; + int ret; + struct in_addr ip; + + fp = popen(BATCTL_DC, "r"); + if (!fp) { + fprintf(stderr, "%i: Error: Could not call batctl dc\n", clock); + return; + } + + while (1) { + pline = fgets(line, sizeof(line), fp); + if (!pline) { + if (!feof(fp)) + fprintf(stderr, "%i: Error: fgets() failed\n", clock); + break; + } + + ret = dat_parse_line(line, &ip); + if (ret < 0) { + fprintf(stderr, "%i: Error: Parsing line failed\n", + clock); + break; + } + + ebt_add_ip(ip); + } + + pclose(fp); +} + +static int tl_parse_line(char *line, struct mac_addr *mac) +{ + int ret; + char *p; + char *tok; + + p = strpbrk(line, "0123456789abcdef"); + if (!p) { + fprintf(stderr, "Error: Can't find hex in: %s\n", line); + return -EINVAL; + } + + tok = strtok(p, " "); + if (!tok) { + fprintf(stderr, "Error: Can't find end of string': %s\n", line); + return -EINVAL; + } + + ret = mac_aton(p, mac); + if (!ret) { + fprintf(stderr, "Error: mac_aton failed on: %s\n", p); + return -EINVAL; + } + + return 0; +} + +static void ebt_tl_update(void) +{ + FILE *fp; + char line[256]; + char *pline; + int ret; + struct mac_addr mac; + + fp = popen(BATCTL_TL, "r"); + if (!fp) { + fprintf(stderr, "%i: Error: Could not call batctl tl\n", clock); + return; + } + + while (1) { + pline = fgets(line, sizeof(line), fp); + if (!pline) { + if (!feof(fp)) + fprintf(stderr, "%i: Error: fgets() failed\n", clock); + break; + } + + ret = tl_parse_line(line, &mac); + if (ret < 0) { + fprintf(stderr, "%i: Error: Parsing line failed\n", + clock); + break; + } + + if (mac_is_multicast(&mac)) + continue; + + ebt_add_mac(&mac); + } + + pclose(fp); +} + +static void ebt_dat_flush(void) +{ + int ret = system(EBTABLES " -F ARP_LIMIT_DATCHECK"); + + if (ret) + fprintf(stderr, "Error flushing ARP_LIMIT_DATCHECK\n"); +} + +static void ebt_tl_flush(void) +{ + int ret = system(EBTABLES " -F ARP_LIMIT_TLCHECK"); + + if (ret) + fprintf(stderr, "Error flushing ARP_LIMIT_TLCHECK\n"); +} + +int main(int argc, char *argv[]) +{ + ebt_dat_flush(); + ebt_tl_flush(); + + /* necessary alignment for hashword() */ + BUILD_BUG_ON(sizeof(struct in_addr) % sizeof(uint32_t) != 0); + BUILD_BUG_ON(sizeof(struct mac_addr) % sizeof(uint32_t) != 0); + + addr_store_init(sizeof(struct in_addr), &ip_node_destructor, + addr_inet_ntoa, &ip_store); + addr_store_init(sizeof(struct mac_addr), &mac_node_destructor, + addr_mac_ntoa, &mac_store); + + while (1) { + ebt_dat_update(); + addr_store_cleanup(&ip_store); + + ebt_tl_update(); + addr_store_cleanup(&mac_store); + + sleep(30); + clock++; + } + + return 0; +} diff --git a/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.h b/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.h new file mode 100644 index 00000000..203ab217 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#ifndef _GLUON_ARP_LIMITER_H_ +#define _GLUON_ARP_LIMITER_H_ + +int clock; + +#endif /* _GLUON_ARP_LIMITER_H_ */ diff --git a/package/gluon-ebtables-limit-arp/src/lookup3.c b/package/gluon-ebtables-limit-arp/src/lookup3.c new file mode 100644 index 00000000..a6252a92 --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/lookup3.c @@ -0,0 +1,998 @@ +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ +//#define SELF_TEST 1 + +#include /* defines printf for tests */ +#include /* defines time_t for timings in the test */ +#include /* defines uint32_t etc */ +#include /* attempt to define endianness */ +#ifdef linux +# include /* attempt to define endianness */ +#endif + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +-------------------------------------------------------------------- + This works on all machines. To be useful, it requires + -- that the key be an array of uint32_t's, and + -- that the length be the number of uint32_t's in the key + + The function hashword() is identical to hashlittle() on little-endian + machines, and identical to hashbig() on big-endian machines, + except that the length has to be measured in uint32_ts rather than in + bytes. hashlittle() is more complicated than hashword() only because + hashlittle() has to dance around fitting the key bytes into registers. +-------------------------------------------------------------------- +*/ +uint32_t hashword( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t initval) /* the previous hash, or an arbitrary value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + (((uint32_t)length)<<2) + initval; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + return c; +} + + +/* +-------------------------------------------------------------------- +hashword2() -- same as hashword(), but take two seeds and return two +32-bit values. pc and pb must both be nonnull, and *pc and *pb must +both be initialized with seeds. If you pass in (*pb)==0, the output +(*pc) will be the same as the return value from hashword(). +-------------------------------------------------------------------- +*/ +void hashword2 ( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t *pc, /* IN: seed OUT: primary hash value */ +uint32_t *pb) /* IN: more seed OUT: secondary hash value */ +{ + uint32_t a,b,c; + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)(length<<2)) + *pc; + c += *pb; + + /*------------------------------------------------- handle most of the key */ + while (length > 3) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 3; + k += 3; + } + + /*------------------------------------------- handle the last 3 uint32_t's */ + switch(length) /* all the case statements fall through */ + { + case 3 : c+=k[2]; + case 2 : b+=k[1]; + case 1 : a+=k[0]; + final(a,b,c); + case 0: /* case 0: nothing left to add */ + break; + } + /*------------------------------------------------------ report the result */ + *pc=c; *pb=b; +} + + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + + +/* + * hashlittle2: return 2 32-bit hash values + * + * This is identical to hashlittle(), except it returns two 32-bit hash + * values instead of just one. This is good enough for hash table + * lookup with 2^^64 buckets, or if you want a second hash if you're not + * happy with the first, or if you want a probably-unique 64-bit ID for + * the key. *pc is better mixed than *pb, so use *pc first. If you want + * a 64-bit value do something like "*pc + (((uint64_t)*pb)<<32)". + */ +void hashlittle2( + const void *key, /* the key to hash */ + size_t length, /* length of the key */ + uint32_t *pc, /* IN: primary initval, OUT: primary hash */ + uint32_t *pb) /* IN: secondary initval, OUT: secondary hash */ +{ + uint32_t a,b,c; /* internal state */ + union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + *pc; + c += *pb; + + u.ptr = key; + if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; + case 11: c+=((uint32_t)k[10])<<16; + case 10: c+=((uint32_t)k[9])<<8; + case 9 : c+=k[8]; + case 8 : b+=((uint32_t)k[7])<<24; + case 7 : b+=((uint32_t)k[6])<<16; + case 6 : b+=((uint32_t)k[5])<<8; + case 5 : b+=k[4]; + case 4 : a+=((uint32_t)k[3])<<24; + case 3 : a+=((uint32_t)k[2])<<16; + case 2 : a+=((uint32_t)k[1])<<8; + case 1 : a+=k[0]; + break; + case 0 : *pc=c; *pb=b; return; /* zero length strings require no mixing */ + } + } + + final(a,b,c); + *pc=c; *pb=b; +} + + + +/* + * hashbig(): + * This is the same as hashword() on big-endian machines. It is different + * from hashlittle() on all machines. hashbig() takes advantage of + * big-endian byte ordering. + */ +uint32_t hashbig( const void *key, size_t length, uint32_t initval) +{ + uint32_t a,b,c; + union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */ + + /* Set up the internal state */ + a = b = c = 0xdeadbeef + ((uint32_t)length) + initval; + + u.ptr = key; + if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) { + const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */ + + /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]<<8" actually reads beyond the end of the string, but + * then shifts out the part it's not allowed to read. Because the + * string is aligned, the illegal read is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef VALGRIND + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff00; a+=k[0]; break; + case 6 : b+=k[1]&0xffff0000; a+=k[0]; break; + case 5 : b+=k[1]&0xff000000; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff00; break; + case 2 : a+=k[0]&0xffff0000; break; + case 1 : a+=k[0]&0xff000000; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<8; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<16; /* fall through */ + case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */ + case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */ + case 1 : a+=((uint32_t)k8[0])<<24; break; + case 0 : return c; + } + +#endif /* !VALGRIND */ + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += ((uint32_t)k[0])<<24; + a += ((uint32_t)k[1])<<16; + a += ((uint32_t)k[2])<<8; + a += ((uint32_t)k[3]); + b += ((uint32_t)k[4])<<24; + b += ((uint32_t)k[5])<<16; + b += ((uint32_t)k[6])<<8; + b += ((uint32_t)k[7]); + c += ((uint32_t)k[8])<<24; + c += ((uint32_t)k[9])<<16; + c += ((uint32_t)k[10])<<8; + c += ((uint32_t)k[11]); + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=k[11]; + case 11: c+=((uint32_t)k[10])<<8; + case 10: c+=((uint32_t)k[9])<<16; + case 9 : c+=((uint32_t)k[8])<<24; + case 8 : b+=k[7]; + case 7 : b+=((uint32_t)k[6])<<8; + case 6 : b+=((uint32_t)k[5])<<16; + case 5 : b+=((uint32_t)k[4])<<24; + case 4 : a+=k[3]; + case 3 : a+=((uint32_t)k[2])<<8; + case 2 : a+=((uint32_t)k[1])<<16; + case 1 : a+=((uint32_t)k[0])<<24; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} + + +#ifdef SELF_TEST + +/* used for timings */ +void driver1() +{ + uint8_t buf[256]; + uint32_t i; + uint32_t h=0; + time_t a,z; + + time(&a); + for (i=0; i<256; ++i) buf[i] = 'x'; + for (i=0; i<1; ++i) + { + h = hashlittle(&buf[0],1,h); + } + time(&z); + if (z-a > 0) printf("time %d %.8x\n", z-a, h); +} + +/* check that every input bit changes every output bit half the time */ +#define HASHSTATE 1 +#define HASHLEN 1 +#define MAXPAIR 60 +#define MAXLEN 70 +void driver2() +{ + uint8_t qa[MAXLEN+1], qb[MAXLEN+2], *a = &qa[0], *b = &qb[1]; + uint32_t c[HASHSTATE], d[HASHSTATE], i=0, j=0, k, l, m=0, z; + uint32_t e[HASHSTATE],f[HASHSTATE],g[HASHSTATE],h[HASHSTATE]; + uint32_t x[HASHSTATE],y[HASHSTATE]; + uint32_t hlen; + + printf("No more than %d trials should ever be needed \n",MAXPAIR/2); + for (hlen=0; hlen < MAXLEN; ++hlen) + { + z=0; + for (i=0; i>(8-j)); + c[0] = hashlittle(a, hlen, m); + b[i] ^= ((k+1)<>(8-j)); + d[0] = hashlittle(b, hlen, m); + /* check every bit is 1, 0, set, and not set at least once */ + for (l=0; lz) z=k; + if (k==MAXPAIR) + { + printf("Some bit didn't change: "); + printf("%.8x %.8x %.8x %.8x %.8x %.8x ", + e[0],f[0],g[0],h[0],x[0],y[0]); + printf("i %d j %d m %d len %d\n", i, j, m, hlen); + } + if (z==MAXPAIR) goto done; + } + } + } + done: + if (z < MAXPAIR) + { + printf("Mix success %2d bytes %2d initvals ",i,m); + printf("required %d trials\n", z/2); + } + } + printf("\n"); +} + +/* Check for reading beyond the end of the buffer and alignment problems */ +void driver3() +{ + uint8_t buf[MAXLEN+20], *b; + uint32_t len; + uint8_t q[] = "This is the time for all good men to come to the aid of their country..."; + uint32_t h; + uint8_t qq[] = "xThis is the time for all good men to come to the aid of their country..."; + uint32_t i; + uint8_t qqq[] = "xxThis is the time for all good men to come to the aid of their country..."; + uint32_t j; + uint8_t qqqq[] = "xxxThis is the time for all good men to come to the aid of their country..."; + uint32_t ref,x,y; + uint8_t *p; + + printf("Endianness. These lines should all be the same (for values filled in):\n"); + printf("%.8x %.8x %.8x\n", + hashword((const uint32_t *)q, (sizeof(q)-1)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-5)/4, 13), + hashword((const uint32_t *)q, (sizeof(q)-9)/4, 13)); + p = q; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qq[1]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqq[2]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + p = &qqqq[3]; + printf("%.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x %.8x\n", + hashlittle(p, sizeof(q)-1, 13), hashlittle(p, sizeof(q)-2, 13), + hashlittle(p, sizeof(q)-3, 13), hashlittle(p, sizeof(q)-4, 13), + hashlittle(p, sizeof(q)-5, 13), hashlittle(p, sizeof(q)-6, 13), + hashlittle(p, sizeof(q)-7, 13), hashlittle(p, sizeof(q)-8, 13), + hashlittle(p, sizeof(q)-9, 13), hashlittle(p, sizeof(q)-10, 13), + hashlittle(p, sizeof(q)-11, 13), hashlittle(p, sizeof(q)-12, 13)); + printf("\n"); + + /* check that hashlittle2 and hashlittle produce the same results */ + i=47; j=0; + hashlittle2(q, sizeof(q), &i, &j); + if (hashlittle(q, sizeof(q), 47) != i) + printf("hashlittle2 and hashlittle mismatch\n"); + + /* check that hashword2 and hashword produce the same results */ + len = 0xdeadbeef; + i=47, j=0; + hashword2(&len, 1, &i, &j); + if (hashword(&len, 1, 47) != i) + printf("hashword2 and hashword mismatch %x %x\n", + i, hashword(&len, 1, 47)); + + /* check hashlittle doesn't read before or after the ends of the string */ + for (h=0, b=buf+1; h<8; ++h, ++b) + { + for (i=0; i /* defines uint32_t etc */ + +uint32_t hashword( +const uint32_t *k, /* the key, an array of uint32_t values */ +size_t length, /* the length of the key, in uint32_ts */ +uint32_t initval); /* the previous hash, or an arbitrary value */ diff --git a/package/gluon-ebtables-limit-arp/src/mac.c b/package/gluon-ebtables-limit-arp/src/mac.c new file mode 100644 index 00000000..863c540e --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/mac.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#include +#include +#include +#include "mac.h" + +#define ETH_STRLEN (sizeof("aa:bb:cc:dd:ee:ff") - 1) + +char mntoa_buf[ETH_STRLEN+1]; + +int mac_aton(const char *cp, struct mac_addr *mac) +{ + struct mac_addr m; + int ret; + + if (strlen(cp) != ETH_STRLEN) + return 0; + + memset(&m, 0, sizeof(m)); + + ret = sscanf(cp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &m.storage[0], &m.storage[1], &m.storage[2], + &m.storage[3], &m.storage[4], &m.storage[5]); + + if (ret != ETH_ALEN) + return 0; + + *mac = m; + return 1; +} + +char *mac_ntoa(struct mac_addr *mac) +{ + unsigned char *m = mac->storage; + + snprintf(mntoa_buf, sizeof(mntoa_buf), + "%02x:%02x:%02x:%02x:%02x:%02x", + m[0], m[1], m[2], m[3], m[4], m[5]); + + return mntoa_buf; +} diff --git a/package/gluon-ebtables-limit-arp/src/mac.h b/package/gluon-ebtables-limit-arp/src/mac.h new file mode 100644 index 00000000..11567ade --- /dev/null +++ b/package/gluon-ebtables-limit-arp/src/mac.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Linus Lüssing + * + * SPDX-License-Identifier: GPL-2.0+ + * License-Filename: LICENSE + */ + +#ifndef _MAC_H_ +#define _MAC_H_ + +struct mac_addr { + /* 8 instead of 6 for multiples of uint32_t for hashword() */ + unsigned char storage[8]; +}; + +int mac_aton(const char *cp, struct mac_addr *mac); +char *mac_ntoa(struct mac_addr *mac); + +static inline int mac_is_multicast(struct mac_addr *addr) +{ + return addr->storage[0] & 0x01; +} + +#endif /* _MAC_H_ */ diff --git a/package/gluon-ebtables-source-filter/Makefile b/package/gluon-ebtables-source-filter/Makefile new file mode 100644 index 00000000..2c14a793 --- /dev/null +++ b/package/gluon-ebtables-source-filter/Makefile @@ -0,0 +1,19 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-ebtables-source-filter +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-ebtables-source-filter + TITLE:=Ebtables rules to filter unreasonable L2 traffic. + DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv +endef + +define Package/gluon-ebtables-source-filter/description + This package adds an additional layer-2 filter-ruleset to prevent unreasonable + traffic entering the network via the nodes. +endef + +$(eval $(call BuildPackageGluon,gluon-ebtables-source-filter)) diff --git a/package/gluon-ebtables-source-filter/check_site.lua b/package/gluon-ebtables-source-filter/check_site.lua new file mode 100644 index 00000000..56d229c0 --- /dev/null +++ b/package/gluon-ebtables-source-filter/check_site.lua @@ -0,0 +1,2 @@ +need_string_match(in_domain({'prefix4'}), '^%d+.%d+.%d+.%d+/%d+$', false) +need_string_array_match(in_domain({'extra_prefixes6'}), '^[%x:]+/%d+$', false) diff --git a/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/100-local-forward-chain b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/100-local-forward-chain new file mode 100644 index 00000000..b9f4467d --- /dev/null +++ b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/100-local-forward-chain @@ -0,0 +1 @@ +chain('LOCAL_FORWARD', 'DROP') diff --git a/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-arp b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-arp new file mode 100644 index 00000000..06436cf2 --- /dev/null +++ b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-arp @@ -0,0 +1,6 @@ +local prefix4 = require('gluon.site').prefix4() + +if prefix4 then + rule('LOCAL_FORWARD -p ARP --arp-ip-src ' .. prefix4 .. ' --arp-ip-dst ' .. prefix4 .. ' -j RETURN') + rule('LOCAL_FORWARD -p ARP --arp-ip-src 0.0.0.0 --arp-ip-dst ' .. prefix4 .. ' -j RETURN') +end diff --git a/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv4 b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv4 new file mode 100644 index 00000000..e712c5fb --- /dev/null +++ b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv4 @@ -0,0 +1,6 @@ +local prefix4 = require('gluon.site').prefix4() + +if prefix4 then + rule('LOCAL_FORWARD -p IPv4 --ip-protocol udp --ip-destination-port 67 -j RETURN') + rule('LOCAL_FORWARD -p IPv4 --ip-src ' .. prefix4 .. ' -j RETURN') +end diff --git a/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv6 b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv6 new file mode 100644 index 00000000..6be0de70 --- /dev/null +++ b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/110-local-forward-allow-ipv6 @@ -0,0 +1,9 @@ +site = require('gluon.site') + +rule('LOCAL_FORWARD -p IPv6 --ip6-src fe80::/64 -j RETURN') +rule('LOCAL_FORWARD -p IPv6 --ip6-src ::/128 --ip6-proto ipv6-icmp -j RETURN') +rule('LOCAL_FORWARD -p IPv6 --ip6-src ' .. site.prefix6() .. ' -j RETURN') + +for _, prefix in ipairs(site.extra_prefixes6({})) do + rule('LOCAL_FORWARD -p IPv6 --ip6-src ' .. prefix .. ' -j RETURN') +end diff --git a/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/300-local-forward-rules b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/300-local-forward-rules new file mode 100644 index 00000000..6c5a9257 --- /dev/null +++ b/package/gluon-ebtables-source-filter/files/lib/gluon/ebtables/300-local-forward-rules @@ -0,0 +1 @@ +rule('FORWARD --logical-in br-client -i ! bat0 -j LOCAL_FORWARD') diff --git a/package/gluon-ebtables/Makefile b/package/gluon-ebtables/Makefile index 39c654c1..ca83fcf4 100644 --- a/package/gluon-ebtables/Makefile +++ b/package/gluon-ebtables/Makefile @@ -4,33 +4,25 @@ PKG_NAME:=gluon-ebtables PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) +PKG_CONFIG_DEPENDS := CONFIG_GLUON_SPECIALIZE_KERNEL -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-ebtables - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Ebtables support - DEPENDS:=+gluon-core +ebtables +kmod-ebtables-ipv4 +kmod-ebtables-ipv6 +kmod-ipt-core + DEPENDS:=+gluon-core +ebtables-tiny \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_T_FILTER \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_T_NAT \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_ARP \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_IP \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_BRIDGE_EBT_IP6 \ + +!GLUON_SPECIALIZE_KERNEL:kmod-ebtables \ + +!GLUON_SPECIALIZE_KERNEL:kmod-ebtables-ipv4 \ + +!GLUON_SPECIALIZE_KERNEL:kmod-ebtables-ipv6 endef define Package/gluon-ebtables/description Gluon community wifi mesh firmware framework: ebtables support endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-ebtables/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-ebtables)) +$(eval $(call BuildPackageGluon,gluon-ebtables)) diff --git a/package/gluon-ebtables/check_site.lua b/package/gluon-ebtables/check_site.lua new file mode 100644 index 00000000..68747b78 --- /dev/null +++ b/package/gluon-ebtables/check_site.lua @@ -0,0 +1 @@ +need_boolean({'mesh', 'filter_membership_reports'}, false) diff --git a/package/gluon-ebtables/files/etc/init.d/gluon-ebtables b/package/gluon-ebtables/files/etc/init.d/gluon-ebtables index 5a770452..60add180 100755 --- a/package/gluon-ebtables/files/etc/init.d/gluon-ebtables +++ b/package/gluon-ebtables/files/etc/init.d/gluon-ebtables @@ -7,13 +7,13 @@ # rule FORWARD --logical-out br-client -d Multicast -p IPv4 --ip-protocol udp --ip-destination-port 5355 -j DROP # # Removing all rules: -# $ ./firewall-ebtables stop +# $ /etc/init.d/gluon-ebtables stop # Inserting all rules: -# $ ./firewall-ebtables start +# $ /etc/init.d/gluon-ebtables start # Inserting a specific rule file: -# $ ./firewall-ebtables start /lib/gluon/ebtables/100-mcast-chain +# $ /etc/init.d/gluon-ebtables start /lib/gluon/ebtables/100-mcast-chain # Removing a specific rule file: -# $ ./firewall-ebtables stop /lib/gluon/ebtables/100-mcast-chain +# $ /etc/init.d/gluon-ebtables stop /lib/gluon/ebtables/100-mcast-chain START=19 @@ -24,12 +24,15 @@ exec_file() { local file="$1" /usr/bin/lua -e " - function rule(command) + function rule(command, table) + table = table or 'filter' os.execute($EBTABLES_RULE) end - function chain(name, policy) + function chain(name, policy, table) + table = table or 'filter' os.execute($EBTABLES_CHAIN) end + " "$file" } @@ -48,8 +51,12 @@ exec_all() { start() { ( - export EBTABLES_RULE='"ebtables -A " .. command' - export EBTABLES_CHAIN='"ebtables -N " .. name .. " -P " .. policy' + export EBTABLES_RULE='"ebtables-tiny -t " .. table .. " -A " .. command' + export EBTABLES_CHAIN='"ebtables-tiny -t " .. table .. " -N " .. name .. " -P " .. policy' + + # Contains /var/lib/ebtables/lock for '--concurrent' + [ ! -d "/var/lib/ebtables" ] && \ + mkdir -p /var/lib/ebtables if [ -z "$1" ]; then exec_all '' @@ -61,8 +68,8 @@ start() { stop() { ( - export EBTABLES_RULE='"ebtables -D " .. command' - export EBTABLES_CHAIN='"ebtables -X " .. name' + export EBTABLES_RULE='"ebtables-tiny -t " .. table .. " -D " .. command' + export EBTABLES_CHAIN='"ebtables-tiny -t " .. table .. " -X " .. name' if [ -z "$1" ]; then exec_all '-r' diff --git a/package/gluon-ebtables/files/lib/gluon/ebtables/100-dir-chain b/package/gluon-ebtables/files/lib/gluon/ebtables/100-dir-chain index 31c19c53..62b92947 100644 --- a/package/gluon-ebtables/files/lib/gluon/ebtables/100-dir-chain +++ b/package/gluon-ebtables/files/lib/gluon/ebtables/100-dir-chain @@ -1,2 +1,9 @@ chain('IN_ONLY', 'RETURN') chain('OUT_ONLY', 'RETURN') + +-- nat chain runs early, so we can drop IGMP/MLD +chain('MULTICAST_IN', 'RETURN', 'nat') +chain('MULTICAST_IN_ICMPV6', 'RETURN', 'nat') + +chain('MULTICAST_OUT', 'RETURN') +chain('MULTICAST_OUT_ICMPV6', 'RETURN') diff --git a/package/gluon-ebtables/files/lib/gluon/ebtables/101-dir-rules b/package/gluon-ebtables/files/lib/gluon/ebtables/101-dir-rules index b1cd4e24..74486ae5 100644 --- a/package/gluon-ebtables/files/lib/gluon/ebtables/101-dir-rules +++ b/package/gluon-ebtables/files/lib/gluon/ebtables/101-dir-rules @@ -1,2 +1,7 @@ -rule 'IN_ONLY --logical-in br-client -i ! bat0 -j DROP' -rule 'OUT_ONLY --logical-out br-client -o ! bat0 -j DROP' +rule 'IN_ONLY --logical-in br-client -i bat0 -j RETURN' +rule 'IN_ONLY --logical-in br-client -i local-port -j RETURN' +rule 'IN_ONLY --logical-in br-client -j DROP' + +rule 'OUT_ONLY --logical-out br-client -o bat0 -j RETURN' +rule 'OUT_ONLY --logical-out br-client -o local-port -j RETURN' +rule 'OUT_ONLY --logical-out br-client -j DROP' diff --git a/package/gluon-ebtables/files/lib/gluon/ebtables/105-mcast-drop-igmp-mld b/package/gluon-ebtables/files/lib/gluon/ebtables/105-mcast-drop-igmp-mld new file mode 100644 index 00000000..3b1ecab3 --- /dev/null +++ b/package/gluon-ebtables/files/lib/gluon/ebtables/105-mcast-drop-igmp-mld @@ -0,0 +1,20 @@ +local site = require 'gluon.site' + +rule('MULTICAST_IN -p IPv4 --ip-protocol igmp --ip-igmp-type membership-query -j DROP', 'nat') +rule('MULTICAST_OUT -p IPv4 --ip-protocol igmp --ip-igmp-type membership-query -j DROP') + +rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP') -- MLD Query +rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP', 'nat') -- MLD Query + +if site.mesh.filter_membership_reports(true) then + rule('MULTICAST_IN -p IPv4 --ip-protocol igmp -j DROP', 'nat') + rule('MULTICAST_OUT -p IPv4 --ip-protocol igmp -j DROP') + + rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP') -- MLDv1 Report + rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP') -- MLDv1 Done + rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP') -- MLDv2 Report + + rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP', 'nat') -- MLDv1 Report + rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP', 'nat') -- MLDv1 Done + rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP', 'nat') -- MLDv2 Report +end diff --git a/package/gluon-ebtables/files/lib/gluon/ebtables/350-mcast-dir-rules b/package/gluon-ebtables/files/lib/gluon/ebtables/350-mcast-dir-rules new file mode 100644 index 00000000..5b625f99 --- /dev/null +++ b/package/gluon-ebtables/files/lib/gluon/ebtables/350-mcast-dir-rules @@ -0,0 +1,6 @@ +rule ('PREROUTING -d Multicast --logical-in br-client -i bat0 -j MULTICAST_IN', 'nat') +rule 'OUTPUT -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT' +rule 'FORWARD -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT' + +rule ('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_IN_ICMPV6', 'nat') +rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_OUT_ICMPV6' diff --git a/package/gluon-l3roamd/Makefile b/package/gluon-l3roamd/Makefile new file mode 100644 index 00000000..9cae9bb1 --- /dev/null +++ b/package/gluon-l3roamd/Makefile @@ -0,0 +1,13 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-l3roamd +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-l3roamd + TITLE:=Configure l3roamd for babel + DEPENDS:=+gluon-core +l3roamd +endef + +$(eval $(call BuildPackageGluon,gluon-l3roamd)) diff --git a/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd b/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd new file mode 100755 index 00000000..d40e1a18 --- /dev/null +++ b/package/gluon-l3roamd/files/etc/init.d/gluon-l3roamd @@ -0,0 +1,29 @@ +#!/bin/sh /etc/rc.common + +START=55 + +USE_PROCD=1 +PROG=/usr/sbin/l3roamd + +start_service () { + local interfaces=$( + for dev in $(gluon-list-mesh-interfaces); do echo " -m $dev"; done + [ "$(ifstatus local_node | jsonfilter -e '@.up')" = 'true' ] && echo ' -i local-node' + ) + + procd_open_instance + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_set_param respawn ${respawn_threshold:-3660} ${respawn_timeout:-5} ${respawn_retry:-0} + procd_set_param command "$PROG" -s /var/run/l3roamd.sock -p $(lua -e 'print(require("gluon.site").prefix6())') $interfaces -t 254 -a $(uci get network.loopback.ip6addr | cut -d/ -f1) -4 0:0:0:0:0:ffff::/96 -b br-client + procd_close_instance +} + +service_triggers() { + local script=$(readlink "$initscript") + local name=$(basename "${script:-$initscript}") + + procd_open_trigger + procd_add_raw_trigger 'interface.*' 0 "/etc/init.d/$name" reload + procd_close_trigger +} diff --git a/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd new file mode 100755 index 00000000..b1b28844 --- /dev/null +++ b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/150-firewall-l3roamd @@ -0,0 +1,12 @@ +#!/usr/bin/lua +local uci = require('simple-uci').cursor() + +uci:section('firewall', 'rule', 'mesh_l3roamd', { + name = 'mesh_l3roamd', + src = 'mesh', + dest_port = '5523', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:save('firewall') diff --git a/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/380-gluon-l3roamd-route b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/380-gluon-l3roamd-route new file mode 100755 index 00000000..5d0fb42e --- /dev/null +++ b/package/gluon-l3roamd/luasrc/lib/gluon/upgrade/380-gluon-l3roamd-route @@ -0,0 +1,6 @@ +#!/usr/bin/lua + +uci:delete('network', 'l3roam') +uci:delete('network', 'l3roamd_client') + +uci:save('network') diff --git a/package/gluon-legacy/Makefile b/package/gluon-legacy/Makefile deleted file mode 100644 index 7320fba6..00000000 --- a/package/gluon-legacy/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-legacy -PKG_VERSION:=2 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -define Package/gluon-legacy - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Legacy update scripts - DEPENDS:=+gluon-core -endef - -define Package/gluon-legacy/description - Gluon community wifi mesh firmware framework: legacy update scripts -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-legacy/install - $(CP) ./files/* $(1)/ -endef - -define Package/gluon-legacy/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-legacy)) diff --git a/package/gluon-legacy/check_site.lua b/package/gluon-legacy/check_site.lua deleted file mode 100644 index 1ec26de0..00000000 --- a/package/gluon-legacy/check_site.lua +++ /dev/null @@ -1,8 +0,0 @@ -need_string_array 'legacy.version_files' -need_string_array 'legacy.old_files' - -need_string_array 'legacy.config_mode_configs' -need_string_array 'legacy.fastd_configs' -need_string 'legacy.mesh_ifname' -need_string_array 'legacy.tc_configs' -need_string_array 'legacy.wifi_names' diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/000-legacy b/package/gluon-legacy/files/lib/gluon/upgrade/000-legacy deleted file mode 100755 index 78436676..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/000-legacy +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -for _, file in ipairs(site.legacy.version_files) do - if os.remove(file) then - -- Set version being upgraded from to 'legacy' - sysconfig.gluon_version = 'legacy' - end -end diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/019-legacy-interfaces b/package/gluon-legacy/files/lib/gluon/upgrade/019-legacy-interfaces deleted file mode 100755 index 691e4ad7..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/019-legacy-interfaces +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/lua - -local gluon_util = require 'gluon.util' -local platform = require 'gluon.platform' -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() -local util = require 'luci.util' - - -if sysconfig.gluon_version == 'legacy' then - local function iface_exists(name) - return (gluon_util.exec('ip', 'link', 'show', 'dev', (name:gsub('%..*$', ''))) == 0) - end - - local function remove_bat0(iface) - return util.trim(string.gsub(' ' .. iface .. ' ', ' bat0 ', ' ')) - end - - - local lan_ifname = remove_bat0(uci:get('network', site.legacy.mesh_ifname, 'ifname')) - local wan_ifname = uci:get('network', 'wan', 'ifname') - - if wan_ifname and iface_exists(wan_ifname) then - sysconfig.wan_ifname = wan_ifname - sysconfig.lan_ifname = lan_ifname - else - sysconfig.wan_ifname = lan_ifname - end - - - uci:delete('network', site.legacy.mesh_ifname) - uci:delete('network', 'wan') - - uci:save('network') -end - - diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/210-legacy-wireless b/package/gluon-legacy/files/lib/gluon/upgrade/210-legacy-wireless deleted file mode 100755 index d8fd1720..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/210-legacy-wireless +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() - - -if sysconfig.gluon_version == 'legacy' then - function delete_legacy_iface(iface) - for _, wifi in pairs(site.legacy.wifi_names) do - if wifi == iface['.name'] then - return true - end - end - - return false - end - - uci:delete_all('wireless', 'wifi-iface', delete_legacy_iface) - - uci:save('wireless') -end diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-setup-mode b/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-setup-mode deleted file mode 100755 index d2a67484..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-setup-mode +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() - - -if sysconfig.gluon_version == 'legacy' then - for _, config in ipairs(site.legacy.config_mode_configs) do - local old = uci:get_first(config, 'wizard', 'configured') - if old == '1' then - local setup_mode = uci:get_first('gluon-setup-mode', 'setup_mode') - uci:set('gluon-setup-mode', setup_mode, 'configured', '1') - uci:save('gluon-setup-mode') - - break - end - end -end diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-simple-tc b/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-simple-tc deleted file mode 100755 index 652c53c9..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/290-legacy-simple-tc +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() - - -if sysconfig.gluon_version == 'legacy' then - for _, config in ipairs(site.legacy.tc_configs) do - local s = uci:get_first(config, 'bandwidth') - if s then - old = uci:get_all(config, s) - uci:section('simple-tc', 'interface', 'mesh_vpn', - { - ifname = 'mesh-vpn', - enabled = old.enabled, - limit_ingress = old.downstream, - limit_egress = old.upstream, - } - ) - - uci:save('simple-tc') - - break - end - end -end diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/390-legacy-mesh-vpn-fastd b/package/gluon-legacy/files/lib/gluon/upgrade/390-legacy-mesh-vpn-fastd deleted file mode 100755 index 21f95e07..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/390-legacy-mesh-vpn-fastd +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() - - -if sysconfig.gluon_version == 'legacy' then - local secret - local enabled - - - for _, config in ipairs(site.legacy.fastd_configs) do - if not secret then - local s = uci:get_all('fastd', config) - if s then - secret = s.secret - enabled = s.enabled - end - end - - uci:delete('fastd', config) - end - - if secret then - uci:section('fastd', 'fastd', 'mesh_vpn', - { - secret = secret, - enabled = enabled, - } - ) - end - - uci:save('fastd') -end diff --git a/package/gluon-legacy/files/lib/gluon/upgrade/990-legacy-late b/package/gluon-legacy/files/lib/gluon/upgrade/990-legacy-late deleted file mode 100755 index efb6b675..00000000 --- a/package/gluon-legacy/files/lib/gluon/upgrade/990-legacy-late +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local sysconfig = require 'gluon.sysconfig' - - -if sysconfig.gluon_version == 'legacy' then - for _, file in ipairs(site.legacy.old_files) do - os.remove(file) - end -end diff --git a/package/gluon-lock-password/Makefile b/package/gluon-lock-password/Makefile index d0e99373..366fd7b8 100644 --- a/package/gluon-lock-password/Makefile +++ b/package/gluon-lock-password/Makefile @@ -4,13 +4,9 @@ PKG_NAME:=gluon-lock-password PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-lock-password - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Locks the root account by default DEPENDS:=+gluon-core endef @@ -19,18 +15,4 @@ define Package/gluon-lock-password/description This packages locks the root account by default. endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-lock-password/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-lock-password)) +$(eval $(call BuildPackageGluon,gluon-lock-password)) diff --git a/package/gluon-luci-admin/Makefile b/package/gluon-luci-admin/Makefile deleted file mode 100644 index 3e20d179..00000000 --- a/package/gluon-luci-admin/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2013 Nils Schneider -# This is free software, licensed under the Apache 2.0 license. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-admin -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-admin - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci based simple administration interface for mesh nodes - DEPENDS:=gluon-config-mode-core-virtual -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-admin,i18n) -endef - -define Package/gluon-luci-admin/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-admin,$(1)) -endef - -$(eval $(call BuildPackage,gluon-luci-admin)) diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua b/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua deleted file mode 100644 index 55c0a248..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/index.lua +++ /dev/null @@ -1,39 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2008 Steven Barth -Copyright 2008 Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -module("luci.controller.admin.index", package.seeall) - -function index() - local uci_state = luci.model.uci.cursor_state() - - -- Disable gluon-luci-admin when setup mode is not enabled - if uci_state:get_first('gluon-setup-mode', 'setup_mode', 'running', '0') ~= '1' then - return - end - - local root = node() - if not root.lock then - root.target = alias("admin") - root.index = true - end - - local page = entry({"admin"}, alias("admin", "index"), _("Expert Mode"), 10) - page.sysauth = "root" - page.sysauth_authenticator = function() return "root" end - page.index = true - - entry({"admin", "index"}, cbi("admin/info"), _("Information"), 1).ignoreindex = true - entry({"admin", "remote"}, cbi("admin/remote"), _("Remote access"), 10) -end diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua b/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua deleted file mode 100644 index 2365f02c..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/controller/admin/upgrade.lua +++ /dev/null @@ -1,133 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2008 Steven Barth -Copyright 2008 Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -module("luci.controller.admin.upgrade", package.seeall) - -function index() - local has_platform = nixio.fs.access("/lib/upgrade/platform.sh") - if has_platform then - entry({"admin", "upgrade"}, call("action_upgrade"), _("Upgrade firmware"), 90) - entry({"admin", "upgrade", "reboot"}, template("admin/upgrade_reboot"), nil, nil) - end -end - -function action_upgrade() - local tmpfile = "/tmp/firmware.img" - - -- Install upload handler - local file - luci.http.setfilehandler( - function(meta, chunk, eof) - if not nixio.fs.access(tmpfile) and not file and chunk and #chunk > 0 then - file = io.open(tmpfile, "w") - end - if file and chunk then - file:write(chunk) - end - if file and eof then - file:close() - end - end - ) - - -- Determine state - local step = tonumber(luci.http.formvalue("step") or 1) - local has_image = nixio.fs.access(tmpfile) - local has_support = image_supported(tmpfile) - - -- Step 1: file upload, error on unsupported image format - if not has_image or not has_support or step == 1 then - -- If there is an image but user has requested step 1 - -- or type is not supported, then remove it. - if has_image then - nixio.fs.unlink(tmpfile) - end - - luci.template.render("admin/upgrade", { - bad_image=(has_image and not has_support or false) - } ) - - -- Step 2: present uploaded file, show checksum, confirmation - elseif step == 2 then - luci.template.render("admin/upgrade_confirm", { - checksum=image_checksum(tmpfile), - filesize=nixio.fs.stat(tmpfile).size, - flashsize=storage_size(), - keepconfig=luci.http.formvalue("keepcfg") == "1" - } ) - elseif step == 3 then - local keepcfg = luci.http.formvalue("keepcfg") == "1" - fork_exec("/sbin/sysupgrade %s %q" % { keepcfg and "" or "-n", tmpfile }) - luci.http.redirect(luci.dispatcher.build_url("admin", "upgrade", "reboot")) - end -end - -function fork_exec(command) - local pid = nixio.fork() - if pid > 0 then - return - elseif pid == 0 then - -- change to root dir - nixio.chdir("/") - - -- patch stdin, out, err to /dev/null - local null = nixio.open("/dev/null", "w+") - if null then - nixio.dup(null, nixio.stderr) - nixio.dup(null, nixio.stdout) - nixio.dup(null, nixio.stdin) - if null:fileno() > 2 then - null:close() - end - end - - -- replace with target command - nixio.exec("/bin/sh", "-c", command) - end -end - -function image_supported(tmpfile) - -- XXX: yay... - return ( 0 == os.execute( - "/sbin/sysupgrade -T %q >/dev/null" - % tmpfile - ) ) -end - -function storage_size() - local size = 0 - if nixio.fs.access("/proc/mtd") then - for l in io.lines("/proc/mtd") do - local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"') - if n == "linux" then - size = tonumber(s, 16) - break - end - end - elseif nixio.fs.access("/proc/partitions") then - for l in io.lines("/proc/partitions") do - local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)') - if b and n and not n:match('[0-9]') then - size = tonumber(b) * 1024 - break - end - end - end - return size -end - -function image_checksum(tmpfile) - return (luci.sys.exec("md5sum %q" % tmpfile):match("^([^%s]+)")) -end diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/info.lua b/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/info.lua deleted file mode 100644 index e9ceba70..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/info.lua +++ /dev/null @@ -1,4 +0,0 @@ -local t = Template('admin/info') -t.pageaction = false - -return t diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua b/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua deleted file mode 100644 index c79c0195..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/model/cbi/admin/remote.lua +++ /dev/null @@ -1,105 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2008 Steven Barth -Copyright 2011 Jo-Philipp Wich -Copyright 2013 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local fs = require "nixio.fs" - -local m = Map("system", translate("SSH keys")) -m.pageaction = false -m.template = "admin/expertmode" - -if fs.access("/etc/config/dropbear") then - local s = m:section(TypedSection, "_dummy1", nil, - translate("You can provide your SSH keys here (one per line):")) - - s.addremove = false - s.anonymous = true - - function s.cfgsections() - return { "_keys" } - end - - local keys - - keys = s:option(TextValue, "_data", "") - keys.wrap = "off" - keys.rows = 5 - keys.rmempty = true - - function keys.cfgvalue() - return fs.readfile("/etc/dropbear/authorized_keys") or "" - end - - function keys.write(self, section, value) - if value then - fs.writefile("/etc/dropbear/authorized_keys", value:gsub("\r\n", "\n"):trim() .. "\n") - end - end - - function keys.remove(self, section) - if keys:formvalue("_keys") then - fs.remove("/etc/dropbear/authorized_keys") - end - end -end - -local m2 = Map("system", translate("Password")) -m2.reset = false -m2.pageaction = false -m2.template = "admin/expertmode" - -local s = m2:section(TypedSection, "_dummy2", nil, translate( - "Alternatively, you can set a password to access you node. Please choose a secure password you don't use anywhere else.

" - .. "If you set an empty password, login via password will be disabled. This is the default.")) - -s.addremove = false -s.anonymous = true - -local pw1 = s:option(Value, "pw1", translate("Password")) -pw1.password = true - -local pw2 = s:option(Value, "pw2", translate("Confirmation")) -pw2.password = true - -function s.cfgsections() - return { "_pass" } -end - -function m2.on_commit(map) - local v1 = pw1:formvalue("_pass") - local v2 = pw2:formvalue("_pass") - - if v1 and v2 then - if v1 == v2 then - if #v1 > 0 then - if luci.sys.user.setpasswd('root', v1) == 0 then - m2.message = translate("Password changed.") - else - m2.errmessage = translate("Unable to change the password.") - end - else - -- We don't check the return code here as the error 'password for root is already locked' is normal... - os.execute('passwd -l root >/dev/null') - m2.message = translate("Password removed.") - end - else - m2.errmessage = translate("The password and the confirmation differ.") - end - end -end - -local c = Compound(m, m2) -c.pageaction = false -return c diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm b/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm deleted file mode 100644 index 53947f3c..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/expertmode.htm +++ /dev/null @@ -1,56 +0,0 @@ -<% if not self.embedded then %> -
-
- - -
-<% end %> -
- <% if self.title and #self.title > 0 then %>

<%=self.title%>

<% end %> - <%- if self.message then %> -

<%=self.message%>

- <%- end %> - <%- if self.errmessage then %> -

<%=self.errmessage%>

- <%- end %> - <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> - <% self:render_children() %> -
-<% if not self.embedded then %> -
-<%- - if type(self.hidden) == "table" then - for k, v in pairs(self.hidden) do --%> - -<%- - end - end -%> -<% if redirect then %> -
- -
-<% end %> -<%- if self.flow and self.flow.skip then %> - -<% end %> -<%- if self.submit ~= false then %> - -<% end %> -<%- if self.reset ~= false then %> - -<% end %> -<%- if self.cancel ~= false and self.on_cancel then %> - -<% end %> - -
-
-<% end %> diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm b/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm deleted file mode 100644 index da403c1b..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/info.htm +++ /dev/null @@ -1,45 +0,0 @@ -<%- - local fs = require 'nixio.fs' - local uci = require('luci.model.uci').cursor() - local util = require 'luci.util' - local i18n = require 'luci.i18n' - - local site = require 'gluon.site_config' - local sysconfig = require 'gluon.sysconfig' - local platform = require 'gluon.platform' - - - local keys = { - hostname = i18n.translate('Hostname'), - primary_mac = i18n.translate('MAC address'), - model = i18n.translate('Hardware model'), - version = i18n.translate('Gluon version'), - release = i18n.translate('Firmware release'), - site = i18n.translate('Site'), - pubkey = i18n.translate('Public VPN key'), - } - - local values = { - hostname = uci:get_first('system', 'system', 'hostname'), - primary_mac = sysconfig.primary_mac, - model = platform.get_model(), - version = util.trim(fs.readfile('/lib/gluon/gluon-version')), - release = util.trim(fs.readfile('/lib/gluon/release')), - site = site.site_name, - pubkey = 'n/a', - } - - local meshvpn_enabled = uci:get("fastd", "mesh_vpn", "enabled", "0") - if meshvpn_enabled == "1" then - local pubkey = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn')) - if pubkey ~= '' then - values.pubkey = pubkey - end - end --%> -

<%:Information%>

-<% for _, key in ipairs({'hostname', 'primary_mac', 'model', 'version', 'release', 'site', 'pubkey'}) do %> -
-
<%=keys[key]%>
<%=values[key] or 'n/a'%>
-
-<% end %> diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm b/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm deleted file mode 100644 index a2b82235..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade.htm +++ /dev/null @@ -1,55 +0,0 @@ -<%# -LuCI - Lua Configuration Interface -Copyright 2008 Steven Barth -Copyright 2008-2009 Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - --%> - -<%+header%> - -

<%:Upgrade firmware%>

- -
-

- <%:You can manually upgrade your firmware here.%> -

- <% if bad_image then %> -

<%:The provided firmware image is not valid for this device.%>

- <% end %> -
-
- -
- -
-
- -
- - -
- - -
-
-
- -
- - -
-
-<%+footer%> - diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_reboot.htm b/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_reboot.htm deleted file mode 100644 index 3e89e778..00000000 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_reboot.htm +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - <%:Upgrading firmware%> - - - -
-
-

- <%:The firmware is currently being upgraded.%> - <%:Don't switch off the device in any circumstance!%> - <%:The upgrade will take a few minutes. When it is finished, your node will reboot automatically.%> -

-
-
- - diff --git a/package/gluon-luci-autoupdater/Makefile b/package/gluon-luci-autoupdater/Makefile deleted file mode 100644 index 650c4692..00000000 --- a/package/gluon-luci-autoupdater/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2013 Nils Schneider -# This is free software, licensed under the Apache 2.0 license. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-autoupdater -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-autoupdater - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci module for gluon-autoupdater - DEPENDS:=+gluon-luci-admin +gluon-autoupdater -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-autoupdater,i18n) -endef - -define Package/gluon-luci-autoupdater/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-autoupdater,$(1)) -endef - -$(eval $(call BuildPackage,gluon-luci-autoupdater)) diff --git a/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/controller/admin/autoupdater.lua b/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/controller/admin/autoupdater.lua deleted file mode 100644 index 64e1acbd..00000000 --- a/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/controller/admin/autoupdater.lua +++ /dev/null @@ -1,19 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2013 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -module("luci.controller.admin.autoupdater", package.seeall) - -function index() - entry({"admin", "autoupdater"}, cbi("admin/autoupdater"), _("Automatic updates"), 80) -end diff --git a/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/model/cbi/admin/autoupdater.lua b/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/model/cbi/admin/autoupdater.lua deleted file mode 100644 index a8f9d3b3..00000000 --- a/package/gluon-luci-autoupdater/files/usr/lib/lua/luci/model/cbi/admin/autoupdater.lua +++ /dev/null @@ -1,29 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2013 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -m = Map("autoupdater", translate("Automatic updates")) -m.pageaction = false -m.template = "admin/expertmode" - -s = m:section(TypedSection, "autoupdater", nil) -s.addremove = false -s.anonymous = true - -s:option(Flag, "enabled", translate("Enable")) -f = s:option(ListValue, "branch", translate("Branch")) - -uci.cursor():foreach("autoupdater", "branch", function (section) f:value(section[".name"]) end) - -return m - diff --git a/package/gluon-luci-mesh-vpn-fastd/Makefile b/package/gluon-luci-mesh-vpn-fastd/Makefile deleted file mode 100644 index 1be12ccc..00000000 --- a/package/gluon-luci-mesh-vpn-fastd/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-mesh-vpn-fastd -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-mesh-vpn-fastd - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci module to enable and disable encryption for the mesh VPN - DEPENDS:=+gluon-luci-admin +gluon-mesh-vpn-fastd -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-mesh-vpn-fastd,i18n) -endef - -define Package/gluon-luci-mesh-vpn-fastd/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-mesh-vpn-fastd,$(1)) -endef - -define Package/gluon-luci-mesh-vpn-fastd/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-luci-mesh-vpn-fastd)) diff --git a/package/gluon-luci-mesh-vpn-fastd/check_site.lua b/package/gluon-luci-mesh-vpn-fastd/check_site.lua deleted file mode 100644 index 42ff5a50..00000000 --- a/package/gluon-luci-mesh-vpn-fastd/check_site.lua +++ /dev/null @@ -1,2 +0,0 @@ -assert(need_boolean('fastd_mesh_vpn.configurable') == true, - "site.conf error: expected `fastd_mesh_vpn.configurable' to be true") diff --git a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/controller/admin/mesh_vpn_fastd.lua b/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/controller/admin/mesh_vpn_fastd.lua deleted file mode 100644 index 8141c44a..00000000 --- a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/controller/admin/mesh_vpn_fastd.lua +++ /dev/null @@ -1,5 +0,0 @@ -module("luci.controller.admin.mesh_vpn_fastd", package.seeall) - -function index() - entry({"admin", "mesh_vpn_fastd"}, cbi("admin/mesh_vpn_fastd"), _("Mesh VPN"), 20) -end diff --git a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/model/cbi/admin/mesh_vpn_fastd.lua b/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/model/cbi/admin/mesh_vpn_fastd.lua deleted file mode 100644 index 14bb5783..00000000 --- a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/model/cbi/admin/mesh_vpn_fastd.lua +++ /dev/null @@ -1,41 +0,0 @@ -local uci = luci.model.uci.cursor() -local util = luci.util - -local f = SimpleForm('mesh_vpn', translate('Mesh VPN')) -f.template = "admin/expertmode" - -local s = f:section(SimpleSection) - -local o = s:option(Value, 'mode') -o.template = "gluon/cbi/mesh-vpn-fastd-mode" - -local methods = uci:get('fastd', 'mesh_vpn', 'method') -if util.contains(methods, 'null') then - o.default = 'performance' -else - o.default = 'security' -end - -function f.handle(self, state, data) - if state == FORM_VALID then - local site = require 'gluon.site_config' - - local methods = {} - if data.mode == 'performance' then - table.insert(methods, 'null') - end - - for _, method in ipairs(site.fastd_mesh_vpn.methods) do - if method ~= 'null' then - table.insert(methods, method) - end - end - - uci:set('fastd', 'mesh_vpn', 'method', methods) - - uci:save('fastd') - uci:commit('fastd') - end -end - -return f diff --git a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/view/gluon/cbi/mesh-vpn-fastd-mode.htm b/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/view/gluon/cbi/mesh-vpn-fastd-mode.htm deleted file mode 100644 index 0899fa1d..00000000 --- a/package/gluon-luci-mesh-vpn-fastd/files/usr/lib/lua/luci/view/gluon/cbi/mesh-vpn-fastd-mode.htm +++ /dev/null @@ -1,32 +0,0 @@ -
-
- /> -
-
- class="cbi-value-title"><%:Security mode%> -
- <%= translate( - 'In security mode, the mesh VPN uses an encrypted tunnel to connect to the VPN servers. ' .. - 'The encryption ensures that it is impossible for your internet access provider to see what ' .. - 'data is exchanged over your node.' - ) %> -
-
-
-
- -
-
- /> -
-
- class="cbi-value-title"><%:Performance mode%> -
- <%= translate( - 'In performance mode, no encryption is used. This usually allows for higher throughput, but the data exchanged over your node is not ' .. - 'protected against eavesdropping.' - ) %> -
-
-
-
diff --git a/package/gluon-luci-node-role/Makefile b/package/gluon-luci-node-role/Makefile deleted file mode 100644 index ded7bd3f..00000000 --- a/package/gluon-luci-node-role/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-node-role -PKG_VERSION:=0.1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-node-role - SECTION:=gluon - CATEGORY:=Gluon - DEPENDS:=+gluon-luci-admin +gluon-node-info - TITLE:=UI for specifying node role -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-node-role,i18n) -endef - -define Package/gluon-luci-node-role/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-node-role,$(1)) -endef - -define Package/gluon-luci-node-role/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-luci-node-role)) diff --git a/package/gluon-luci-node-role/check_site.lua b/package/gluon-luci-node-role/check_site.lua deleted file mode 100644 index ab01eeb5..00000000 --- a/package/gluon-luci-node-role/check_site.lua +++ /dev/null @@ -1,2 +0,0 @@ -need_string 'roles.default' -need_string_array 'roles.list' diff --git a/package/gluon-luci-node-role/files/usr/lib/lua/luci/controller/admin/noderole.lua b/package/gluon-luci-node-role/files/usr/lib/lua/luci/controller/admin/noderole.lua deleted file mode 100644 index cfca1275..00000000 --- a/package/gluon-luci-node-role/files/usr/lib/lua/luci/controller/admin/noderole.lua +++ /dev/null @@ -1,5 +0,0 @@ -module("luci.controller.admin.noderole", package.seeall) - -function index() - entry({"admin", "noderole"}, cbi("admin/noderole"), "Node role", 20) -end diff --git a/package/gluon-luci-node-role/files/usr/lib/lua/luci/model/cbi/admin/noderole.lua b/package/gluon-luci-node-role/files/usr/lib/lua/luci/model/cbi/admin/noderole.lua deleted file mode 100644 index e7832ad9..00000000 --- a/package/gluon-luci-node-role/files/usr/lib/lua/luci/model/cbi/admin/noderole.lua +++ /dev/null @@ -1,34 +0,0 @@ -local f, s, o -local site = require 'gluon.site_config' -local i18n = require "luci.i18n" -local uci = luci.model.uci.cursor() -local config = 'gluon-node-info' - --- where to read the configuration from -local role = uci:get(config, uci:get_first(config, "system"), "role") - -f = SimpleForm("role", i18n.translate("Node role")) -f.template = "admin/expertmode" - -s = f:section(SimpleSection, nil, i18n.translate( - "If this node has a special role within the freifunk network you can specify this role here. " - .. "Please find out about the available roles and their impact first. " - .. "Only change the role if you know what you are doing.")) - -o = s:option(ListValue, "role", i18n.translate("Role")) -o.default = role -o.rmempty = false -for _, role in ipairs(site.roles.list) do - o:value(role, i18n.translate('gluon-luci-node-role:role:' .. role)) -end - -function f.handle(self, state, data) - if state == FORM_VALID then - uci:set(config, uci:get_first(config, "system"), "role", data.role) - - uci:save(config) - uci:commit(config) - end -end - -return f diff --git a/package/gluon-luci-node-role/i18n/fr.po b/package/gluon-luci-node-role/i18n/fr.po deleted file mode 100644 index a571f568..00000000 --- a/package/gluon-luci-node-role/i18n/fr.po +++ /dev/null @@ -1,26 +0,0 @@ -msgid "" -msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" -"Project-Id-Version: PACKAGE VERSION\n" -"PO-Revision-Date: 2015-08-19 23:30+0100\n" -"Last-Translator:Tobias Bernot \n" -"Language-Team: French\n" -"Language: fr\n" -"MIME-Version: 1.0\n" -"Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgid "Node role" -msgstr "Rôle du nœud" - -msgid "Role" -msgstr "Rôle" - -msgid "" -"If this node has a special role within the freifunk network you can specify " -"this role here. Please find out about the available roles and their impact " -"first. Only change the role if you know what you are doing." -msgstr "" -"Si votre nœud a un rôle spécial dans le réseau freifunk, vous pouvez spécifier ce " -"rôle ici. Avant de changer, informez vous sur les rôles disponibles et sur leur impacts. " -"Changez de rôle uniquement si vous comprenez ce que vous faites." diff --git a/package/gluon-luci-portconfig/Makefile b/package/gluon-luci-portconfig/Makefile deleted file mode 100644 index 007c5fea..00000000 --- a/package/gluon-luci-portconfig/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2013 Nils Schneider -# This is free software, licensed under the Apache 2.0 license. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-portconfig -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-portconfig - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci module for advanced ethernet port configuration - DEPENDS:=+gluon-luci-admin +gluon-mesh-batman-adv -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-portconfig,i18n) -endef - -define Package/gluon-luci-portconfig/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-portconfig,$(1)) -endef - -$(eval $(call BuildPackage,gluon-luci-portconfig)) diff --git a/package/gluon-luci-portconfig/files/usr/lib/lua/luci/controller/admin/portconfig.lua b/package/gluon-luci-portconfig/files/usr/lib/lua/luci/controller/admin/portconfig.lua deleted file mode 100644 index 037b56c8..00000000 --- a/package/gluon-luci-portconfig/files/usr/lib/lua/luci/controller/admin/portconfig.lua +++ /dev/null @@ -1,19 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2013 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -module("luci.controller.admin.portconfig", package.seeall) - -function index() - entry({"admin", "portconfig"}, cbi("admin/portconfig"), _("Network"), 20) -end diff --git a/package/gluon-luci-portconfig/files/usr/lib/lua/luci/model/cbi/admin/portconfig.lua b/package/gluon-luci-portconfig/files/usr/lib/lua/luci/model/cbi/admin/portconfig.lua deleted file mode 100644 index 994f3077..00000000 --- a/package/gluon-luci-portconfig/files/usr/lib/lua/luci/model/cbi/admin/portconfig.lua +++ /dev/null @@ -1,155 +0,0 @@ ---[[ -LuCI - Lua Configuration Interface - -Copyright 2014 Nils Schneider - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]]-- - -local uci = luci.model.uci.cursor() -local lutil = require 'luci.util' -local sysconfig = require 'gluon.sysconfig' - -local wan = uci:get_all("network", "wan") -local wan6 = uci:get_all("network", "wan6") -local dns = uci:get_first("gluon-wan-dnsmasq", "static") - -local f = SimpleForm("portconfig", translate("WAN connection")) -f.template = "admin/expertmode" - -local s -local o - -s = f:section(SimpleSection, nil, nil) - -o = s:option(ListValue, "ipv4", translate("IPv4")) -o:value("dhcp", translate("Automatic (DHCP)")) -o:value("static", translate("Static")) -o:value("none", translate("Disabled")) -o.default = wan.proto - -o = s:option(Value, "ipv4_addr", translate("IP address")) -o:depends("ipv4", "static") -o.value = wan.ipaddr -o.datatype = "ip4addr" -o.rmempty = false - -o = s:option(Value, "ipv4_netmask", translate("Netmask")) -o:depends("ipv4", "static") -o.value = wan.netmask or "255.255.255.0" -o.datatype = "ip4addr" -o.rmempty = false - -o = s:option(Value, "ipv4_gateway", translate("Gateway")) -o:depends("ipv4", "static") -o.value = wan.gateway -o.datatype = "ip4addr" -o.rmempty = false - - -s = f:section(SimpleSection, nil, nil) - -o = s:option(ListValue, "ipv6", translate("IPv6")) -o:value("dhcpv6", translate("Automatic (RA/DHCPv6)")) -o:value("static", translate("Static")) -o:value("none", translate("Disabled")) -o.default = wan6.proto - -o = s:option(Value, "ipv6_addr", translate("IP address")) -o:depends("ipv6", "static") -o.value = wan6.ip6addr -o.datatype = "ip6addr" -o.rmempty = false - -o = s:option(Value, "ipv6_gateway", translate("Gateway")) -o:depends("ipv6", "static") -o.value = wan6.ip6gw -o.datatype = "ip6addr" -o.rmempty = false - - -if dns then - s = f:section(SimpleSection, nil, nil) - - o = s:option(DynamicList, "dns", translate("Static DNS servers")) - o:write(nil, uci:get("gluon-wan-dnsmasq", dns, "server")) - o.datatype = "ipaddr" -end - -s = f:section(SimpleSection, nil, nil) - -o = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface")) -o.default = uci:get_bool("network", "mesh_wan", "auto") and o.enabled or o.disabled -o.rmempty = false - -if sysconfig.lan_ifname then - o = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface")) - o.default = uci:get_bool("network", "mesh_lan", "auto") and o.enabled or o.disabled - o.rmempty = false -end - - -function f.handle(self, state, data) - if state == FORM_VALID then - uci:set("network", "wan", "proto", data.ipv4) - if data.ipv4 == "static" then - uci:set("network", "wan", "ipaddr", data.ipv4_addr:trim()) - uci:set("network", "wan", "netmask", data.ipv4_netmask:trim()) - uci:set("network", "wan", "gateway", data.ipv4_gateway:trim()) - else - uci:delete("network", "wan", "ipaddr") - uci:delete("network", "wan", "netmask") - uci:delete("network", "wan", "gateway") - end - - uci:set("network", "wan6", "proto", data.ipv6) - if data.ipv6 == "static" then - uci:set("network", "wan6", "ip6addr", data.ipv6_addr:trim()) - uci:set("network", "wan6", "ip6gw", data.ipv6_gateway:trim()) - else - uci:delete("network", "wan6", "ip6addr") - uci:delete("network", "wan6", "ip6gw") - end - - uci:set("network", "mesh_wan", "auto", data.mesh_wan) - - if sysconfig.lan_ifname then - uci:set("network", "mesh_lan", "auto", data.mesh_lan) - - local doit - if data.mesh_lan == '1' then - doit = uci.remove_from_set - else - doit = uci.add_to_set - end - - for _, lanif in ipairs(lutil.split(sysconfig.lan_ifname, ' ')) do - doit(uci, "network", "client", "ifname", lanif) - end - end - - uci:save("network") - uci:commit("network") - - if dns then - if #data.dns > 0 then - uci:set("gluon-wan-dnsmasq", dns, "server", data.dns) - else - uci:delete("gluon-wan-dnsmasq", dns, "server") - end - - uci:save("gluon-wan-dnsmasq") - uci:commit("gluon-wan-dnsmasq") - end - end - - return true -end - -return f diff --git a/package/gluon-luci-private-wifi/Makefile b/package/gluon-luci-private-wifi/Makefile deleted file mode 100644 index 604929dd..00000000 --- a/package/gluon-luci-private-wifi/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-private-wifi -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-private-wifi - SECTION:=gluon - CATEGORY:=Gluon - DEPENDS:=+gluon-luci-admin - TITLE:=UI for activating a private WLAN -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-private-wifi,i18n) -endef - -define Package/gluon-luci-private-wifi/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-private-wifi,$(1)) -endef - -$(eval $(call BuildPackage,gluon-luci-private-wifi)) diff --git a/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/controller/admin/privatewifi.lua b/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/controller/admin/privatewifi.lua deleted file mode 100644 index e11ba58b..00000000 --- a/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/controller/admin/privatewifi.lua +++ /dev/null @@ -1,5 +0,0 @@ -module("luci.controller.admin.privatewifi", package.seeall) - -function index() - entry({"admin", "privatewifi"}, cbi("admin/privatewifi"), _("Private WLAN"), 10) -end diff --git a/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua b/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua deleted file mode 100644 index 788ff430..00000000 --- a/package/gluon-luci-private-wifi/files/usr/lib/lua/luci/model/cbi/admin/privatewifi.lua +++ /dev/null @@ -1,63 +0,0 @@ -local f, s, o, ssid -local uci = luci.model.uci.cursor() -local config = 'wireless' - --- where to read the configuration from -local primary_iface = 'wan_radio0' -local ssid = uci:get(config, primary_iface, "ssid") - -f = SimpleForm("wifi", translate("Private WLAN")) -f.template = "admin/expertmode" - -s = f:section(SimpleSection, nil, translate( - 'Your node can additionally extend your private network by bridging the WAN interface ' - .. 'with a separate WLAN. This feature is completely independent of the mesh functionality. ' - .. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled ' - .. 'at the same time.' -)) - -o = s:option(Flag, "enabled", translate("Enabled")) -o.default = (ssid and not uci:get_bool(config, primary_iface, "disabled")) and o.enabled or o.disabled -o.rmempty = false - -o = s:option(Value, "ssid", translate("Name (SSID)")) -o:depends("enabled", '1') -o.default = ssid - -o = s:option(Value, "key", translate("Key"), translate("8-63 characters")) -o:depends("enabled", '1') -o.datatype = "wpakey" -o.default = uci:get(config, primary_iface, "key") - -function f.handle(self, state, data) - if state == FORM_VALID then - uci:foreach(config, "wifi-device", - function(s) - local device = s['.name'] - local name = "wan_" .. device - - if data.enabled == '1' then - -- set up WAN wifi-iface - uci:section(config, "wifi-iface", name, - { - device = device, - network = "wan", - mode = 'ap', - encryption = 'psk2', - ssid = data.ssid, - key = data.key, - disabled = 0, - } - ) - else - -- disable WAN wifi-iface - uci:set(config, name, "disabled", 1) - end - end) - - uci:save(config) - uci:commit(config) - end -end - -return f diff --git a/package/gluon-luci-theme/Makefile b/package/gluon-luci-theme/Makefile deleted file mode 100644 index 4fc947c4..00000000 --- a/package/gluon-luci-theme/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2013 Nils Schneider -# This is free software, licensed under the Apache 2.0 license. - -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-theme -PKG_VERSION:=0.1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Package/gluon-luci-theme - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Luci theme for Gluon - DEPENDS:= -endef - -define Package/gluon-luci-theme/description - Luci based config mode -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-luci-theme/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-luci-theme)) diff --git a/package/gluon-luci-theme/files/etc/uci-defaults/luci-theme-gluon b/package/gluon-luci-theme/files/etc/uci-defaults/luci-theme-gluon deleted file mode 100755 index 795bd186..00000000 --- a/package/gluon-luci-theme/files/etc/uci-defaults/luci-theme-gluon +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -uci batch <<-EOF - set luci.themes.Gluon=/luci-static/gluon - commit luci -EOF - diff --git a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/footer.htm b/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/footer.htm deleted file mode 100644 index 6b709030..00000000 --- a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/footer.htm +++ /dev/null @@ -1,19 +0,0 @@ -<%# -LuCI - Lua Configuration Interface -Copyright 2008 Steven Barth -Copyright 2008 Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - --%> - - - - - diff --git a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm b/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm deleted file mode 100644 index 2fe1004b..00000000 --- a/package/gluon-luci-theme/files/usr/lib/lua/luci/view/themes/gluon/header.htm +++ /dev/null @@ -1,168 +0,0 @@ -<%# -LuCI - Lua Configuration Interface -Copyright 2008 Steven Barth -Copyright 2008-2010 Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - --%> -<% - local sys = require "luci.sys" - local http = require "luci.http" - local disp = require "luci.dispatcher" - local fs = require "nixio.fs" - - local hostname = sys.hostname() - local release = fs.readfile("/lib/gluon/release") - - local request = disp.context.path - local request2 = disp.context.request - - local category = request[1] - local cattree = category and disp.node(category) - - local leaf = request2[#request2] - - local tree = disp.node() - local node = disp.context.dispatched - - local categories = disp.node_childs(tree) - - local c = tree - local i, r - - -- tag all nodes leading to this page - for i, r in ipairs(request) do - if c.nodes and c.nodes[r] then - c = c.nodes[r] - c._menu_selected = true - end - end - - http.prepare_content("application/xhtml+xml") - - local function nodeurl(prefix, name, query) - local url = controller .. prefix .. name .. "/" - if query then - url = url .. http.build_querystring(query) - end - return pcdata(url) - end - - local function subtree(prefix, node, level) - if not level then - level = 1 - end - - local childs = disp.node_childs(node) - if #childs > 0 then -%> -
-
    - <% - local selected_node - local selected_name - local i, v - - for i, v in ipairs(childs) do - local nnode = node.nodes[v] - if nnode._menu_selected then - selected_node = nnode - selected_name = v - end - %> -
  • - <%=striptags(translate(nnode.title))%> -
  • - <% - end - %> -
-
-<% - if selected_node then - subtree(prefix .. selected_name .. "/", selected_node, level + 1) - end -%> -
-<% - end - end --%> - - - - - - - - -<% if node and node.css then %> -<% end -%> -<% if css then %> -<% end -%> - -<%=striptags( hostname .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> - LuCI - - - - - -
- <% if category then subtree("/" .. category .. "/", cattree) end %> - -
- diff --git a/package/gluon-luci-theme/files/www/luci-static/gluon/cascade.css b/package/gluon-luci-theme/files/www/luci-static/gluon/cascade.css deleted file mode 100644 index eb9833df..00000000 --- a/package/gluon-luci-theme/files/www/luci-static/gluon/cascade.css +++ /dev/null @@ -1,2 +0,0 @@ -.lang_he{direction:RTL;unicode-bidi:embed}.hidden{display:none}html{min-height:100%;height:auto;position:relative}body,input,select,option{font-family:'Open Sans', Arial, sans-serif;font-size:12pt}body{color:#4d4e53;line-height:1.5em;margin:0;display:flex;flex-direction:column;min-height:100vh;background-color:#f3f3f3}a img{border:none;text-decoration:none}.tabmenu1{text-align:center}ul.tabmenu{list-style:none;padding:0;margin:2em 0;display:inline-flex}ul.tabmenu li{white-space:nowrap;margin:0 0.5em;padding:0;text-align:center}ul.tabmenu li a{display:block;text-decoration:none;padding:1em;margin:0;color:#333;border-radius:2em}ul.tabmenu li a:hover{background:#ffe9b3}ul.tabmenu li.active a{font-weight:bold;background:white;color:#333}abbr,acronym{font-style:normal;font-variant:normal}abbr[title],acronym[title]{border-bottom:1px dotted;cursor:help}a:link abbr[title],a:visited abbr[title],a:link acronym[title],a:visited acronym[title]{cursor:pointer}code{font-family:monospace;white-space:pre}#maincontent ul{margin-left:2em}.warning{color:red;background-color:white;font-weight:bold}.clear{clear:both}.error{color:#ff0000;background-color:white}div.hostinfo{margin:0;padding:0;font-size:80%;padding:0.5em;flex:1;font-weight:bold}#xhr_poll_status{cursor:pointer}#xhr_poll_status #xhr_poll_status_off{font-weight:bold;color:#FF0000}#xhr_poll_status #xhr_poll_status_on{font-weight:bold;color:#00FF00}#menubar{display:flex;background:#dc0067;color:#ffffff}#menubar .warning{color:red;background-color:#557788}#menubar a:link,#menubar a:visited{position:relative;display:block;padding:0.5em;text-decoration:none;font-size:80%;font-weight:normal;color:white}#menubar a:link:hover,#menubar a:visited:hover,#menubar a:link:focus,#menubar a:visited:focus{background:#ffb400;color:black}#menubar a:link.active,#menubar a:visited.active{background:#ffb400;color:black;font-weight:bold}#menubar a:link.warning,#menubar a:visited.warning{background:#000000;color:red;font-weight:bold}#modemenu{list-style:none;margin:0;padding:0}#modemenu li{display:inline-block}.lang_de #submenu_admin_uci{width:12em}.lang_ru #submenu_admin_uci{width:11.5em}textarea#syslog{width:98%;min-height:500px;border:3px solid #cccccc;padding:5px;font-family:monospace}#maincontent{padding:0 1em 2em;max-width:60em;min-width:40em;margin:1em auto}.lang_he #maincontent{direction:rtl}#maincontent p{margin-bottom:1em}.cbi-section{margin:0;padding:0;border:none}.cbi-section legend{font-size:1.4em;font-weight:bold;position:relative;padding:0;margin-bottom:0.5em}.cbi-section h2{margin:0em 0 0.5em -0.5em !important}.cbi-section h3{text-decoration:none !important;font-weight:bold !important;color:#555555 !important;margin:0.25em !important;font-size:100% !important}.cbi-section-descr{margin-bottom:2em}.cbi-title-ref{color:inherit;text-decoration:none;padding-right:18px;background:url("../resources/cbi/link.gif") no-repeat scroll right center;background-color:inherit}ul.cbi-apply{font-size:90%}input:-webkit-input-placeholder{color:#AAAAAA}input:-moz-placeholder{color:#AAAAAA}input:-ms-input-placeholder{color:#AAAAAA}input[type=checkbox]{display:none}input[type=checkbox]+label{display:inline-block;width:1em;height:1em;margin:0}input[type=checkbox]:checked+label:after{content:'✔';color:#dc0067;vertical-align:middle;position:absolute;top:50%;left:0;margin-top:-0.5em;width:100%;text-align:center;font-size:1.7em}input[type=submit],input[type=reset],input[type=image],input[type=button]{cursor:pointer}select,input,textarea,input[type=checkbox]+label{color:#003247;border:none;background:#ffe199;border-radius:3pt;padding:0.5em}input[type=image]{border:none}select,input[type=text],input[type=password]{width:20em}td select,td input[type=text],td input[type=password]{width:99%}img.cbi-image-button{cursor:pointer;margin:0 2px;vertical-align:middle}input.cbi-button{display:inline-block;zoom:1;line-height:normal;white-space:nowrap;vertical-align:baseline;text-align:center;cursor:pointer;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;font-size:100%;padding:0.5em 1em;color:rgba(0,0,0,0.8);border:none transparent;background-color:#E6E6E6;text-decoration:none;border-radius:2px;-webkit-transition:0.1s linear -webkit-box-shadow;-moz-transition:0.1s linear -moz-box-shadow;-ms-transition:0.1s linear box-shadow;-o-transition:0.1s linear box-shadow;transition:0.1s linear box-shadow;margin-left:0.5em;background-repeat:no-repeat}input.cbi-button::-moz-focus-inner{padding:0;border:0}input.cbi-button:active{box-shadow:0 0 0 1px rgba(0,0,0,0.15) inset,0 0 6px rgba(0,0,0,0.2) inset}input.cbi-button:focus{outline:0}input.cbi-button:hover,input.cbi-button:focus{background-image:-webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0,0.05)), to(rgba(0,0,0,0.1)));background-image:-webkit-linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1));background-image:-moz-linear-gradient(top, rgba(0,0,0,0.05) 0%, rgba(0,0,0,0.1));background-image:-o-linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1));background-image:linear-gradient(transparent, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1))}input.cbi-button[disabled]{border:none;background-image:none;opacity:0.40;cursor:not-allowed;box-shadow:none}input.cbi-input-user{background-image:url("../resources/cbi/user.gif");background-repeat:no-repeat;background-position:1px center;color:#000000;text-indent:17px}input.cbi-input-find,input.cbi-button-find{background-image:url("../resources/cbi/find.gif");color:#000000;padding-left:17px}input.cbi-input-reload{background-image:url("../resources/cbi/reload.gif");color:#000000;padding-left:17px}input.cbi-input-add,input.cbi-button-add{background-image:url("../resources/cbi/add.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-input-fieldadd,input.cbi-button-fieldadd{background-image:url(../resources/cbi/fieldadd.gif);color:#000000;padding-left:17px;padding-right:1px}input.cbi-input-reset,input.cbi-button-reset{background-color:#e30;color:#fff}input.cbi-input-save,input.cbi-button-save{background-color:#009ee0;color:#fff}input.cbi-input-apply,input.cbi-button-apply{background-color:#009ee0;color:#fff}input.cbi-input-link,input.cbi-button-link{background-image:url("../resources/cbi/link.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-input-download,input.cbi-button-download{background-image:url("../resources/cbi/download.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-input-remove,div.cbi-section-remove input{background-image:url("../resources/cbi/remove.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-button-up{background-image:url("../resources/cbi/up.gif");padding-left:11px;padding-right:1px}input.cbi-button-down{background-image:url("../resources/cbi/down.gif");padding-left:11px;padding-right:1px}input.cbi-button-edit{background-image:url("../resources/cbi/edit.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-button-reload{background-image:url("../resources/cbi/reload.gif");color:#000000;padding-left:17px;padding-right:1px}input.cbi-button-remove{background-image:url("../resources/cbi/remove.gif");color:#000000;padding-left:17px;padding-right:1px}.cbi-input-invalid{background:#e30 !important;color:white}div.cbi-section-remove input{border-bottom:none}textarea{margin-left:-1px;margin-bottom:0.5em}table td,table th{color:#000000}table.smalltext{background:#f5f5f5;color:#000000;border-top:1px solid #666666;border-right:1px solid #666666;border-bottom:1px solid #666666;font-size:90%;width:80%;margin-left:auto;margin-right:auto;border-collapse:collapse}table.smalltext tr:hover td{background-color:#bbddee;color:#000000}table.smalltext tr th{padding:0 0.25em;border-left:1px solid #666666;text-align:left}table.smalltext tr td{padding:0 0.25em;border-top:1px solid #666666;border-left:1px solid #666666}table.cbi-section-table .cbi-rowstyle-1{background-color:#eeeeff;color:#000000}table.cbi-section-table .cbi-rowstyle-1:hover,table.cbi-section-table .cbi-rowstyle-2:hover{background-color:#b2c8d4;color:#000000}table.cbi-section-table .cbi-section-table-cell{padding:3px;white-space:nowrap}.cbi-section .cbi-rowstyle-1 h3{background-color:#eeeeff;color:#555555}.cbi-rowstyle-2{color:#000000}div.cbi-value{display:flex;flex-direction:row;margin-bottom:0.5em}.cbi-value-title{flex:2;text-align:right;padding-right:1em;font-weight:bold}div.cbi-value-field{flex:3;position:relative}div.cbi-value-field input,div.cbi-value-field select,div.cbi-value-field input+label{position:relative;top:-0.39em}div.cbi-value-field-long{flex:10;position:relative}div.cbi-value-field-long input,div.cbi-value-field-long select,div.cbi-value-field-long input+label{position:relative;top:-0.39em}div.cbi-value-field-long-after{flex:2}div.cbi-value-description{font-size:8pt}div.cbi-section-create{clear:left;white-space:nowrap;vertical-align:top}div.cbi-section-create .cbi-button{margin:0.25em}input.cbi-section-create-name{margin-right:-0.25em}div.cbi-map-descr{margin-bottom:1em}.cbi-map-descr:empty,.cbi-section-descr:empty{display:none}.cbi-map-descr,.cbi-section-descr,.cbi-page-actions{padding:1em;background:#ececec}.cbi-page-actions{text-align:right;display:flex;display:-moz-flex;-moz-flex-flow:row-reverse;flex-flow:row-reverse}div.cbi-optionals{padding:0.25em;border-bottom:1px dotted #bbbbbb}div.cbi-section-remove{float:right}.cbi-section-node{clear:both;position:relative;border:none}.cbi-section-node-tabbed{border-top-left-radius:0}.cbi-section-node .cbi-value-last{border-bottom:none}.cbi-section-node table div{padding-bottom:0;border-bottom:none}.cbi-section-node div.cbi-section-table-row{margin:0.25em}table.cbi-section-table{width:100%;font-size:95%}table.cbi-section-table th,table.cbi-section-table td{text-align:center}tr.cbi-section-table-descr th{font-weight:normal;font-size:90%;vertical-align:top}td.cbi-section-table-optionals{text-align:left !important;padding-top:1em}.cbi-value-helpicon img{display:none}div.cbi-error{font-size:95%;font-weight:bold;color:#ff0000;background-color:#ffffff}td.cbi-value-error{border-color:red}.cbi-value-error input,.cbi-value-error select{background-color:#ffcccc}.cbi-section-error{color:red;background-color:white;font-size:95%;border:1px dotted red;margin:3px;padding:3px}.cbi-value-field var{color:#2222FF}ul.cbi-tabmenu{padding:3px 0;margin-left:0 !important;list-style-type:none;position:relative;z-index:10;top:4px;line-height:20px}ul.cbi-tabmenu li.cbi-tab,ul.cbi-tabmenu li.cbi-tab-disabled{display:inline;margin:0}ul.cbi-tabmenu li.cbi-tab a,ul.cbi-tabmenu li.cbi-tab-disabled a{text-decoration:none;padding:3px 7px;margin-right:3px;border:1px solid #BBBBBB;border-bottom:none;border-radius:3px 3px 0 0;background-color:#EEEEEE;color:#BBBBBB}ul.cbi-tabmenu li.cbi-tab-highlighted a{color:#000000;background-color:#FFEEAA}ul.cbi-tabmenu li a:hover{color:#000000}ul.cbi-tabmenu li.cbi-tab a{padding-top:4px;color:#000000;background-color:#FFFFFF}div.cbi-tab-descr{background-image:url(/luci-static/resources/cbi/help.gif);background-position:0.25em 50%;background-repeat:no-repeat;border-bottom:1px solid #CCCCCC;margin:0.25em 0.25em 2em;padding:0.5em 0.5em 0.5em 2em}.left{text-align:left !important}.right{text-align:right !important}.luci{position:absolute;bottom:0;left:1em;height:1.5em;font-size:80%}.luci a:link,.luci a:visited{background-color:transparent;color:#666666;text-decoration:none;font-size:70%}.inline{display:inline}.error500{white-space:normal;border:1px dotted #ff0000;background-color:#ffffff;color:#000000;padding:0.5em}.errorbox{border:1px solid #FF0000;background-color:#FFCCCC;padding:5px;margin-bottom:5px}.errorbox a{color:#000000 !important}.ifacebox{background-color:#FFFFFF;border:1px solid #CCCCCC;margin:0 10px;text-align:center;white-space:nowrap}.ifacebox .ifacebox-head{border-bottom:1px solid #CCCCCC;padding:2px}.ifacebox .ifacebox-body{padding:2px}.ifacebadge{background-color:#FFFFFF;border:1px solid #CCCCCC;padding:2px;margin-left:2px;display:inline-block}.ifacebadge-active{border-color:#000000;font-weight:bold}.zonebadge{padding:2px;display:inline-block;white-space:nowrap;cursor:pointer}.zonebadge em,.zonebadge strong{margin:3px;display:inline-block}.zonebadge input{width:6em;height:1.5em}.zonebadge-empty{border:1px dashed #AAAAAA;color:#AAAAAA;font-style:italic;font-size:smaller}.uci-change-list{font-family:monospace}.uci-change-list ins,.uci-change-legend-label ins{text-decoration:none;border:1px solid #00FF00;background-color:#CCFFCC;display:block;padding:2px}.uci-change-list del,.uci-change-legend-label del{text-decoration:none;border:1px solid #FF0000;background-color:#FFCCCC;display:block;font-style:normal;padding:2px}.uci-change-list var,.uci-change-legend-label var{text-decoration:none;border:1px solid #CCCCCC;background-color:#EEEEEE;display:block;font-style:normal;padding:2px}.uci-change-list var ins,.uci-change-list var del{border:none;white-space:pre;font-style:normal;padding:0px}.uci-change-legend{padding:5px}.uci-change-legend-label{width:150px;float:left;font-size:80%}.uci-change-legend-label>ins,.uci-change-legend-label>del,.uci-change-legend-label>var{float:left;margin-right:4px;width:10px;height:10px;display:block}.uci-change-legend-label var ins,.uci-change-legend-label var del{line-height:6px;border:none}.cbi-input-password+img{display:none}.the-key{text-align:left;font-size:1.4em;background:#ffe9b3;border:3pt dashed #dc0067;margin-bottom:0.5em;padding:0.5em} -/*# sourceMappingURL=cascade.css.map */ diff --git a/package/gluon-luci-theme/sass/cascade.scss b/package/gluon-luci-theme/sass/cascade.scss deleted file mode 100644 index bfcfc58c..00000000 --- a/package/gluon-luci-theme/sass/cascade.scss +++ /dev/null @@ -1,1029 +0,0 @@ -/* ATTENTION: This file is not compiled when building gluon. - The compiled version is at ../files/www/luci-static/gluon/cascade.css - - Use sass like this to update it: - - sass cascade.scss ../files/www/luci-static/gluon/cascade.css - - When commiting changes to this file make sure to commit the respective - changes to the compilid version within the same commit! - */ - -@charset "utf-8"; - -$ffyellow: #ffb400; -$ffmagenta: #dc0067; -$ffzusatz: #009ee0; -$red: #ee3300; - -@mixin button { - &::-moz-focus-inner { - padding: 0; - border: 0; - } - - display: inline-block; - zoom: 1; - line-height: normal; - white-space: nowrap; - vertical-align: baseline; - text-align: center; - cursor: pointer; - -webkit-user-drag: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - - font-size: 100%; - padding: 0.5em 1em; - color: rgba(0, 0, 0, 0.80); - border: none rgba(0, 0, 0, 0); - background-color: #E6E6E6; - text-decoration: none; - border-radius: 2px; - - /* Transitions */ - -webkit-transition: 0.1s linear -webkit-box-shadow; - -moz-transition: 0.1s linear -moz-box-shadow; - -ms-transition: 0.1s linear box-shadow; - -o-transition: 0.1s linear box-shadow; - transition: 0.1s linear box-shadow; - - &:active { - box-shadow: 0 0 0 1px rgba(0,0,0, 0.15) inset, 0 0 6px rgba(0,0,0, 0.20) inset; - } - - &:focus { - outline: 0; - } - - &:hover, &:focus { - background-image: -webkit-gradient(linear, 0 0, 0 100%, from(transparent), color-stop(40%, rgba(0,0,0, 0.05)), to(rgba(0,0,0, 0.10))); - background-image: -webkit-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10)); - background-image: -moz-linear-gradient(top, rgba(0,0,0, 0.05) 0%, rgba(0,0,0, 0.10)); - background-image: -o-linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10)); - background-image: linear-gradient(transparent, rgba(0,0,0, 0.05) 40%, rgba(0,0,0, 0.10)); - } - - &[disabled] { - border: none; - background-image: none; - opacity: 0.40; - cursor: not-allowed; - box-shadow: none; - } -} - -@mixin button-primary { - background-color: $ffzusatz; - color: #fff; -} - -.lang_he { - direction: RTL; - unicode-bidi: embed; -} - -.hidden { - display: none; -} - -html { - min-height: 100%; - height: auto; - position:relative; -} - -body, input, select, option { - font-family: 'Open Sans', Arial, sans-serif; - font-size: 12pt; -} - -body { - color: rgb(77, 78, 83); - line-height: 1.5em; - margin: 0; - display: flex; - flex-direction: column; - min-height: 100vh; - background-color: #f3f3f3; -} - -a img { - border: none; - text-decoration: none; -} - -.tabmenu1 { - text-align: center; -} - -ul.tabmenu { - list-style: none; - padding: 0; - margin: 2em 0; - display: inline-flex; -} - -ul.tabmenu li { - white-space: nowrap; - margin: 0 0.5em; - padding: 0; - text-align: center; - - a { - display: block; - text-decoration: none; - padding: 1em; - margin: 0; - color: #333; - border-radius: 2em; - - &:hover { - background: lighten($ffyellow, 35); - } - } - - &.active a { - font-weight: bold; - background: white; - color: #333; - } -} - -abbr, -acronym { - font-style: normal; - font-variant: normal; -} - -abbr[title], -acronym[title] { - border-bottom: 1px dotted; - cursor: help; -} - -a:link abbr[title], -a:visited abbr[title], -a:link acronym[title], -a:visited acronym[title] { - cursor: pointer; -} - -code { - font-family: monospace; - white-space: pre; -} - -#maincontent ul { - margin-left: 2em; -} - -.warning { - color: red; - background-color: white; - font-weight: bold; -} - -.clear { - clear: both; -} - -.error { - color: #ff0000; - background-color: white; -} - -div.hostinfo { - margin: 0; - padding: 0; - font-size: 80%; - padding: 0.5em; - flex: 1; - font-weight: bold; -} - -#xhr_poll_status { - cursor: pointer; -} - -#xhr_poll_status #xhr_poll_status_off { - font-weight: bold; - color: #FF0000; -} - -#xhr_poll_status #xhr_poll_status_on { - font-weight: bold; - color: #00FF00; -} - -#menubar { - display: flex; - background: $ffmagenta; - color: #ffffff; -} - -#menubar .warning { - color: red; - background-color: #557788; -} - -#menubar a:link, -#menubar a:visited { - position: relative; - display: block; - padding: 0.5em; - text-decoration: none; - font-size: 80%; - font-weight: normal; - color: white; -} - -#menubar a:link:hover, -#menubar a:visited:hover, -#menubar a:link:focus, -#menubar a:visited:focus { - background: $ffyellow; - color: black; -} - -#menubar a:link.active, -#menubar a:visited.active { - background: $ffyellow; - color: black; - font-weight: bold; -} - -#menubar a:link.warning, -#menubar a:visited.warning { - background: #000000; - color: red; - font-weight: bold; -} - -#modemenu { - list-style: none; - margin: 0; - padding: 0; -} - -#modemenu li { - display: inline-block; -} - -#savemenu { -} - -.lang_he #savemenu { -} - -.lang_de #submenu_admin_uci { - width: 12em; -} - -.lang_ru #submenu_admin_uci { - width: 11.5em; -} - -textarea#syslog { - width: 98%; - min-height: 500px; - border: 3px solid #cccccc; - padding: 5px; - font-family: monospace; -} - -#maincontent { - padding: 0 1em 2em; - max-width: 60em; - min-width: 40em; - margin: 1em auto; -} - -.lang_he #maincontent { - direction: rtl; -} - -#maincontent h2 { -} - -#maincontent h3 { -} - -#maincontent p { - margin-bottom: 1em; -} - -.cbi-section { - margin: 0; - padding: 0; - border: none; -} - -.cbi-section legend { - font-size: 1.4em; - font-weight: bold; - position: relative; - padding: 0; - margin-bottom: 0.5em; -} - -.cbi-section h2 { - margin: 0em 0 0.5em -0.5em !important; -} - -.cbi-section h3 { - text-decoration: none !important; - font-weight: bold !important; - color: #555555 !important; - margin: 0.25em !important; - font-size: 100% !important; -} - -.cbi-section-descr { - margin-bottom: 2em; -} - -.cbi-title-ref { - color: inherit; - text-decoration: none; - padding-right: 18px; - background: url('../resources/cbi/link.gif') no-repeat scroll right center; - background-color: inherit; -} - -ul.cbi-apply { - font-size: 90%; -} - -input:-webkit-input-placeholder { - color: #AAAAAA; -} - -input:-moz-placeholder { - color: #AAAAAA; -} - -input:-ms-input-placeholder { - color: #AAAAAA; -} - -input[type=checkbox] { - display: none; - - & + label { - display: inline-block; - width: 1em; - height: 1em; - margin: 0; - } - - &:checked + label:after { - content: '✔'; - color: $ffmagenta; - vertical-align: middle; - position: absolute; - top: 50%; - left: 0; - margin-top: -0.5em; - width: 100%; - text-align: center; - font-size: 1.7em; - } -} - -input[type=submit], -input[type=reset], -input[type=image], -input[type=button] { - cursor: pointer; -} - -select, -input, -textarea, -input[type=checkbox] + label { - color: darken($ffzusatz, 30); - border: none; - background: lighten($ffyellow, 30); - border-radius: 3pt; - padding: 0.5em; -} - -input[type=image] { - border: none; -} - -select, -input[type=text], -input[type=password] { - width: 20em; -} - -td select, -td input[type=text], -td input[type=password] { - width: 99%; -} - -img.cbi-image-button { - cursor: pointer; - margin: 0 2px; - vertical-align: middle; -} - -input.cbi-button { - @include button; - - margin-left: 0.5em; - background-repeat: no-repeat; -} - -input.cbi-input-user { - background-image: url('../resources/cbi/user.gif'); - background-repeat: no-repeat; - background-position: 1px center; - color: #000000; - text-indent: 17px; -} - -input.cbi-input-find, -input.cbi-button-find { - background-image: url('../resources/cbi/find.gif'); - color: #000000; - padding-left: 17px; -} - -input.cbi-input-reload { - background-image: url('../resources/cbi/reload.gif'); - color: #000000; - padding-left: 17px; -} - -input.cbi-input-add, -input.cbi-button-add { - background-image: url('../resources/cbi/add.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-input-fieldadd, -input.cbi-button-fieldadd { - background-image: url(../resources/cbi/fieldadd.gif); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-input-reset, -input.cbi-button-reset { - background-color: $red; - color: #fff; -} - -input.cbi-input-save, -input.cbi-button-save { - @include button-primary; -} - -input.cbi-input-apply, -input.cbi-button-apply { - @include button-primary; -} - -input.cbi-input-link, -input.cbi-button-link { - background-image: url('../resources/cbi/link.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-input-download, -input.cbi-button-download { - background-image: url('../resources/cbi/download.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-input-remove, -div.cbi-section-remove input { - background-image: url('../resources/cbi/remove.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-button-up { - background-image: url('../resources/cbi/up.gif'); - padding-left: 11px; - padding-right: 1px; -} - -input.cbi-button-down { - background-image: url('../resources/cbi/down.gif'); - padding-left: 11px; - padding-right: 1px; -} - -input.cbi-button-edit { - background-image: url('../resources/cbi/edit.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-button-reload { - background-image: url('../resources/cbi/reload.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -input.cbi-button-remove { - background-image: url('../resources/cbi/remove.gif'); - color: #000000; - padding-left: 17px; - padding-right: 1px; -} - -.cbi-input-invalid { - background: $red !important; - color: white; -} - -div.cbi-section-remove input { - border-bottom: none; -} - -textarea { - margin-left: -1px; - margin-bottom: 0.5em; -} - -table td, -table th { - color: #000000; -} - -table.smalltext { - background: #f5f5f5; - color: #000000; - border-top: 1px solid #666666; - border-right: 1px solid #666666; - border-bottom: 1px solid #666666; - font-size: 90%; - width: 80%; - margin-left: auto; - margin-right: auto; - border-collapse: collapse; -} - -table.smalltext tr:hover td { - background-color: #bbddee; - color: #000000; -} - -table.smalltext tr th { - padding: 0 0.25em; - border-left: 1px solid #666666; - text-align: left; -} - -table.smalltext tr td { - padding: 0 0.25em; - border-top: 1px solid #666666; - border-left: 1px solid #666666; -} - -table.cbi-section-table .cbi-rowstyle-1 { - background-color: #eeeeff; - color: #000000; -} - -table.cbi-section-table .cbi-rowstyle-1:hover, -table.cbi-section-table .cbi-rowstyle-2:hover { - background-color: #b2c8d4; - color: #000000; -} - -table.cbi-section-table .cbi-section-table-cell { - padding: 3px; - white-space: nowrap; -} - -.cbi-section .cbi-rowstyle-1 h3 { - background-color: #eeeeff; - color: #555555; -} - -.cbi-rowstyle-2 { - color: #000000; -} - -div.cbi-value { - display: flex; - flex-direction: row; - margin-bottom: 0.5em; -} - -.cbi-value-title { - flex: 2; - text-align: right; - padding-right: 1em; - font-weight: bold; -} - -div.cbi-value-field { - flex: 3; - position: relative; - - input, select, input + label { - position: relative; - top: -0.39em; - } -} - -div.cbi-value-field-long { - flex: 10; - position: relative; - - - input, select, input + label { - position: relative; - top: -0.39em; - } -} - -div.cbi-value-field-long-after { - flex: 2; -} - -div.cbi-value-description { - font-size: 8pt; -} - -div.cbi-section-create { - clear: left; - white-space: nowrap; - vertical-align: top; -} - -div.cbi-section-create .cbi-button { - margin: 0.25em; -} - -input.cbi-section-create-name { - margin-right: -0.25em; -} - -div.cbi-map-descr { - margin-bottom: 1em; -} - -.cbi-map-descr:empty, .cbi-section-descr:empty { - display: none; -} - -.cbi-map-descr, .cbi-section-descr, .cbi-page-actions { - padding: 1em; - background: #ececec; -} - -.cbi-page-actions { - text-align: right; - display: flex; - display: -moz-flex; - -moz-flex-flow: row-reverse; - flex-flow: row-reverse; -} - -div.cbi-optionals { - padding: 0.25em; - border-bottom: 1px dotted #bbbbbb; -} - -div.cbi-section-remove { - float: right; -} - -.cbi-section-node { - clear: both; - position: relative; - border: none; -} - -.cbi-section-node-tabbed { - border-top-left-radius: 0; -} - -.cbi-section-node .cbi-value-last { - border-bottom: none; -} - -.cbi-section-node table div { - padding-bottom: 0; - border-bottom: none; -} - -.cbi-section-node div.cbi-section-table-row { - margin: 0.25em; -} - -table.cbi-section-table { - width: 100%; - font-size: 95%; -} - -table.cbi-section-table th, -table.cbi-section-table td { - text-align: center; -} - -tr.cbi-section-table-descr th { - font-weight: normal; - font-size: 90%; - vertical-align: top; -} - -td.cbi-section-table-optionals { - text-align: left !important; - padding-top: 1em; -} - -.cbi-value-helpicon img { - display: none; -} - -div.cbi-error { - font-size: 95%; - font-weight: bold; - color: #ff0000; - background-color: #ffffff; -} - -td.cbi-value-error { - border-color: red; -} - -.cbi-value-error input, -.cbi-value-error select { - background-color: #ffcccc; -} - -.cbi-section-error { - color: red; - background-color: white; - font-size: 95%; - border: 1px dotted red; - margin: 3px; - padding: 3px; -} - -.cbi-value-field var { - color: #2222FF; -} - -ul.cbi-tabmenu { - padding: 3px 0; - margin-left: 0 !important; - list-style-type: none; - position: relative; - z-index: 10; - top: 4px; - line-height: 20px; -} - -ul.cbi-tabmenu li.cbi-tab, -ul.cbi-tabmenu li.cbi-tab-disabled { - display: inline; - margin: 0; -} - -ul.cbi-tabmenu li.cbi-tab a, -ul.cbi-tabmenu li.cbi-tab-disabled a { - text-decoration: none; - padding: 3px 7px; - margin-right: 3px; - border: 1px solid #BBBBBB; - border-bottom: none; - border-radius: 3px 3px 0 0; - background-color: #EEEEEE; - color: #BBBBBB; -} - -ul.cbi-tabmenu li.cbi-tab-highlighted a { - color: #000000; - background-color: #FFEEAA; -} - -ul.cbi-tabmenu li a:hover { - color: #000000; -} - -ul.cbi-tabmenu li.cbi-tab a { - padding-top: 4px; - color: #000000; - background-color: #FFFFFF; -} - -div.cbi-tab-descr { - background-image: url(/luci-static/resources/cbi/help.gif); - background-position: 0.25em 50%; - background-repeat: no-repeat; - border-bottom: 1px solid #CCCCCC; - margin: 0.25em 0.25em 2em; - padding: 0.5em 0.5em 0.5em 2em; -} - -.left { - text-align: left !important; -} - -.right { - text-align: right !important; -} - -.luci { - position: absolute; - bottom: 0; - left: 1em; - height: 1.5em; - font-size: 80%; -} - -.luci a:link, -.luci a:visited { - background-color: transparent; - color: #666666; - text-decoration: none; - font-size: 70%; -} - -.inline { - display: inline; -} - -.error500 { - white-space: normal; - border: 1px dotted #ff0000; - background-color: #ffffff; - color: #000000; - padding: 0.5em; -} - -.errorbox { - border: 1px solid #FF0000; - background-color: #FFCCCC; - padding: 5px; - margin-bottom: 5px; -} - -.errorbox a { - color: #000000 !important; -} - - -.ifacebox { - background-color: #FFFFFF; - border: 1px solid #CCCCCC; - margin: 0 10px; - text-align: center; - white-space: nowrap; -} - -.ifacebox .ifacebox-head { - border-bottom: 1px solid #CCCCCC; - padding: 2px; -} - -.ifacebox .ifacebox-body { - padding: 2px; -} - - -.ifacebadge { - background-color: #FFFFFF; - border: 1px solid #CCCCCC; - padding: 2px; - margin-left: 2px; - display: inline-block; -} - -.ifacebadge-active { - border-color: #000000; - font-weight: bold; -} - - -.zonebadge { - padding: 2px; - display: inline-block; - white-space: nowrap; - cursor: pointer; -} - -.zonebadge em, -.zonebadge strong { - margin: 3px; - display: inline-block; -} - -.zonebadge input { - width: 6em; - height: 1.5em; -} - -.zonebadge-empty { - border: 1px dashed #AAAAAA; - color: #AAAAAA; - font-style: italic; - font-size: smaller; -} - - -.uci-change-list { - font-family: monospace; -} - -.uci-change-list ins, -.uci-change-legend-label ins { - text-decoration: none; - border: 1px solid #00FF00; - background-color: #CCFFCC; - display: block; - padding: 2px; -} - -.uci-change-list del, -.uci-change-legend-label del { - text-decoration: none; - border: 1px solid #FF0000; - background-color: #FFCCCC; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var, -.uci-change-legend-label var { - text-decoration: none; - border: 1px solid #CCCCCC; - background-color: #EEEEEE; - display: block; - font-style: normal; - padding: 2px; -} - -.uci-change-list var ins, -.uci-change-list var del { - /*display: inline;*/ - border: none; - white-space: pre; - font-style: normal; - padding: 0px; -} - -.uci-change-legend { - padding: 5px; -} - -.uci-change-legend-label { - width: 150px; - float: left; - font-size: 80%; -} - -.uci-change-legend-label>ins, -.uci-change-legend-label>del, -.uci-change-legend-label>var { - float: left; - margin-right: 4px; - width: 10px; - height: 10px; - display: block; -} - -.uci-change-legend-label var ins, -.uci-change-legend-label var del { - line-height: 6px; - border: none; -} - -// Hide show/hide password toggle image -.cbi-input-password + img { - display: none; -} - -.the-key { - text-align: left; - font-size: 1.4em; - background: lighten($ffyellow, 35); - border: 3pt dashed $ffmagenta; - margin-bottom: 0.5em; - padding: 0.5em -} diff --git a/package/gluon-luci-wifi-config/Makefile b/package/gluon-luci-wifi-config/Makefile deleted file mode 100644 index 462eab9f..00000000 --- a/package/gluon-luci-wifi-config/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-luci-wifi-config -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - -define Package/gluon-luci-wifi-config - SECTION:=gluon - CATEGORY:=Gluon - DEPENDS:=+gluon-luci-admin +libiwinfo-lua - TITLE:=UI for Wifi Settings -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile - $(call GluonBuildI18N,gluon-luci-wifi-config,i18n) -endef - -define Package/gluon-luci-wifi-config/install - $(CP) ./files/* $(1)/ - $(call GluonInstallI18N,gluon-luci-wifi-config,$(1)) -endef - -$(eval $(call BuildPackage,gluon-luci-wifi-config)) diff --git a/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/controller/admin/wifi-config.lua b/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/controller/admin/wifi-config.lua deleted file mode 100644 index 2ff1cb84..00000000 --- a/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/controller/admin/wifi-config.lua +++ /dev/null @@ -1,5 +0,0 @@ -module("luci.controller.admin.wifi-config", package.seeall) - -function index() - entry({"admin", "wifi-config"}, cbi("admin/wifi-config"), _("WLAN"), 20) -end diff --git a/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/model/cbi/admin/wifi-config.lua b/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/model/cbi/admin/wifi-config.lua deleted file mode 100644 index 060fb22b..00000000 --- a/package/gluon-luci-wifi-config/files/usr/lib/lua/luci/model/cbi/admin/wifi-config.lua +++ /dev/null @@ -1,170 +0,0 @@ -local uci = luci.model.uci.cursor() -local fs = require 'nixio.fs' -local iwinfo = require 'iwinfo' - - -local function find_phy_by_path(path) - for phy in fs.glob("/sys/devices/" .. path .. "/ieee80211/phy*") do - return phy:match("([^/]+)$") - end -end - -local function find_phy_by_macaddr(macaddr) - local addr = macaddr:lower() - for file in fs.glob("/sys/class/ieee80211/*/macaddress") do - if luci.util.trim(fs.readfile(file)) == addr then - return file:match("([^/]+)/macaddress$") - end - end -end - -local function txpower_list(phy) - local list = iwinfo.nl80211.txpwrlist(phy) or { } - local off = tonumber(iwinfo.nl80211.txpower_offset(phy)) or 0 - local new = { } - local prev = -1 - local _, val - for _, val in ipairs(list) do - local dbm = val.dbm + off - local mw = math.floor(10 ^ (dbm / 10)) - if mw ~= prev then - prev = mw - table.insert(new, { - display_dbm = dbm, - display_mw = mw, - driver_dbm = val.dbm, - }) - end - end - return new -end - - -local f = SimpleForm("wifi", translate("WLAN")) -f.template = "admin/expertmode" - -local s = f:section(SimpleSection, nil, translate( - "You can enable or disable your node's client and mesh network " - .. "SSIDs here. Please don't disable the mesh network without " - .. "a good reason, so other nodes can mesh with yours.

" - .. "It is also possible to configure the WLAN adapters transmission power " - .. "here. Please note that the transmission power values include the antenna gain " - .. "where available, but there are many devices for which the gain is unavailable or inaccurate." -)) - -local radios = {} - --- look for wifi interfaces and add them to the array -uci:foreach('wireless', 'wifi-device', - function(s) - table.insert(radios, s['.name']) - end -) - --- add a client and mesh checkbox for each interface -for _, radio in ipairs(radios) do - local config = uci:get_all('wireless', radio) - local p - - if config.hwmode == '11g' or config.hwmode == '11ng' then - p = f:section(SimpleSection, translate("2.4GHz WLAN")) - elseif config.hwmode == '11a' or config.hwmode == '11na' then - p = f:section(SimpleSection, translate("5GHz WLAN")) - end - - if p then - local o - - if uci:get('wireless', 'client_' .. radio) then - o = p:option(Flag, radio .. '_client_enabled', translate("Enable client network (access point)")) - o.default = uci:get_bool('wireless', 'client_' .. radio, "disabled") and o.disabled or o.enabled - o.rmempty = false - end - - if uci:get('wireless', 'mesh_' .. radio) then - o = p:option(Flag, radio .. '_mesh_enabled', translate("Enable mesh network (802.11s)")) - o.default = uci:get_bool('wireless', 'mesh_' .. radio, "disabled") and o.disabled or o.enabled - o.rmempty = false - end - - if uci:get('wireless', 'ibss_' .. radio) then - o = p:option(Flag, radio .. '_ibss_enabled', translate("Enable mesh network (IBSS)")) - o.default = uci:get_bool('wireless', 'ibss_' .. radio, "disabled") and o.disabled or o.enabled - o.rmempty = false - end - - local phy - - if config.path then - phy = find_phy_by_path(config.path) - elseif config.macaddr then - phy = find_phy_by_path(config.macaddr) - end - - if phy then - local txpowers = txpower_list(phy) - - if #txpowers > 1 then - local tp = p:option(ListValue, radio .. '_txpower', translate("Transmission power")) - tp.rmempty = true - tp.default = uci:get('wireless', radio, 'txpower') or 'default' - - tp:value('default', translate("(default)")) - - table.sort(txpowers, function(a, b) return a.driver_dbm > b.driver_dbm end) - - for _, entry in ipairs(txpowers) do - tp:value(entry.driver_dbm, "%i dBm (%i mW)" % {entry.display_dbm, entry.display_mw}) - end - end - end - end - -end - ---when the save-button is pushed -function f.handle(self, state, data) - if state == FORM_VALID then - - for _, radio in ipairs(radios) do - - if uci:get('wireless', 'client_' .. radio) then - local disabled = 0 - if data[radio .. '_client_enabled'] == '0' then - disabled = 1 - end - uci:set('wireless', 'client_' .. radio, "disabled", disabled) - end - - if uci:get('wireless', 'mesh_' .. radio) then - local disabled = 0 - if data[radio .. '_mesh_enabled'] == '0' then - disabled = 1 - end - uci:set('wireless', 'mesh_' .. radio, "disabled", disabled) - end - - if uci:get('wireless', 'ibss_' .. radio) then - local disabled = 0 - if data[radio .. '_ibss_enabled'] == '0' then - disabled = 1 - end - uci:set('wireless', 'ibss_' .. radio, "disabled", disabled) - end - - if data[radio .. '_txpower'] then - if data[radio .. '_txpower'] == 'default' then - uci:delete('wireless', radio, 'txpower') - else - uci:set('wireless', radio, 'txpower', data[radio .. '_txpower']) - end - end - - end - - uci:save('wireless') - uci:commit('wireless') - end -end - -return f diff --git a/package/gluon-mesh-batman-adv-14/Makefile b/package/gluon-mesh-batman-adv-14/Makefile deleted file mode 100644 index be65cafa..00000000 --- a/package/gluon-mesh-batman-adv-14/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-mesh-batman-adv-14 -PKG_VERSION:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -define Package/gluon-mesh-batman-adv-14 - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Support for batman-adv meshing (compat level 14) - DEPENDS:=+gluon-mesh-batman-adv-core +kmod-batman-adv-legacy - PROVIDES:=gluon-mesh-batman-adv -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-mesh-batman-adv-14/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-mesh-batman-adv-14)) diff --git a/package/gluon-mesh-batman-adv-14/files/lib/gluon/mesh-batman-adv-core/compat b/package/gluon-mesh-batman-adv-14/files/lib/gluon/mesh-batman-adv-core/compat deleted file mode 100644 index 8351c193..00000000 --- a/package/gluon-mesh-batman-adv-14/files/lib/gluon/mesh-batman-adv-core/compat +++ /dev/null @@ -1 +0,0 @@ -14 diff --git a/package/gluon-mesh-batman-adv-14/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-14 b/package/gluon-mesh-batman-adv-14/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-14 deleted file mode 100755 index 30e2682b..00000000 --- a/package/gluon-mesh-batman-adv-14/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-14 +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' - -local uci = require('luci.model.uci').cursor() - - -local function configure_mtu(radio, config, mtu) - if config.ibss then - local network = 'ibss_' .. radio - - if config.ibss.vlan then - uci:set('network', network, 'mtu', mtu + 4) - uci:set('network', network .. '_vlan', 'mtu', mtu) - else - uci:set('network', network, 'mtu', mtu) - end - end - - if config.mesh then - uci:set('network', 'mesh_' .. radio, 'mtu', mtu) - end -end - - -local radios = {} - -uci:foreach('wireless', 'wifi-device', - function(s) - table.insert(radios, s['.name']) - end -) - -local mtu = 1528 - -for _, radio in ipairs(radios) do - local hwmode = uci:get('wireless', radio, 'hwmode') - - if hwmode == '11g' or hwmode == '11ng' then - configure_mtu(radio, site.wifi24, mtu) - elseif hwmode == '11a' or hwmode == '11na' then - configure_mtu(radio, site.wifi5, mtu) - end -end - - -uci:save('network') diff --git a/package/gluon-mesh-batman-adv-15/Makefile b/package/gluon-mesh-batman-adv-15/Makefile deleted file mode 100644 index 14a39a61..00000000 --- a/package/gluon-mesh-batman-adv-15/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-mesh-batman-adv-15 -PKG_VERSION:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -define Package/gluon-mesh-batman-adv-15 - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Support for batman-adv meshing (compat level 15) - DEPENDS:=+gluon-mesh-batman-adv-core +kmod-batman-adv +batctl - PROVIDES:=gluon-mesh-batman-adv -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-mesh-batman-adv-15/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-mesh-batman-adv-15)) diff --git a/package/gluon-mesh-batman-adv-15/files/lib/gluon/mesh-batman-adv-core/compat b/package/gluon-mesh-batman-adv-15/files/lib/gluon/mesh-batman-adv-core/compat deleted file mode 100644 index 60d3b2f4..00000000 --- a/package/gluon-mesh-batman-adv-15/files/lib/gluon/mesh-batman-adv-core/compat +++ /dev/null @@ -1 +0,0 @@ -15 diff --git a/package/gluon-mesh-batman-adv-15/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-15 b/package/gluon-mesh-batman-adv-15/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-15 deleted file mode 100755 index 7148d42c..00000000 --- a/package/gluon-mesh-batman-adv-15/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-15 +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' - -local uci = require('luci.model.uci').cursor() - - -local function configure_mtu(radio, config, mtu) - if config.ibss then - local network = 'ibss_' .. radio - - if config.ibss.vlan then - uci:set('network', network, 'mtu', mtu + 4) - uci:set('network', network .. '_vlan', 'mtu', mtu) - else - uci:set('network', network, 'mtu', mtu) - end - end - - if config.mesh then - uci:set('network', 'mesh_' .. radio, 'mtu', mtu) - end -end - - -local radios = {} - -uci:foreach('wireless', 'wifi-device', - function(s) - table.insert(radios, s['.name']) - end -) - -local mtu = 1532 - -for _, radio in ipairs(radios) do - local hwmode = uci:get('wireless', radio, 'hwmode') - - if hwmode == '11g' or hwmode == '11ng' then - configure_mtu(radio, site.wifi24, mtu) - elseif hwmode == '11a' or hwmode == '11na' then - configure_mtu(radio, site.wifi5, mtu) - end -end - - -uci:save('network') diff --git a/package/gluon-mesh-batman-adv-core/Makefile b/package/gluon-mesh-batman-adv-core/Makefile deleted file mode 100644 index 7ae7c305..00000000 --- a/package/gluon-mesh-batman-adv-core/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-mesh-batman-adv-core -PKG_VERSION:=1 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS := respondd - -include $(GLUONDIR)/include/package.mk - -define Package/gluon-mesh-batman-adv-core - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Support for batman-adv meshing (core) - DEPENDS:=+gluon-core +libgluonutil +gluon-client-bridge +firewall +libiwinfo -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/gluon-mesh-batman-adv-core/install - $(CP) ./files/* $(1)/ - - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/mesh-batman-adv-core.so -endef - -define Package/gluon-mesh-batman-adv-core/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - - -$(eval $(call BuildPackage,gluon-mesh-batman-adv-core)) diff --git a/package/gluon-mesh-batman-adv-core/check_site.lua b/package/gluon-mesh-batman-adv-core/check_site.lua deleted file mode 100644 index 19774871..00000000 --- a/package/gluon-mesh-batman-adv-core/check_site.lua +++ /dev/null @@ -1,22 +0,0 @@ -for _, config in ipairs({'wifi24', 'wifi5'}) do - if need_table(config .. '.ibss', nil, false) then - need_string(config .. '.ibss.ssid') - need_string_match(config .. '.ibss.bssid', '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$') - need_number(config .. '.ibss.mcast_rate', false) - need_number(config .. '.ibss.vlan', false) - need_boolean(config .. '.ibss.disabled', false) - end - - if need_table(config .. '.mesh', nil, false) then - need_string(config .. '.mesh.id') - need_number(config .. '.mesh.mcast_rate', false) - need_boolean(config .. '.mesh.disabled', false) - end -end - -need_boolean('mesh_on_wan', false) -need_boolean('mesh_on_lan', false) - -if need_table('mesh', nil, false) and need_table('mesh.batman_adv', nil, false) then - need_number('mesh.batman_adv.gw_sel_class', false) -end diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan deleted file mode 100755 index be96c012..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/300-gluon-mesh-batman-adv-core-wan +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/lua - -local util = require 'gluon.util' -local uci = require('luci.model.uci').cursor() - - --- fix up duplicate mac addresses (for mesh-on-WAN) -uci:set('network', 'wan', 'macaddr', util.generate_mac(3)) -uci:save('network') - diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/310-gluon-mesh-batman-adv-core-mesh b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/310-gluon-mesh-batman-adv-core-mesh deleted file mode 100755 index ade6af57..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/310-gluon-mesh-batman-adv-core-mesh +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/lua - -local sysconfig = require 'gluon.sysconfig' -local sysctl = require 'gluon.sysctl' -local site = require 'gluon.site_config' - -local uci = require('luci.model.uci').cursor() -local lutil = require 'luci.util' - - -local gw_sel_class -if site.mesh and site.mesh.batman_adv then - gw_sel_class = site.mesh.batman_adv.gw_sel_class -end - -uci:delete('batman-adv', 'bat0') -uci:section('batman-adv', 'mesh', 'bat0', - { - orig_interval = 5000, - gw_mode = 'client', - gw_sel_class = gw_sel_class, - hop_penalty = 15, - multicast_mode = 0, - } -) -uci:save('batman-adv') - -if not uci:get('network', 'client', 'ifname') then - uci:add_to_set('network', 'client', 'ifname', 'bat0') - - if sysconfig.lan_ifname and not site.mesh_on_lan then - for _, lanif in ipairs(lutil.split(sysconfig.lan_ifname, ' ')) do - uci:add_to_set('network', 'client', 'ifname', lanif) - end - end -end - -uci:set('network', 'client', 'proto', 'dhcpv6') -uci:set('network', 'client', 'reqprefix', 'no') -uci:set('network', 'client', 'igmp_snooping', 0) -uci:set('network', 'client', 'robustness', 3) -uci:set('network', 'client', 'query_interval', 2000) -uci:set('network', 'client', 'query_response_interval', 500) -uci:set('network', 'client', 'peerdns', 1) -uci:set('network', 'client', 'sourcefilter', 0) - -uci:delete('network', 'bat0') -uci:section('network', 'interface', 'bat0', - { - ifname = 'bat0', - proto = 'none', - macaddr = sysconfig.primary_mac, - multicast_router = 2, - } -) - -uci:save('network') - - -uci:delete('firewall', 'client') -uci:section('firewall', 'zone', 'client', - { - name = 'client', - network = {'client'}, - input = 'ACCEPT', - output = 'ACCEPT', - forward = 'REJECT', - } -) - -uci:section('firewall', 'rule', 'client_dns', - { - name = 'client_dns', - src = 'client', - dest_port = '53', - target = 'REJECT', - } -) - -uci:save('firewall') - - -local dnsmasq = uci:get_first('dhcp', 'dnsmasq') -uci:set('dhcp', dnsmasq, 'boguspriv', 0) -uci:set('dhcp', dnsmasq, 'localise_queries', 0) -uci:set('dhcp', dnsmasq, 'rebind_protection', 0) - -uci:delete('dhcp', 'client') -uci:section('dhcp', 'dhcp', 'client', - { - interface = 'client', - ignore = 1, - } -) - -uci:save('dhcp') - - -sysctl.set('net.ipv6.conf.br-client.forwarding', 0) diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless deleted file mode 100755 index dd3354de..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/320-gluon-mesh-batman-adv-core-wireless +++ /dev/null @@ -1,137 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local util = require 'gluon.util' - -local uci = require('luci.model.uci').cursor() - - -local function is_disabled(name) - if uci:get('wireless', name) then - return uci:get_bool('wireless', name, 'disabled') - end -end - --- Returns the first argument that is not nil; don't call without any non-nil arguments! -local function first_non_nil(first, ...) - if first ~= nil then - return first - else - return first_non_nil(...) - end -end - - -local function configure_ibss(config, radio, index, suffix, disabled) - local name = 'ibss_' .. radio - - uci:delete('network', name) - uci:delete('network', name .. '_vlan') - uci:delete('wireless', name) - - macaddr = util.generate_mac(3*(index-1)+2) - - if config and macaddr then - if config.vlan then - uci:section('network', 'interface', name, - { - proto = 'none', - } - ) - - uci:section('network', 'interface', name .. '_vlan', - { - ifname = '@' .. name .. '.' .. config.vlan, - proto = 'batadv', - mesh = 'bat0', - } - ) - else - uci:section('network', 'interface', name, - { - proto = 'batadv', - mesh = 'bat0', - } - ) - end - - uci:section('wireless', 'wifi-iface', name, - { - device = radio, - network = name, - mode = 'adhoc', - ssid = config.ssid, - bssid = config.bssid, - macaddr = macaddr, - mcast_rate = config.mcast_rate, - ifname = suffix and 'ibss' .. suffix, - disabled = disabled and 1 or 0, - } - ) - end -end - -local function configure_mesh(config, radio, index, suffix, disabled) - local name = 'mesh_' .. radio - local macfilter = uci:get('wireless', name, 'macfilter') - local maclist = uci:get('wireless', name, 'maclist') - - uci:delete('network', name) - uci:delete('wireless', name) - - macaddr = util.generate_mac(3*(index-1)+1) - - if config and macaddr then - uci:section('network', 'interface', name, - { - proto = 'batadv', - mesh = 'bat0', - } - ) - - uci:section('wireless', 'wifi-iface', name, - { - device = radio, - network = name, - mode = 'mesh', - mesh_id = config.id, - mesh_fwding = 0, - macaddr = macaddr, - mcast_rate = config.mcast_rate, - ifname = suffix and 'mesh' .. suffix, - disabled = disabled and 1 or 0, - macfilter = macfilter, - maclist = maclist, - } - ) - end -end - -local function configure_radio(radio, index, config) - local suffix = radio:match('^radio(%d+)$') - - local ibss_disabled = is_disabled('ibss_' .. radio) - local mesh_disabled = is_disabled('mesh_' .. radio) - - configure_ibss(config.ibss, radio, index, suffix, - first_non_nil( - ibss_disabled, - mesh_disabled, - (config.ibss or {}).disabled, -- will be nil if config.ibss or config.ibss.disabled is unset - false - ) - ) - configure_mesh(config.mesh, radio, index, suffix, - first_non_nil( - mesh_disabled, - ibss_disabled, - (config.mesh or {}).disabled, -- will be nil if config.mesh or config.mesh.disabled is unset - false - ) - ) -end - -util.iterate_radios(configure_radio) - -uci:save('wireless') -uci:save('network') diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/330-gluon-mesh-batman-adv-core-mesh-on-wan b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/330-gluon-mesh-batman-adv-core-mesh-on-wan deleted file mode 100755 index 7a964ee2..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/330-gluon-mesh-batman-adv-core-mesh-on-wan +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -local c = uci.cursor() - -if not c:get('network', 'mesh_wan') then - c:section('network', 'interface', 'mesh_wan', - { ifname = 'br-wan' - , proto = 'batadv' - , mesh = 'bat0' - , mesh_no_rebroadcast = '1' - , auto = site.mesh_on_wan and 1 or 0 - }) -end - -c:save('network') diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan deleted file mode 100755 index 99ca4213..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/340-gluon-mesh-batman-adv-core-mesh-on-lan +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local util = require 'gluon.util' -local sysconfig = require 'gluon.sysconfig' - -local uci = require('luci.model.uci').cursor() -local lutil = require 'luci.util' - -if not sysconfig.lan_ifname then - os.exit(0) -end - -uci:section('network', 'interface', 'mesh_lan', { - ifname = sysconfig.lan_ifname, - type = 'bridge', - igmp_snooping = 0, - proto = 'batadv', - mesh = 'bat0', - mesh_no_rebroadcast = '1', - macaddr = util.generate_mac(6), -}) - -if uci:get('network', 'mesh_lan', 'auto') == nil then - local enable = site.mesh_on_lan - - if enable then - local interfaces = uci:get_list('network', 'client', 'ifname') - - if interfaces then - for _, lanif in ipairs(lutil.split(sysconfig.lan_ifname, ' ')) do - if lutil.contains(interfaces, lanif) then - enable = false - break - end - end - end - end - - uci:set('network', 'mesh_lan', 'auto', enable and 1 or 0) -end - -uci:save('network') diff --git a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-core-rssid b/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-core-rssid deleted file mode 100755 index b6b16574..00000000 --- a/package/gluon-mesh-batman-adv-core/files/lib/gluon/upgrade/350-gluon-mesh-batman-adv-core-rssid +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/lua - -local uci = require('luci.model.uci').cursor() - -if uci:get('system', 'rssid_wlan0') then - if uci:get('wireless', 'mesh_radio0') then - uci:set('system', 'rssid_wlan0', 'dev', 'mesh0') - else - uci:set('system', 'rssid_wlan0', 'dev', 'ibss0') - end - - uci:save('system') -end diff --git a/package/gluon-mesh-batman-adv-core/src/Makefile b/package/gluon-mesh-batman-adv-core/src/Makefile deleted file mode 100644 index 84d9d48e..00000000 --- a/package/gluon-mesh-batman-adv-core/src/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -all: respondd.so - -CFLAGS += -Wall - -respondd.so: respondd.c - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -liwinfo -luci diff --git a/package/gluon-mesh-batman-adv/Makefile b/package/gluon-mesh-batman-adv/Makefile new file mode 100644 index 00000000..4b158f5a --- /dev/null +++ b/package/gluon-mesh-batman-adv/Makefile @@ -0,0 +1,41 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-mesh-batman-adv +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-mesh-batman-adv/common + PROVIDES:=gluon-mesh-batman-adv + DEPENDS:=+gluon-core +libgluonutil +gluon-client-bridge +gluon-ebtables +firewall +libiwinfo +kmod-dummy +libnl-tiny +libbatadv +@GLUON_SPECIALIZE_KERNEL:KERNEL_DUMMY +@GLUON_SPECIALIZE_KERNEL:KERNEL_CRC16 +@GLUON_SPECIALIZE_KERNEL:KERNEL_LIBCRC32C +endef + +define Package/gluon-mesh-batman-adv-14 +$(Package/gluon-mesh-batman-adv/common) + TITLE:=Support for batman-adv meshing (compat level 14) + CONFLICTS:=gluon-mesh-batman-adv-15 + DEPENDS+=+kmod-batman-adv-legacy +endef + +define Package/gluon-mesh-batman-adv-15 +$(Package/gluon-mesh-batman-adv/common) + TITLE:=Support for batman-adv meshing (compat level 15) + DEPENDS+=+kmod-batman-adv +batctl +endef + +define Package/gluon-mesh-batman-adv-14/install + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/lib/gluon/mesh-batman-adv + echo 14 > $(1)/lib/gluon/mesh-batman-adv/compat +endef + +define Package/gluon-mesh-batman-adv-15/install + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/lib/gluon/mesh-batman-adv + echo 15 > $(1)/lib/gluon/mesh-batman-adv/compat +endef + +$(eval $(call BuildPackageGluon,gluon-mesh-batman-adv-14)) +$(eval $(call BuildPackageGluon,gluon-mesh-batman-adv-15)) diff --git a/package/gluon-mesh-batman-adv/check_site.lua b/package/gluon-mesh-batman-adv/check_site.lua new file mode 100644 index 00000000..f5ea9fb4 --- /dev/null +++ b/package/gluon-mesh-batman-adv/check_site.lua @@ -0,0 +1,5 @@ +-- mesh/vxlan is required in single domain setups (this_domain() is nil) +need_boolean(in_domain({'mesh', 'vxlan'}), not this_domain()) + +need_number({'mesh', 'batman_adv', 'gw_sel_class'}, false) +need_one_of({'mesh', 'batman_adv', 'routing_algo'}, {'BATMAN_IV', 'BATMAN_V'}, false) diff --git a/package/gluon-mesh-batman-adv/files/etc/sysctl.d/31-gluon-mesh-batman-adv.conf b/package/gluon-mesh-batman-adv/files/etc/sysctl.d/31-gluon-mesh-batman-adv.conf new file mode 100644 index 00000000..c93fa0da --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/etc/sysctl.d/31-gluon-mesh-batman-adv.conf @@ -0,0 +1,2 @@ +net.ipv6.conf.br-client.forwarding=0 +net.ipv6.conf.local-node.forwarding=0 diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/post-setup.d/30-gluon-mesh-batman-adv b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/post-setup.d/30-gluon-mesh-batman-adv new file mode 100755 index 00000000..a372c960 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/post-setup.d/30-gluon-mesh-batman-adv @@ -0,0 +1,3 @@ +#!/bin/sh + +ubus call network.interface.gluon_bat0 renew diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/setup.d/30-gluon-mesh-batman-adv b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/setup.d/30-gluon-mesh-batman-adv new file mode 100755 index 00000000..373b872c --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/setup.d/30-gluon-mesh-batman-adv @@ -0,0 +1,13 @@ +#!/bin/sh + +if [ "$FIXED_MTU" -eq 0 ]; then + # In case on VLAN on IBSS, first set MTU of the underlying interface + for lower in /sys/class/net/"$IFNAME"/lower_*/wireless; do + lower="${lower%%\/wireless}" + lower="${lower##*\/lower_}" + ip link set dev "$lower" mtu 1536 + break + done + + ip link set dev "$IFNAME" mtu 1532 +fi diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/teardown.d/70-gluon-mesh-batman-adv b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/teardown.d/70-gluon-mesh-batman-adv new file mode 100755 index 00000000..355b89b0 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/core/mesh/teardown.d/70-gluon-mesh-batman-adv @@ -0,0 +1,5 @@ +#!/bin/sh + +lock /var/lock/gluon_bat0.lock +(echo 'none' > "/sys/class/net/$IFNAME/batman_adv/mesh_iface") 2>/dev/null +lock -u /var/lock/gluon_bat0.lock diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/ebtables/250-next-node b/package/gluon-mesh-batman-adv/files/lib/gluon/ebtables/250-next-node new file mode 100644 index 00000000..8b8d77a2 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/ebtables/250-next-node @@ -0,0 +1,38 @@ +local client_bridge = require 'gluon.client_bridge' +local site = require 'gluon.site' +local next_node = site.next_node({}) + +local macaddr = client_bridge.next_node_macaddr() + +rule('FORWARD --logical-out br-client -i bat0 -o local-port -j DROP') +rule('FORWARD --logical-out br-client -i local-port -o bat0 -j DROP') + +rule('FORWARD --logical-out br-client -o bat0 -d ' .. macaddr .. ' -j DROP') +rule('OUTPUT --logical-out br-client -o bat0 -d ' .. macaddr .. ' -j DROP') +rule('FORWARD --logical-out br-client -o bat0 -s ' .. macaddr .. ' -j DROP') +rule('OUTPUT --logical-out br-client -o bat0 -s ' .. macaddr .. ' -j DROP') + +if next_node.ip4 then + rule('FORWARD --logical-out br-client -o bat0 -p ARP --arp-ip-src ' .. next_node.ip4 .. ' -j DROP') + rule('FORWARD --logical-out br-client -o bat0 -p ARP --arp-ip-dst ' .. next_node.ip4 .. ' -j DROP') + rule('FORWARD --logical-out br-client -i bat0 -p ARP --arp-ip-src ' .. next_node.ip4 .. ' -j DROP') + rule('FORWARD --logical-out br-client -i bat0 -p ARP --arp-ip-dst ' .. next_node.ip4 .. ' -j DROP') + + rule('OUTPUT --logical-out br-client -o bat0 -p ARP --arp-ip-src ' .. next_node.ip4 .. ' -j DROP') + rule('OUTPUT --logical-out br-client -o bat0 -p ARP --arp-ip-dst ' .. next_node.ip4 .. ' -j DROP') + + rule('INPUT -i bat0 -p ARP --arp-ip-src ' .. next_node.ip4 .. ' -j DROP') + rule('INPUT -i bat0 -p ARP --arp-ip-dst ' .. next_node.ip4 .. ' -j DROP') + + rule('FORWARD --logical-out br-client -o bat0 -p IPv4 --ip-destination ' .. next_node.ip4 .. ' -j DROP') + rule('OUTPUT --logical-out br-client -o bat0 -p IPv4 --ip-destination ' .. next_node.ip4 .. ' -j DROP') + rule('FORWARD --logical-out br-client -o bat0 -p IPv4 --ip-source ' .. next_node.ip4 .. ' -j DROP') + rule('OUTPUT --logical-out br-client -o bat0 -p IPv4 --ip-source ' .. next_node.ip4 .. ' -j DROP') +end + +if next_node.ip6 then + rule('FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-destination ' .. next_node.ip6 .. ' -j DROP') + rule('OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-destination ' .. next_node.ip6 .. ' -j DROP') + rule('FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-source ' .. next_node.ip6 .. ' -j DROP') + rule('OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-source ' .. next_node.ip6 .. ' -j DROP') +end diff --git a/package/gluon-radvd/files/lib/gluon/ebtables/300-radv-input-output b/package/gluon-mesh-batman-adv/files/lib/gluon/ebtables/300-radv-input-output similarity index 100% rename from package/gluon-radvd/files/lib/gluon/ebtables/300-radv-input-output rename to package/gluon-mesh-batman-adv/files/lib/gluon/ebtables/300-radv-input-output diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/respondd/client.dev b/package/gluon-mesh-batman-adv/files/lib/gluon/respondd/client.dev new file mode 100644 index 00000000..b051c6c5 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/respondd/client.dev @@ -0,0 +1 @@ +client diff --git a/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh b/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh new file mode 100755 index 00000000..ea562c49 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/netifd/proto/gluon_bat0.sh @@ -0,0 +1,63 @@ +#!/bin/sh + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +proto_gluon_bat0_init_config() { + no_device=1 + available=1 + renew_handler=1 +} + +proto_gluon_bat0_renew() { + local config="$1" + + lock /var/lock/gluon_bat0.lock + + local ifdump="$(ubus call network.interface dump)" + + echo "$ifdump" | jsonfilter \ + -e "@.interface[@.proto='gluon_mesh' && @.up=true]['device','data']" \ + | while read dev; do + read data + + echo bat0 > "/sys/class/net/$dev/batman_adv/mesh_iface" + + ! [ "$(echo "$data" | jsonfilter -e "@.transitive")" = 'true' ] + transitive=$? + + (echo "$transitive" > "/sys/class/net/$dev/batman_adv/no_rebroadcast") 2>/dev/null + done + + lock -u /var/lock/gluon_bat0.lock +} + +proto_gluon_bat0_setup() { + local config="$1" + + local primary0_mac="$(lua -lgluon.util -e 'print(gluon.util.generate_mac(3))')" + + ip link add primary0 type dummy + echo 1 > /proc/sys/net/ipv6/conf/primary0/disable_ipv6 + ip link set primary0 address "$primary0_mac" mtu 1532 up + + local routing_algo="$(uci -q get batman-adv.bat0.routing_algo || echo 'BATMAN_IV')" + (echo "$routing_algo" >/sys/module/batman_adv/parameters/routing_algo) 2>/dev/null + + echo bat0 > /sys/class/net/primary0/batman_adv/mesh_iface + + proto_init_update primary0 1 + proto_send_update "$config" + + proto_gluon_bat0_renew "$1" +} + +proto_gluon_bat0_teardown() { + local config="$1" + + ip link del bat0 + ip link del primary0 +} + +add_protocol gluon_bat0 diff --git a/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/abort.d/10start-network b/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/abort.d/10start-network new file mode 100755 index 00000000..f04d55cc --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/abort.d/10start-network @@ -0,0 +1,5 @@ +#!/bin/sh + +. /lib/gluon/autoupdater/lib.sh + +pidof netifd >/dev/null || start_enabled network diff --git a/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/upgrade.d/10stop-network b/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/upgrade.d/10stop-network new file mode 100755 index 00000000..b02580a3 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/usr/lib/autoupdater/upgrade.d/10stop-network @@ -0,0 +1,8 @@ +#!/bin/sh + +. /lib/gluon/autoupdater/lib.sh + +wifi down +sleep 1 +stop network +ip link del bat0 diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/radvd/arguments b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/radvd/arguments new file mode 100755 index 00000000..c7f43e11 --- /dev/null +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/radvd/arguments @@ -0,0 +1,9 @@ +#!/usr/bin/lua + +local site = require "gluon.site" + +io.write("-i local-node -p " .. site.prefix6()) + +if site.dns.servers() and site.next_node.ip6() then + io.write(" --rdnss " .. site.next_node.ip6()) +end diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh new file mode 100755 index 00000000..be5f18b5 --- /dev/null +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/310-gluon-mesh-batman-adv-mesh @@ -0,0 +1,45 @@ +#!/usr/bin/lua + +local sysconfig = require 'gluon.sysconfig' +local site = require 'gluon.site' +local util = require 'gluon.util' + +local uci = require('simple-uci').cursor() + + +local gw_mode = uci:get('batman-adv', 'bat0', 'gw_mode') or 'client' +local gw_sel_class = site.mesh.batman_adv.gw_sel_class() +local routing_algo = site.mesh.batman_adv.routing_algo() + + +uci:delete('batman-adv', 'bat0') +uci:section('batman-adv', 'mesh', 'bat0', { + orig_interval = 5000, + gw_mode = gw_mode, + gw_sel_class = gw_sel_class, + hop_penalty = 15, + routing_algo = routing_algo, + multicast_mode = false, +}) +uci:save('batman-adv') + +uci:delete('network', 'gluon_bat0') +uci:section('network', 'interface', 'gluon_bat0', { + proto = 'gluon_bat0', +}) + +uci:delete('network', 'bat0') +uci:section('network', 'interface', 'bat0', { + ifname = 'bat0', + proto = 'none', + auto = true, + macaddr = sysconfig.primary_mac, + multicast_router = 2, + learning = true, +}) + +local interfaces = uci:get_list('network', 'client', 'ifname') +util.add_to_set(interfaces, 'bat0') +uci:set_list('network', 'client', 'ifname', interfaces) + +uci:save('network') diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge new file mode 100755 index 00000000..85c21ac4 --- /dev/null +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/320-gluon-mesh-batman-adv-client-bridge @@ -0,0 +1,48 @@ +#!/usr/bin/lua + +-- This script must be ordered after 300-gluon-client-bridge-network, as +-- it overrides parts of network.client + + +local site = require 'gluon.site' +local sysconfig = require 'gluon.sysconfig' +local util = require 'gluon.util' +local uci = require('simple-uci').cursor() + + +uci:section('network', 'interface', 'client', { + ipv6 = true, + proto = 'dhcpv6', + reqprefix = 'no', + peerdns = not site.dns.servers(), + sourcefilter = false, + keep_ra_dnslifetime = true, + robustness = 9, + query_interval = 2000, + query_response_interval = 500, +}) + +uci:delete('network', 'client_lan') + +uci:delete('network', 'local_node_route') + +uci:delete('network', 'local_node_route6') +uci:section('network', 'route6', 'local_node_route6', { + interface = 'client', + target = site.prefix6(), + gateway = '::', +}) + +uci:save('network') + +local networks = uci:get_list('firewall', 'mesh', 'network') +util.add_to_set(networks, 'client') +uci:set_list('firewall', 'mesh', 'network', networks) + +local networks = uci:get_list('firewall', 'drop', 'network') +util.remove_from_set(networks, 'client') +uci:set_list('firewall', 'drop', 'network', networks) + +uci:delete('firewall', 'local_node_dns') + +uci:save('firewall') diff --git a/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses new file mode 100755 index 00000000..a8e69d78 --- /dev/null +++ b/package/gluon-mesh-batman-adv/luasrc/lib/gluon/upgrade/330-gluon-mesh-batman-adv-mac-addresses @@ -0,0 +1,10 @@ +#!/usr/bin/lua + +local util = require 'gluon.util' +local uci = require('simple-uci').cursor() + + +-- fix up potentially duplicate MAC addresses (for meshing) +uci:set('network', 'wan', 'macaddr', util.generate_mac(0)) +uci:set('network', 'mesh_lan', 'macaddr', util.generate_mac(4)) +uci:save('network') diff --git a/package/gluon-mesh-batman-adv/src/Makefile b/package/gluon-mesh-batman-adv/src/Makefile new file mode 100644 index 00000000..0974669b --- /dev/null +++ b/package/gluon-mesh-batman-adv/src/Makefile @@ -0,0 +1,35 @@ +all: respondd.so + +CFLAGS += -Wall + +ifeq ($(origin PKG_CONFIG), undefined) + PKG_CONFIG = pkg-config + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif +endif + +ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined) + LIBNL_NAME ?= libnl-tiny + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),) + $(error No $(LIBNL_NAME) development libraries found!) + endif + LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME)) + LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME)) +endif +CFLAGS += $(LIBNL_CFLAGS) +LDLIBS += $(LIBNL_LDLIBS) + +ifeq ($(origin LIBBATADV_CFLAGS) $(origin LIBBATADV_LDLIBS), undefined undefined) + LIBBATADV_NAME ?= libbatadv + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBBATADV_NAME) 2>/dev/null),) + $(error No $(LIBBATADV_NAME) development libraries found!) + endif + LIBBATADV_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBBATADV_NAME)) + LIBBATADV_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBBATADV_NAME)) +endif +CFLAGS += $(LIBBATADV_CFLAGS) +LDLIBS += $(LIBBATADV_LDLIBS) + +respondd.so: respondd.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -liwinfo -luci diff --git a/package/gluon-mesh-batman-adv-core/src/respondd.c b/package/gluon-mesh-batman-adv/src/respondd.c similarity index 70% rename from package/gluon-mesh-batman-adv-core/src/respondd.c rename to package/gluon-mesh-batman-adv/src/respondd.c index 7c2ac6c7..ca7ae968 100644 --- a/package/gluon-mesh-batman-adv-core/src/respondd.c +++ b/package/gluon-mesh-batman-adv/src/respondd.c @@ -51,11 +51,28 @@ #include #include +#include #define _STRINGIFY(s) #s #define STRINGIFY(s) _STRINGIFY(s) +struct neigh_netlink_opts { + struct json_object *interfaces; + struct batadv_nlquery_opts query_opts; +}; + +struct gw_netlink_opts { + struct json_object *obj; + struct batadv_nlquery_opts query_opts; +}; + +struct clients_netlink_opts { + size_t total; + size_t wifi; + struct batadv_nlquery_opts query_opts; +}; + static struct json_object * get_addresses(void) { FILE *f = fopen("/proc/net/if_inet6", "r"); @@ -121,9 +138,31 @@ static void mesh_add_subif(const char *ifname, struct json_object *wireless, struct json_object *tunnel, struct json_object *other) { struct json_object *address = gluonutil_wrap_and_free_string(gluonutil_get_interface_address(ifname)); - if (interface_file_exists(ifname, "wireless")) + char lowername[IFNAMSIZ]; + strncpy(lowername, ifname, sizeof(lowername)-1); + lowername[sizeof(lowername)-1] = 0; + + const char *format = "/sys/class/net/%s/lower_*"; + char pattern[strlen(format) + IFNAMSIZ]; + + /* In case of VLAN and bridge interfaces, we want the lower interface + * to determine the interface type (but not for the interface address) */ + while (true) { + snprintf(pattern, sizeof(pattern), format, lowername); + size_t pattern_len = strlen(pattern); + + glob_t lower; + if (glob(pattern, GLOB_NOSORT, NULL, &lower)) + break; + + strncpy(lowername, lower.gl_pathv[0] + pattern_len - 1, sizeof(lowername)-1); + + globfree(&lower); + } + + if (interface_file_exists(lowername, "wireless")) json_object_array_add(wireless, address); - else if (interface_file_exists(ifname, "tun_flags")) + else if (interface_file_exists(lowername, "tun_flags")) json_object_array_add(tunnel, address); else json_object_array_add(other, address); @@ -168,7 +207,7 @@ static struct json_object * get_mesh(void) { } static struct json_object * get_batman_adv_compat(void) { - FILE *f = fopen("/lib/gluon/mesh-batman-adv-core/compat", "r"); + FILE *f = fopen("/lib/gluon/mesh-batman-adv/compat", "r"); if (!f) return NULL; @@ -201,27 +240,71 @@ static struct json_object * respondd_provider_nodeinfo(void) { return ret; } +static const enum batadv_nl_attrs gateways_mandatory[] = { + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_ROUTER, +}; + +static int parse_gw_list_netlink_cb(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct batadv_nlquery_opts *query_opts = arg; + struct genlmsghdr *ghdr; + uint8_t *orig; + uint8_t *router; + struct gw_netlink_opts *opts; + char addr[18]; + + opts = batadv_container_of(query_opts, struct gw_netlink_opts, + query_opts); + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_GATEWAYS) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) + return NL_OK; + + if (batadv_genl_missing_attrs(attrs, gateways_mandatory, + BATADV_ARRAY_SIZE(gateways_mandatory))) + return NL_OK; + + if (!attrs[BATADV_ATTR_FLAG_BEST]) + return NL_OK; + + orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]); + router = nla_data(attrs[BATADV_ATTR_ROUTER]); + + sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", + orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]); + + json_object_object_add(opts->obj, "gateway", json_object_new_string(addr)); + + sprintf(addr, "%02x:%02x:%02x:%02x:%02x:%02x", + router[0], router[1], router[2], router[3], router[4], router[5]); + + json_object_object_add(opts->obj, "gateway_nexthop", json_object_new_string(addr)); + + return NL_STOP; +} static void add_gateway(struct json_object *obj) { - FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/gateways", "r"); - if (!f) - return; + struct gw_netlink_opts opts = { + .obj = obj, + .query_opts = { + .err = 0, + }, + }; - char *line = NULL; - size_t len = 0; - - while (getline(&line, &len, f) >= 0) { - char addr[18]; - - if (sscanf(line, "=> %17[0-9a-fA-F:]", addr) != 1) - continue; - - json_object_object_add(obj, "gateway", json_object_new_string(addr)); - break; - } - - free(line); - fclose(f); + batadv_genl_query("bat0", BATADV_CMD_GET_GATEWAYS, + parse_gw_list_netlink_cb, NLM_F_DUMP, + &opts.query_opts); } static inline bool ethtool_ioctl(int fd, struct ifreq *ifr, void *data) { @@ -364,6 +447,8 @@ static void count_iface_stations(size_t *wifi24, size_t *wifi5, const char *ifna static void count_stations(size_t *wifi24, size_t *wifi5) { struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + return; ctx->flags &= ~UCI_FLAG_STRICT; @@ -397,39 +482,70 @@ static void count_stations(size_t *wifi24, size_t *wifi5) { uci_free_context(ctx); } +static const enum batadv_nl_attrs clients_mandatory[] = { + BATADV_ATTR_TT_FLAGS, +}; + +static int parse_clients_list_netlink_cb(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct batadv_nlquery_opts *query_opts = arg; + struct genlmsghdr *ghdr; + struct clients_netlink_opts *opts; + uint32_t flags; + + opts = batadv_container_of(query_opts, struct clients_netlink_opts, + query_opts); + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) + return NL_OK; + + if (batadv_genl_missing_attrs(attrs, clients_mandatory, + BATADV_ARRAY_SIZE(clients_mandatory))) + return NL_OK; + + flags = nla_get_u32(attrs[BATADV_ATTR_TT_FLAGS]); + + if (flags & BATADV_TT_CLIENT_NOPURGE) + return NL_OK; + + if (flags & BATADV_TT_CLIENT_WIFI) + opts->wifi++; + + opts->total++; + + return NL_OK; +} + static struct json_object * get_clients(void) { - size_t total = 0, wifi = 0, wifi24 = 0, wifi5 = 0; + size_t wifi24 = 0, wifi5 = 0; + struct clients_netlink_opts opts = { + .total = 0, + .wifi = 0, + .query_opts = { + .err = 0, + }, + }; - FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/transtable_local", "r"); - if (!f) - return NULL; - - char *line = NULL; - size_t len = 0; - - while (getline(&line, &len, f) >= 0) { - char flags[16]; - - if (sscanf(line, " * %*[^[] [%15[^]]]", flags) != 1) - continue; - - if (strchr(flags, 'P')) - continue; - - total++; - - if (strchr(flags, 'W')) - wifi++; - } - - free(line); - fclose(f); + batadv_genl_query("bat0", BATADV_CMD_GET_TRANSTABLE_LOCAL, + parse_clients_list_netlink_cb, NLM_F_DUMP, + &opts.query_opts); count_stations(&wifi24, &wifi5); struct json_object *ret = json_object_new_object(); - json_object_object_add(ret, "total", json_object_new_int(total)); - json_object_object_add(ret, "wifi", json_object_new_int(wifi)); + json_object_object_add(ret, "total", json_object_new_int(opts.total)); + json_object_object_add(ret, "wifi", json_object_new_int(opts.wifi)); json_object_object_add(ret, "wifi24", json_object_new_int(wifi24)); json_object_object_add(ret, "wifi5", json_object_new_int(wifi5)); return ret; @@ -468,49 +584,105 @@ static struct json_object * ifnames2addrs(struct json_object *interfaces) { return ret; } -static struct json_object * get_batadv(void) { - FILE *f = fopen("/sys/kernel/debug/batman_adv/bat0/originators", "r"); - if (!f) - return NULL; +static const enum batadv_nl_attrs parse_orig_list_mandatory[] = { + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_TQ, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, +}; - char *line = NULL; - size_t len = 0; +static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct batadv_nlquery_opts *query_opts = arg; + struct genlmsghdr *ghdr; + uint8_t *orig; + uint8_t *dest; + uint8_t tq; + uint32_t hardif; + uint32_t lastseen; + char ifname_buf[IF_NAMESIZE], *ifname; + struct neigh_netlink_opts *opts; + char mac1[18]; - struct json_object *interfaces = json_object_new_object(); + opts = batadv_container_of(query_opts, struct neigh_netlink_opts, + query_opts); - while (getline(&line, &len, f) >= 0) { - char mac1[18], mac2[18]; - /* IF_NAMESIZE would be enough, but adding 1 here is simpler than subtracting 1 in the format string */ - char ifname[IF_NAMESIZE+1]; - double lastseen; - int tq; + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; - if (sscanf(line, - "%17[0-9a-fA-F:] %lfs ( %i ) %17[0-9a-fA-F:] [ %"STRINGIFY(IF_NAMESIZE)"[^]] ]", - mac1, &lastseen, &tq, mac2, ifname) != 5) - continue; + ghdr = nlmsg_data(nlh); - if (strcmp(mac1, mac2)) - continue; + if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS) + return NL_OK; - struct json_object *interface; - if (!json_object_object_get_ex(interfaces, ifname, &interface)) { - interface = json_object_new_object(); - json_object_object_add(interfaces, ifname, interface); - } + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) + return NL_OK; - struct json_object *obj = json_object_new_object(); - json_object_object_add(obj, "tq", json_object_new_int(tq)); - struct json_object *jso = json_object_new_double(lastseen); - json_object_set_serializer(jso, json_object_double_to_json_string, "%.3f", NULL); - json_object_object_add(obj, "lastseen", jso); - json_object_object_add(interface, mac1, obj); + if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory, + BATADV_ARRAY_SIZE(parse_orig_list_mandatory))) + return NL_OK; + + if (!attrs[BATADV_ATTR_FLAG_BEST]) + return NL_OK; + + orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]); + dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]); + tq = nla_get_u8(attrs[BATADV_ATTR_TQ]); + hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]); + lastseen = nla_get_u32(attrs[BATADV_ATTR_LAST_SEEN_MSECS]); + + if (memcmp(orig, dest, 6) != 0) + return NL_OK; + + ifname = if_indextoname(hardif, ifname_buf); + if (!ifname) + return NL_OK; + + sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x", + orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]); + + struct json_object *obj = json_object_new_object(); + if (!obj) + return NL_OK; + + struct json_object *interface; + if (!json_object_object_get_ex(opts->interfaces, ifname, &interface)) { + interface = json_object_new_object(); + json_object_object_add(opts->interfaces, ifname, interface); } - fclose(f); - free(line); + json_object_object_add(obj, "tq", json_object_new_int(tq)); + json_object_object_add(obj, "lastseen", json_object_new_double(lastseen / 1000.)); + json_object_object_add(interface, mac1, obj); - return ifnames2addrs(interfaces); + return NL_OK; +} + +static struct json_object * get_batadv(void) { + struct neigh_netlink_opts opts = { + .query_opts = { + .err = 0, + }, + }; + int ret; + + opts.interfaces = json_object_new_object(); + if (!opts.interfaces) + return NULL; + + ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS, + parse_orig_list_netlink_cb, NLM_F_DUMP, + &opts.query_opts); + if (ret < 0) { + json_object_put(opts.interfaces); + return NULL; + } + + return ifnames2addrs(opts.interfaces); } static struct json_object * get_wifi_neighbours(const char *ifname) { diff --git a/package/gluon-mesh-vpn-core/Makefile b/package/gluon-mesh-vpn-core/Makefile new file mode 100644 index 00000000..f161333f --- /dev/null +++ b/package/gluon-mesh-vpn-core/Makefile @@ -0,0 +1,21 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-mesh-vpn-core +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-mesh-vpn-core + TITLE:=Basic support for connecting meshes via VPN tunnels + DEPENDS:=+gluon-core +gluon-wan-dnsmasq +iptables +iptables-mod-extra +simple-tc \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NETFILTER_XT_MATCH_ADDRTYPE \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NETFILTER_XT_MATCH_OWNER \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NETFILTER_XT_MATCH_PKTTYPE \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NETFILTER_XT_MATCH_QUOTA \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NET_CLS_BASIC \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NET_SCH_TBF \ + +@GLUON_SPECIALIZE_KERNEL:KERNEL_NET_SCH_INGRESS + USERID:=:gluon-mesh-vpn=800 +endef + +$(eval $(call BuildPackageGluon,gluon-mesh-vpn-core)) diff --git a/package/gluon-mesh-vpn-core/check_site.lua b/package/gluon-mesh-vpn-core/check_site.lua new file mode 100644 index 00000000..04ff3c84 --- /dev/null +++ b/package/gluon-mesh-vpn-core/check_site.lua @@ -0,0 +1,7 @@ +need_boolean(in_site({'mesh_vpn', 'enabled'}), false) +need_number({'mesh_vpn', 'mtu'}) +need_boolean(in_site({'mesh_vpn', 'pubkey_privacy'}), false) + +need_boolean(in_site({'mesh_vpn', 'bandwidth_limit', 'enabled'}), false) +need_number(in_site({'mesh_vpn', 'bandwidth_limit', 'ingress'}), false) +need_number(in_site({'mesh_vpn', 'bandwidth_limit', 'egress'}), false) diff --git a/package/gluon-mesh-vpn-core/files/lib/gluon/mesh-vpn/iptables.rules b/package/gluon-mesh-vpn-core/files/lib/gluon/mesh-vpn/iptables.rules new file mode 100644 index 00000000..771fb40c --- /dev/null +++ b/package/gluon-mesh-vpn-core/files/lib/gluon/mesh-vpn/iptables.rules @@ -0,0 +1,3 @@ +*nat +-I OUTPUT -m owner --gid-owner gluon-mesh-vpn -o lo -d 127.0.0.1 -p udp --dport 53 -j DNAT --to-destination :54 +COMMIT diff --git a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn new file mode 100755 index 00000000..d02bb7f6 --- /dev/null +++ b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/upgrade/500-mesh-vpn @@ -0,0 +1,85 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local users = require 'gluon.users' +local util = require 'gluon.util' +local fs = require 'nixio.fs' + +local uci = require('simple-uci').cursor() + + +uci:section('network', 'interface', 'mesh_vpn', { + ifname = 'mesh-vpn', + proto = 'gluon_mesh', + transitive = true, + fixed_mtu = true, + macaddr = util.generate_mac(7), + mtu = site.mesh_vpn.mtu(), +}) + +uci:save('network') + + +if fs.access('/etc/config/gluon-simple-tc') then + os.rename('/etc/config/gluon-simple-tc', '/etc/config/simple-tc') +end + +if not uci:get('simple-tc', 'mesh_vpn') then + uci:section('simple-tc', 'interface', 'mesh_vpn', { + ifname = 'mesh-vpn', + enabled = site.mesh_vpn.bandwidth_limit.enabled(false), + limit_ingress = site.mesh_vpn.bandwidth_limit.ingress(), + limit_egress = site.mesh_vpn.bandwidth_limit.egress(), + }) + uci:save('simple-tc') +end + + +-- The previously used user and group are removed, we now have a generic group +users.remove_user('gluon-fastd') +users.remove_group('gluon-fastd') + +uci:section('firewall', 'include', 'mesh_vpn_dns', { + type = 'restore', + path = '/lib/gluon/mesh-vpn/iptables.rules', + family = 'ipv4', +}) + +uci:save('firewall') + + +-- VPN migration +local has_fastd = fs.access('/lib/gluon/mesh-vpn/fastd') +local fastd_enabled = uci:get('fastd', 'mesh_vpn', 'enabled') + +local has_tunneldigger = fs.access('/lib/gluon/mesh-vpn/tunneldigger') +local tunneldigger_enabled = uci:get('tunneldigger', 'mesh_vpn', 'enabled') + +local enabled + +-- If the installed VPN package has its enabled state set, keep the value +if has_fastd and fastd_enabled then + enabled = fastd_enabled == '1' +elseif has_tunneldigger and tunneldigger_enabled then + enabled = tunneldigger_enabled == '1' +-- Otherwise, migrate the other package's value if any is set +elseif fastd_enabled or tunneldigger_enabled then + enabled = fastd_enabled == '1' or tunneldigger_enabled == '1' +-- If nothing is set, use the default +else + enabled = site.mesh_vpn.enabled(false) +end + +if has_fastd then + uci:set('fastd', 'mesh_vpn', 'enabled', enabled) +else + uci:delete('fastd', 'mesh_vpn') +end +uci:save('fastd') + +if has_tunneldigger then + uci:set('tunneldigger', 'mesh_vpn', 'enabled', enabled) +else + uci:delete('tunneldigger', 'mesh_vpn') +end +uci:save('tunneldigger') diff --git a/package/gluon-mesh-vpn-fastd/Makefile b/package/gluon-mesh-vpn-fastd/Makefile index bb33257e..087aff5f 100644 --- a/package/gluon-mesh-vpn-fastd/Makefile +++ b/package/gluon-mesh-vpn-fastd/Makefile @@ -3,33 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mesh-vpn-fastd PKG_VERSION:=3 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS := respondd - -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-mesh-vpn-fastd - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Support for connecting batman-adv meshes via fastd - DEPENDS:=+gluon-core +libgluonutil gluon-mesh-batman-adv +gluon-wan-dnsmasq +fastd +iptables +iptables-mod-extra +simple-tc + TITLE:=Support for connecting meshes via fastd + DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +fastd +@GLUON_SPECIALIZE_KERNEL:KERNEL_TUN endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/gluon-mesh-vpn-fastd/install - $(CP) ./files/* $(1)/ - - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/mesh-vpn-fastd.so -endef - -define Package/gluon-mesh-vpn-fastd/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-mesh-vpn-fastd)) +$(eval $(call BuildPackageGluon,gluon-mesh-vpn-fastd)) diff --git a/package/gluon-mesh-vpn-fastd/check_site.lua b/package/gluon-mesh-vpn-fastd/check_site.lua index 30cca11d..18becfee 100644 --- a/package/gluon-mesh-vpn-fastd/check_site.lua +++ b/package/gluon-mesh-vpn-fastd/check_site.lua @@ -1,37 +1,22 @@ -need_string_array('fastd_mesh_vpn.methods') -need_number('fastd_mesh_vpn.mtu') -need_boolean('fastd_mesh_vpn.enabled', false) -need_boolean('fastd_mesh_vpn.configurable', false) +local fastd_methods = {'salsa2012+gmac', 'salsa2012+umac', 'null+salsa2012+gmac', 'null+salsa2012+umac', 'null'} +need_array_of({'mesh_vpn', 'fastd', 'methods'}, fastd_methods) +need_boolean(in_site({'mesh_vpn', 'fastd', 'configurable'}), false) +need_one_of(in_site({'mesh_vpn', 'fastd', 'syslog_level'}), {'error', 'warn', 'info', 'verbose', 'debug', 'debug2'}, false) -local function check_peer(prefix) - return function(k, _) - assert_uci_name(k) +local function check_peer(k) + need_alphanumeric_key(k) - local table = string.format('%s[%q].', prefix, k) - - need_string(table .. 'key') - need_string_array(table .. 'remotes') - end + need_string_match(in_domain(extend(k, {'key'})), '^%x+$') + need_string_array(in_domain(extend(k, {'remotes'}))) end -local function check_group(prefix) - return function(k, _) - assert_uci_name(k) +local function check_group(k) + need_alphanumeric_key(k) - local table = string.format('%s[%q].', prefix, k) - - need_number(table .. 'limit', false) - need_table(table .. 'peers', check_peer(table .. 'peers'), false) - need_table(table .. 'groups', check_group(table .. 'groups'), false) - end + need_number(extend(k, {'limit'}), false) + need_table(extend(k, {'peers'}), check_peer, false) + need_table(extend(k, {'groups'}), check_group, false) end -need_table('fastd_mesh_vpn.groups', check_group('fastd_mesh_vpn.groups')) - - -if need_table('fastd_mesh_vpn.bandwidth_limit', nil, false) then - need_boolean('fastd_mesh_vpn.bandwidth_limit.enabled', false) - need_number('fastd_mesh_vpn.bandwidth_limit.ingress', false) - need_number('fastd_mesh_vpn.bandwidth_limit.egress', false) -end +need_table({'mesh_vpn', 'fastd', 'groups'}, check_group) diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn-fastd/iptables.rules b/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn-fastd/iptables.rules deleted file mode 100644 index c1a16ee1..00000000 --- a/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn-fastd/iptables.rules +++ /dev/null @@ -1,3 +0,0 @@ -*nat --I OUTPUT -m owner --gid-owner gluon-fastd -o lo -d 127.0.0.1 -p udp --dport 53 -j DNAT --to-destination :54 -COMMIT diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/fastd b/package/gluon-mesh-vpn-fastd/files/lib/gluon/mesh-vpn/fastd new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd b/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd deleted file mode 100755 index 77f2e6f2..00000000 --- a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/400-mesh-vpn-fastd +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local users = require 'gluon.users' -local util = require 'gluon.util' - -local uci = require('luci.model.uci').cursor() -local lutil = require 'luci.util' - - --- The previously used user is removed, we need root privileges to use the packet_mark option -users.remove_user('gluon-fastd') - --- Group for iptables rule -users.add_group('gluon-fastd', 800) - - -local enabled = uci:get('fastd', 'mesh_vpn', 'enabled') -if not enabled then - enabled = site.fastd_mesh_vpn.enabled and 1 or 0 -end - - -local methods - -if site.fastd_mesh_vpn.configurable then - local has_null = lutil.contains(site.fastd_mesh_vpn.methods, 'null') - - local old_methods = uci:get('fastd', 'mesh_vpn', 'method') - if old_methods then - has_null = lutil.contains(old_methods, 'null') - end - - - methods = {} - if has_null then - table.insert(methods, 'null') - end - - for _, method in ipairs(site.fastd_mesh_vpn.methods) do - if method ~= 'null' then - table.insert(methods, method) - end - end - -else - methods = site.fastd_mesh_vpn.methods -end - - -uci:section('fastd', 'fastd', 'mesh_vpn', - { - enabled = enabled, - group = 'gluon-fastd', - syslog_level = 'verbose', - interface = 'mesh-vpn', - mode = 'tap', - mtu = site.fastd_mesh_vpn.mtu, - secure_handshakes = 1, - method = methods, - packet_mark = 1, - status_socket = '/var/run/fastd.mesh_vpn.socket', - } -) -uci:delete('fastd', 'mesh_vpn', 'user') - - -local add_groups - -local function add_peer(group, name, config) - uci:section('fastd', 'peer', group .. '_peer_' .. name, - { - enabled = 1, - net = 'mesh_vpn', - group = group, - key = config.key, - remote = config.remotes, - } - ) -end - -local function add_group(name, config, parent) - uci:delete('fastd', name) - uci:delete_all('fastd', 'peer', - function(peer) - return (peer.net == 'mesh_vpn' and peer.group == name) - end - ) - - - uci:section('fastd', 'peer_group', name, - { - enabled = 1, - net = 'mesh_vpn', - parent = parent, - peer_limit = config.limit, - } - ) - - if config.peers then - for peername, peerconfig in pairs(config.peers) do - add_peer(name, peername, peerconfig) - end - end - - add_groups(name, config.groups, name) -end - --- declared local above -function add_groups(prefix, groups, parent) - if groups then - for name, group in pairs(groups) do - add_group(prefix .. '_' .. name, group, parent) - end - end -end - -add_groups('mesh_vpn', site.fastd_mesh_vpn.groups) - - -uci:save('fastd') - - -uci:section('network', 'interface', 'mesh_vpn', - { - ifname = 'mesh-vpn', - proto = 'batadv', - mesh = 'bat0', - mesh_no_rebroadcast = 1, - macaddr = util.generate_mac(0), - } -) - -uci:save('network') - - -uci:section('firewall', 'include', 'mesh_vpn_dns', - { - type = 'restore', - path = '/lib/gluon/mesh-vpn-fastd/iptables.rules', - family = 'ipv4', - } -) - -uci:save('firewall') diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/420-mesh-vpn-fastd-simple-tc b/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/420-mesh-vpn-fastd-simple-tc deleted file mode 100755 index 3c3e10a4..00000000 --- a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/420-mesh-vpn-fastd-simple-tc +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require('luci.model.uci').cursor() -local fs = require 'nixio.fs' - - -if fs.access('/etc/config/gluon-simple-tc') then - os.rename('/etc/config/gluon-simple-tc', '/etc/config/simple-tc') -end - - -if not uci:get('simple-tc', 'mesh_vpn') then - local config = { - ifname = 'mesh-vpn', - enabled = 0, - } - - - if site.fastd_mesh_vpn.bandwidth_limit then - if site.fastd_mesh_vpn.bandwidth_limit.enabled then - config.enabled = 1 - end - - config.limit_ingress = site.fastd_mesh_vpn.bandwidth_limit.ingress - config.limit_egress = site.fastd_mesh_vpn.bandwidth_limit.egress - end - - uci:section('simple-tc', 'interface', 'mesh_vpn', config) - uci:save('simple-tc') -end diff --git a/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd new file mode 100755 index 00000000..83eff0c7 --- /dev/null +++ b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/400-mesh-vpn-fastd @@ -0,0 +1,98 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local util = require 'gluon.util' + +local uci = require('simple-uci').cursor() + + +local syslog_level = uci:get('fastd', 'mesh_vpn', 'syslog_level') or 'verbose' + +local methods + +if site.mesh_vpn.fastd.configurable(false) then + local has_null = util.contains(site.mesh_vpn.fastd.methods(), 'null') + + local old_methods = uci:get('fastd', 'mesh_vpn', 'method') + if old_methods then + has_null = util.contains(old_methods, 'null') + end + + methods = {} + if has_null then + table.insert(methods, 'null') + end + + for _, method in ipairs(site.mesh_vpn.fastd.methods()) do + if method ~= 'null' then + table.insert(methods, method) + end + end + +else + methods = site.mesh_vpn.fastd.methods() +end + + +uci:section('fastd', 'fastd', 'mesh_vpn', { + group = 'gluon-mesh-vpn', + syslog_level = syslog_level, + interface = 'mesh-vpn', + mode = 'tap', + mtu = site.mesh_vpn.mtu(), + secure_handshakes = true, + method = methods, + packet_mark = 1, + status_socket = '/var/run/fastd.mesh_vpn.socket', +}) +uci:delete('fastd', 'mesh_vpn', 'user') + + +local add_groups + +local function add_peer(group, name, config) + uci:section('fastd', 'peer', group .. '_peer_' .. name, { + enabled = true, + net = 'mesh_vpn', + group = group, + key = config.key, + remote = config.remotes, + }) +end + +local function add_group(name, config, parent) + uci:delete('fastd', name) + uci:delete_all('fastd', 'peer', function(peer) + return (peer.net == 'mesh_vpn' and peer.group == name) + end) + + + uci:section('fastd', 'peer_group', name, { + enabled = true, + net = 'mesh_vpn', + parent = parent, + peer_limit = config.limit, + }) + + if config.peers then + for peername, peerconfig in pairs(config.peers) do + add_peer(name, peername, peerconfig) + end + end + + add_groups(name, config.groups, name) +end + +-- declared local above +function add_groups(prefix, groups, parent) + if groups then + for name, group in pairs(groups) do + add_group(prefix .. '_' .. name, group, parent) + end + end +end + +add_groups('mesh_vpn', site.mesh_vpn.fastd.groups()) + + +uci:save('fastd') diff --git a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret similarity index 85% rename from package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret rename to package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret index e581dea8..f43e8b1f 100755 --- a/package/gluon-mesh-vpn-fastd/files/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret +++ b/package/gluon-mesh-vpn-fastd/luasrc/lib/gluon/upgrade/410-mesh-vpn-fastd-generate-secret @@ -1,6 +1,6 @@ #!/usr/bin/lua -local uci = require 'luci.model.uci' +local uci = require 'simple-uci' local c = uci.cursor() diff --git a/package/gluon-mesh-vpn-fastd/src/respondd.c b/package/gluon-mesh-vpn-fastd/src/respondd.c index 7354783a..4d4b5a37 100644 --- a/package/gluon-mesh-vpn-fastd/src/respondd.c +++ b/package/gluon-mesh-vpn-fastd/src/respondd.c @@ -73,10 +73,63 @@ static struct json_object * get_fastd_version(void) { return ret; } +static struct json_object * get_fastd_public_key(void) { + FILE *f = popen("/etc/init.d/fastd show_key mesh_vpn", "r"); + if (!f) + return NULL; + + char *line = NULL; + size_t len = 0; + + ssize_t r = getline(&line, &len, f); + + pclose(f); + + if (r >= 0) { + len = strlen(line); /* The len given by getline is the buffer size, not the string length */ + + if (len && line[len-1] == '\n') + line[len-1] = 0; + } + else { + free(line); + line = NULL; + } + + return gluonutil_wrap_and_free_string(line); +} + +static bool get_pubkey_privacy(void) { + bool ret = true; + struct json_object *site = NULL; + + site = gluonutil_load_site_config(); + if (!site) + goto end; + + struct json_object *mesh_vpn; + if (!json_object_object_get_ex(site, "mesh_vpn", &mesh_vpn)) + goto end; + + struct json_object *pubkey_privacy; + if (!json_object_object_get_ex(mesh_vpn, "pubkey_privacy", &pubkey_privacy)) + goto end; + + ret = json_object_get_boolean(pubkey_privacy); + +end: + json_object_put(site); + + return ret; +} + static struct json_object * get_fastd(void) { bool enabled = false; + struct json_object *ret = json_object_new_object(); struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + goto disabled_nofree; ctx->flags &= ~UCI_FLAG_STRICT; struct uci_package *p; @@ -91,13 +144,14 @@ static struct json_object * get_fastd(void) { if (!enabled_str || !strcmp(enabled_str, "1")) enabled = true; - disabled: - +disabled: uci_free_context(ctx); - struct json_object *ret = json_object_new_object(); +disabled_nofree: json_object_object_add(ret, "version", get_fastd_version()); json_object_object_add(ret, "enabled", json_object_new_boolean(enabled)); + if (enabled && !get_pubkey_privacy()) + json_object_object_add(ret, "public_key", get_fastd_public_key()); return ret; } @@ -159,6 +213,8 @@ static struct json_object * get_status(void) { struct json_object *ret = NULL; struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + return NULL; ctx->flags &= ~UCI_FLAG_STRICT; struct uci_package *p; @@ -276,11 +332,15 @@ static struct json_object * get_mesh_vpn(void) { if (!site) goto end; - struct json_object *fastd_mesh_vpn; - if (!json_object_object_get_ex(site, "fastd_mesh_vpn", &fastd_mesh_vpn)) + struct json_object *mesh_vpn; + if (!json_object_object_get_ex(site, "mesh_vpn", &mesh_vpn)) goto end; - ret = get_peer_group(fastd_mesh_vpn, peers); + struct json_object *mesh_vpn_fastd; + if (!json_object_object_get_ex(mesh_vpn, "fastd", &mesh_vpn_fastd)) + goto end; + + ret = get_peer_group(mesh_vpn_fastd, peers); end: json_object_put(site); diff --git a/package/gluon-mesh-vpn-tunneldigger/Makefile b/package/gluon-mesh-vpn-tunneldigger/Makefile new file mode 100644 index 00000000..b7a5f18d --- /dev/null +++ b/package/gluon-mesh-vpn-tunneldigger/Makefile @@ -0,0 +1,13 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-mesh-vpn-tunneldigger +PKG_VERSION:=3 + +include ../gluon.mk + +define Package/gluon-mesh-vpn-tunneldigger + TITLE:=Support for connecting meshes via tunneldigger/L2TPv3 pseudowire + DEPENDS:=+gluon-core +gluon-mesh-vpn-core +tunneldigger +@GLUON_SPECIALIZE_KERNEL:KERNEL_L2TP +endef + +$(eval $(call BuildPackageGluon,gluon-mesh-vpn-tunneldigger)) diff --git a/package/gluon-mesh-vpn-tunneldigger/check_site.lua b/package/gluon-mesh-vpn-tunneldigger/check_site.lua new file mode 100644 index 00000000..188433fd --- /dev/null +++ b/package/gluon-mesh-vpn-tunneldigger/check_site.lua @@ -0,0 +1 @@ +need_string_array(in_domain({'mesh_vpn', 'tunneldigger', 'brokers'})) diff --git a/package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/tunneldigger b/package/gluon-mesh-vpn-tunneldigger/files/lib/gluon/mesh-vpn/tunneldigger new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger new file mode 100755 index 00000000..b91288a2 --- /dev/null +++ b/package/gluon-mesh-vpn-tunneldigger/luasrc/lib/gluon/upgrade/400-mesh-vpn-tunneldigger @@ -0,0 +1,33 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local util = require 'gluon.util' + +local uci = require('simple-uci').cursor() + + +local enabled + +-- Delete old broker config section (remove in 2019) +if not uci:get('tunneldigger', 'mesh_vpn') then + if uci:get_first('tunneldigger', 'broker', 'interface') == 'mesh-vpn' then + enabled = uci:get_first('tunneldigger', 'broker', 'enabled') + end + + -- In the usual case (no migration from old tunneldigger package), the + -- enabled state is set in the 500-mesh-vpn script + + uci:delete_all('tunneldigger', 'broker') +end + +uci:section('tunneldigger', 'broker', 'mesh_vpn', { + enabled = enabled, + uuid = util.node_id(), + interface = 'mesh-vpn', + bind_interface = 'br-wan', + group = 'gluon-mesh-vpn', + broker_selection = 'usage', + address = site.mesh_vpn.tunneldigger.brokers(), +}) + +uci:save('tunneldigger') diff --git a/package/gluon-neighbour-info/Makefile b/package/gluon-neighbour-info/Makefile index 63586920..af58036c 100644 --- a/package/gluon-neighbour-info/Makefile +++ b/package/gluon-neighbour-info/Makefile @@ -4,13 +4,9 @@ PKG_NAME:=gluon-neighbour-info PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-neighbour-info - SECTION:=gluon - CATEGORY:=Gluon TITLE:=neighbour-info DEPENDS:= endef @@ -19,23 +15,11 @@ define Package/gluon-neighbour-info/description Gluon community wifi mesh firmware framework: neighbour-info endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Configure -endef - -define Build/Compile - CFLAGS="$(TARGET_CFLAGS)" CPPFLAGS="$(TARGET_CPPFLAGS)" $(MAKE) -C $(PKG_BUILD_DIR) $(TARGET_CONFIGURE_OPTS) -endef - define Package/gluon-neighbour-info/install - $(CP) ./files/* $(1)/ + $(Gluon/Build/Install) $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-neighbour-info $(1)/usr/bin/ endef -$(eval $(call BuildPackage,gluon-neighbour-info)) +$(eval $(call BuildPackageGluon,gluon-neighbour-info)) diff --git a/package/gluon-neighbour-info/files/lib/gluon/upgrade/400-neighbour-info-firewall b/package/gluon-neighbour-info/luasrc/lib/gluon/upgrade/400-neighbour-info-firewall similarity index 58% rename from package/gluon-neighbour-info/files/lib/gluon/upgrade/400-neighbour-info-firewall rename to package/gluon-neighbour-info/luasrc/lib/gluon/upgrade/400-neighbour-info-firewall index 373f166a..54f4a86c 100755 --- a/package/gluon-neighbour-info/files/lib/gluon/upgrade/400-neighbour-info-firewall +++ b/package/gluon-neighbour-info/luasrc/lib/gluon/upgrade/400-neighbour-info-firewall @@ -1,6 +1,6 @@ #!/usr/bin/lua -local uci = require('luci.model.uci').cursor() +local uci = require('simple-uci').cursor() -- Allow incoming respondd replies to queries on WAN -- If the query was via multicast, the response isn't matched by --state RELATED @@ -16,4 +16,16 @@ uci:section('firewall', 'rule', 'wan_respondd_reply', } ) +uci:section('firewall', 'rule', 'mesh_respondd_reply', + { + name = 'mesh_respondd_reply', + src = 'mesh', + src_ip = 'fe80::/64', + src_port = '1001', + dest_port = '32768:61000', -- see /proc/sys/net/ipv4/ip_local_port_range + proto = 'udp', + target = 'ACCEPT', + } +) + uci:save('firewall') diff --git a/package/gluon-neighbour-info/src/gluon-neighbour-info.c b/package/gluon-neighbour-info/src/gluon-neighbour-info.c index c1dd162a..808a1b12 100644 --- a/package/gluon-neighbour-info/src/gluon-neighbour-info.c +++ b/package/gluon-neighbour-info/src/gluon-neighbour-info.c @@ -38,7 +38,7 @@ void usage() { puts("Usage: gluon-neighbour-info [-h] [-s] [-l] [-c ] [-t ] -d -p -i -r "); puts(" -p UDP port"); - puts(" -d multicast group, e.g. ff02:0:0:0:0:0:2:1001"); + puts(" -d destination address (unicast ip6 or multicast group, e.g. ff02:0:0:0:0:0:2:1001)"); puts(" -i interface, e.g. eth0 "); puts(" -r request, e.g. nodeinfo"); puts(" -t timeout in seconds (default: 3)"); @@ -145,7 +145,6 @@ int main(int argc, char **argv) { } client_addr.sin6_family = AF_INET6; - client_addr.sin6_addr = in6addr_any; opterr = 0; @@ -206,10 +205,20 @@ int main(int argc, char **argv) { } if (request_string == NULL) { - fprintf(stderr, "No request string supplied"); + fprintf(stderr, "No request string supplied\n"); exit(EXIT_FAILURE); } + if (client_addr.sin6_port == htons(0)) { + fprintf(stderr, "No port supplied\n"); + exit(EXIT_FAILURE); + } + + if (IN6_IS_ADDR_UNSPECIFIED(&client_addr.sin6_addr)) { + fprintf(stderr, "No destination address supplied\n"); + exit(EXIT_FAILURE); + } + if (sse) { fputs("Content-Type: text/event-stream\n\n", stdout); fflush(stdout); diff --git a/package/gluon-next-node/Makefile b/package/gluon-next-node/Makefile deleted file mode 100644 index df27ecbe..00000000 --- a/package/gluon-next-node/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-next-node -PKG_VERSION:=3 - -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk - -define Package/gluon-next-node - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Next-node anycast address - DEPENDS:=+gluon-core +gluon-ebtables +gluon-mesh-batman-adv +kmod-macvlan -endef - -define Package/gluon-next-node/description - Gluon community wifi mesh firmware framework: next-node anycast address -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-next-node/install - $(CP) ./files/* $(1)/ -endef - -define Package/gluon-next-node/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-next-node)) diff --git a/package/gluon-next-node/check_site.lua b/package/gluon-next-node/check_site.lua deleted file mode 100644 index 83889a8e..00000000 --- a/package/gluon-next-node/check_site.lua +++ /dev/null @@ -1,4 +0,0 @@ -need_string_match('next_node.ip4', '^%d+.%d+.%d+.%d+$') -need_string_match('next_node.ip6', '^[%x:]+$') - -need_string_match('next_node.mac', '^%x[02468aAcCeE]:%x%x:%x%x:%x%x:%x%x:%x%x$') diff --git a/package/gluon-next-node/files/lib/gluon/ebtables/250-next-node b/package/gluon-next-node/files/lib/gluon/ebtables/250-next-node deleted file mode 100644 index 0df7abcc..00000000 --- a/package/gluon-next-node/files/lib/gluon/ebtables/250-next-node +++ /dev/null @@ -1,20 +0,0 @@ -local site = require 'gluon.site_config' -local next_node = site.next_node - -rule('FORWARD --logical-in br-client -p ARP --arp-ip-src ' .. next_node.ip4 .. ' -j DROP') -rule('FORWARD --logical-in br-client -p ARP --arp-ip-dst ' .. next_node.ip4 .. ' -j DROP') - -rule('FORWARD --logical-out br-client -o bat0 -d ' .. next_node.mac .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -d ' .. next_node.mac .. ' -j DROP') -rule('FORWARD --logical-out br-client -o bat0 -s ' .. next_node.mac .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -s ' .. next_node.mac .. ' -j DROP') - -rule('FORWARD --logical-out br-client -o bat0 -p IPv4 --ip-destination ' .. next_node.ip4 .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -p IPv4 --ip-destination ' .. next_node.ip4 .. ' -j DROP') -rule('FORWARD --logical-out br-client -o bat0 -p IPv4 --ip-source ' .. next_node.ip4 .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -p IPv4 --ip-source ' .. next_node.ip4 .. ' -j DROP') - -rule('FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-destination ' .. next_node.ip6 .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-destination ' .. next_node.ip6 .. ' -j DROP') -rule('FORWARD --logical-out br-client -o bat0 -p IPv6 --ip6-source ' .. next_node.ip6 .. ' -j DROP') -rule('OUTPUT --logical-out br-client -o bat0 -p IPv6 --ip6-source ' .. next_node.ip6 .. ' -j DROP') diff --git a/package/gluon-next-node/files/lib/gluon/upgrade/400-next-node b/package/gluon-next-node/files/lib/gluon/upgrade/400-next-node deleted file mode 100755 index 79cc0369..00000000 --- a/package/gluon-next-node/files/lib/gluon/upgrade/400-next-node +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' -local ip = require 'luci.ip' - -local c = uci.cursor() - - -c:delete('network', 'local_node_dev') -c:section('network', 'device', 'local_node_dev', - { - name = 'local-node', - ifname = 'br-client', - type = 'macvlan', - macaddr = site.next_node.mac, - } -) - -local prefix4 = ip.IPv4(site.prefix4) -c:delete('network', 'local_node') -c:section('network', 'interface', 'local_node', - { - ifname = 'local-node', - proto = 'static', - ipaddr = site.next_node.ip4, - netmask = prefix4:mask():string(), - ip6addr = site.next_node.ip6 .. '/128', - } -) - -c:delete('network', 'local_node_route6') -c:section('network', 'route6', 'local_node_route6', - { - interface = 'client', - target = site.prefix6, - gateway = '::', - } -) - -c:save('network') - -c:delete('firewall', 'local_node') -c:section('firewall', 'zone', 'local_node', - { - name = 'local_node', - network = {'local_node'}, - input = 'ACCEPT', - output = 'ACCEPT', - forward = 'REJECT', - } -) -c:save('firewall') diff --git a/package/gluon-node-info/Makefile b/package/gluon-node-info/Makefile index a5ac8ddc..7718fa2b 100644 --- a/package/gluon-node-info/Makefile +++ b/package/gluon-node-info/Makefile @@ -4,33 +4,11 @@ PKG_NAME:=gluon-node-info PKG_VERSION:=1 PKG_RELEASE:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS := respondd - -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-node-info - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Add /etc/config/gluon-node-info to uci DEPENDS:=+gluon-core +libgluonutil endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/gluon-node-info/install - $(CP) ./files/* $(1)/ - - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/node-info.so -endef - -define Package/gluon-node-info/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-node-info)) +$(eval $(call BuildPackageGluon,gluon-node-info)) diff --git a/package/gluon-node-info/check_site.lua b/package/gluon-node-info/check_site.lua index 7e50edfc..d1d6712a 100644 --- a/package/gluon-node-info/check_site.lua +++ b/package/gluon-node-info/check_site.lua @@ -1 +1 @@ -need_string('roles.default', false) +need_string(in_site({'roles', 'default'}), false) diff --git a/package/gluon-node-info/files/lib/gluon/upgrade/510-node-info-role b/package/gluon-node-info/files/lib/gluon/upgrade/510-node-info-role deleted file mode 100755 index 06d42f8e..00000000 --- a/package/gluon-node-info/files/lib/gluon/upgrade/510-node-info-role +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require('luci.model.uci').cursor() - -local config = 'gluon-node-info' -local role = uci:get(config, uci:get_first(config, 'system'), 'role') - -if site.roles then - default_role = site.roles.default -else - default_role = '' -end - -if not role then - uci:set(config, uci:get_first(config, 'system'), 'role', default_role) - uci:save(config) -end diff --git a/package/gluon-node-info/files/lib/gluon/upgrade/500-node-info-system b/package/gluon-node-info/luasrc/lib/gluon/upgrade/500-node-info-system similarity index 76% rename from package/gluon-node-info/files/lib/gluon/upgrade/500-node-info-system rename to package/gluon-node-info/luasrc/lib/gluon/upgrade/500-node-info-system index a70eb282..6ee047ec 100755 --- a/package/gluon-node-info/files/lib/gluon/upgrade/500-node-info-system +++ b/package/gluon-node-info/luasrc/lib/gluon/upgrade/500-node-info-system @@ -1,6 +1,6 @@ #!/usr/bin/lua -local uci = require('luci.model.uci').cursor() +local uci = require('simple-uci').cursor() local config = 'gluon-node-info' diff --git a/package/gluon-node-info/luasrc/lib/gluon/upgrade/510-node-info-role b/package/gluon-node-info/luasrc/lib/gluon/upgrade/510-node-info-role new file mode 100755 index 00000000..014f3f6f --- /dev/null +++ b/package/gluon-node-info/luasrc/lib/gluon/upgrade/510-node-info-role @@ -0,0 +1,12 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + +local config = 'gluon-node-info' +local role = uci:get(config, uci:get_first(config, 'system'), 'role') + +if not role then + uci:set(config, uci:get_first(config, 'system'), 'role', site.roles.default('')) + uci:save(config) +end diff --git a/package/gluon-node-info/files/lib/gluon/upgrade/520-node-info-whitespace-fix b/package/gluon-node-info/luasrc/lib/gluon/upgrade/520-node-info-whitespace-fix similarity index 68% rename from package/gluon-node-info/files/lib/gluon/upgrade/520-node-info-whitespace-fix rename to package/gluon-node-info/luasrc/lib/gluon/upgrade/520-node-info-whitespace-fix index 49e7053d..62cd4beb 100755 --- a/package/gluon-node-info/files/lib/gluon/upgrade/520-node-info-whitespace-fix +++ b/package/gluon-node-info/luasrc/lib/gluon/upgrade/520-node-info-whitespace-fix @@ -1,5 +1,6 @@ #!/usr/bin/lua -local uci = require('luci.model.uci').cursor() +local uci = require('simple-uci').cursor() +local util = require 'gluon.util' local sname = uci:get_first('gluon-node-info', 'location') if sname then @@ -7,7 +8,7 @@ if sname then for _, option in ipairs(options) do local value = uci:get('gluon-node-info', sname, option) if value then - uci:set('gluon-node-info', sname, option, value:trim()) + uci:set('gluon-node-info', sname, option, util.trim(value)) end end uci:save('gluon-node-info') diff --git a/package/gluon-node-info/src/respondd.c b/package/gluon-node-info/src/respondd.c index 3b0e07dc..7d5e2edf 100644 --- a/package/gluon-node-info/src/respondd.c +++ b/package/gluon-node-info/src/respondd.c @@ -117,6 +117,8 @@ static struct json_object * respondd_provider_nodeinfo(void) { struct json_object *ret = json_object_new_object(); struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + return ret; ctx->flags &= ~UCI_FLAG_STRICT; struct uci_package *p; diff --git a/package/gluon-radv-filterd/Makefile b/package/gluon-radv-filterd/Makefile new file mode 100644 index 00000000..28d778c1 --- /dev/null +++ b/package/gluon-radv-filterd/Makefile @@ -0,0 +1,25 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-radv-filterd +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-radv-filterd + TITLE:=Filter IPv6 router advertisements + DEPENDS:=+gluon-ebtables +libgluonutil +libbatadv +libnl-tiny +endef + +MAKE_VARS += \ + LIBNL_NAME="libnl-tiny" \ + LIBNL_GENL_NAME="libnl-tiny" + +define Package/gluon-radv-filterd/install + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/usr/sbin/ + $(INSTALL_BIN) $(PKG_BUILD_DIR)/gluon-radv-filterd $(1)/usr/sbin/ +endef + +$(eval $(call BuildPackageGluon,gluon-radv-filterd)) diff --git a/package/gluon-radv-filterd/check_site.lua b/package/gluon-radv-filterd/check_site.lua new file mode 100644 index 00000000..fa38475d --- /dev/null +++ b/package/gluon-radv-filterd/check_site.lua @@ -0,0 +1 @@ +need_number({'radv_filterd', 'threshold'}, false) diff --git a/package/gluon-radv-filterd/files/etc/init.d/gluon-radv-filterd b/package/gluon-radv-filterd/files/etc/init.d/gluon-radv-filterd new file mode 100755 index 00000000..04906e56 --- /dev/null +++ b/package/gluon-radv-filterd/files/etc/init.d/gluon-radv-filterd @@ -0,0 +1,22 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +START=50 +DAEMON=/usr/sbin/gluon-radv-filterd + +start_service() { + local threshold="$(lua -e 'print(require("gluon.site").radv_filterd.threshold(20))')" + + procd_open_instance + procd_set_param command $DAEMON -i br-client -c RADV_FILTER -t $threshold + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + procd_set_param netdev br-client + procd_set_param stderr 1 + procd_close_instance +} + +service_triggers() { + procd_open_trigger + procd_add_raw_trigger "interface.*" 1000 /etc/init.d/gluon-radv-filterd reload + procd_close_trigger +} diff --git a/package/gluon-radv-filterd/files/lib/gluon/ebtables/400-radv-filterd b/package/gluon-radv-filterd/files/lib/gluon/ebtables/400-radv-filterd new file mode 100644 index 00000000..178084d4 --- /dev/null +++ b/package/gluon-radv-filterd/files/lib/gluon/ebtables/400-radv-filterd @@ -0,0 +1,3 @@ +chain('RADV_FILTER', 'DROP') +rule 'FORWARD -p IPv6 -i bat0 --ip6-protocol ipv6-icmp --ip6-icmp-type router-advertisement -j RADV_FILTER' +rule 'RADV_FILTER -j ACCEPT' diff --git a/package/gluon-radv-filterd/src/Makefile b/package/gluon-radv-filterd/src/Makefile new file mode 100644 index 00000000..17b65584 --- /dev/null +++ b/package/gluon-radv-filterd/src/Makefile @@ -0,0 +1,49 @@ +all: gluon-radv-filterd respondd.so + +CPPFLAGS += -D_GNU_SOURCE + +ifeq ($(origin PKG_CONFIG), undefined) + PKG_CONFIG = pkg-config + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif +endif + +ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined) + LIBNL_NAME ?= libnl-3.0 + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),) + $(error No $(LIBNL_NAME) development libraries found!) + endif + LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME)) + LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME)) +endif +CFLAGS += $(LIBNL_CFLAGS) +LDLIBS += $(LIBNL_LDLIBS) + +ifeq ($(origin LIBNL_GENL_CFLAGS) $(origin LIBNL_GENL_LDLIBS), undefined undefined) + LIBNL_GENL_NAME ?= libnl-genl-3.0 + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_GENL_NAME) 2>/dev/null),) + $(error No $(LIBNL_GENL_NAME) development libraries found!) + endif + LIBNL_GENL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_GENL_NAME)) + LIBNL_GENL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_GENL_NAME)) +endif +CFLAGS += $(LIBNL_GENL_CFLAGS) +LDLIBS += $(LIBNL_GENL_LDLIBS) + +ifeq ($(origin LIBBATADV_CFLAGS) $(origin LIBBATADV_LDLIBS), undefined undefined) + LIBBATADV_NAME ?= libbatadv + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBBATADV_NAME) 2>/dev/null),) + $(error No $(LIBBATADV_NAME) development libraries found!) + endif + LIBBATADV_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBBATADV_NAME)) + LIBBATADV_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBBATADV_NAME)) +endif +CFLAGS += $(LIBBATADV_CFLAGS) +LDLIBS += $(LIBBATADV_LDLIBS) + +gluon-radv-filterd: gluon-radv-filterd.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS) + +respondd.so: respondd.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -o $@ $^ $(LDLIBS) -lgluonutil diff --git a/package/gluon-radv-filterd/src/gluon-radv-filterd.c b/package/gluon-radv-filterd/src/gluon-radv-filterd.c new file mode 100644 index 00000000..75c980fd --- /dev/null +++ b/package/gluon-radv-filterd/src/gluon-radv-filterd.c @@ -0,0 +1,819 @@ +/* + Copyright (c) 2016 Jan-Philipp Litza + Copyright (c) 2017 Sven Eckelmann + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "mac.h" + +// Recheck TQs after this time even if no RA was received +#define MAX_INTERVAL 60 + +// Recheck TQs at most this often, even if new RAs were received (they won't +// become the preferred routers until the TQs have been rechecked) +// Also, the first update will take at least this long +#define MIN_INTERVAL 15 + +// Remember the originator of a router for at most this period of time (in +// seconds). Re-read it from the transtable afterwards. +#define ORIGINATOR_CACHE_TTL 300 + +// max execution time of a single ebtables call in nanoseconds +#define EBTABLES_TIMEOUT 500000000 // 500ms + +// TQ value assigned to local routers +#define LOCAL_TQ 512 + +#define BUFSIZE 1500 + +#ifdef DEBUG +#define CHECK(stmt) \ + if(!(stmt)) { \ + fprintf(stderr, "check failed: " #stmt "\n"); \ + goto check_failed; \ + } +#define DEBUG_MSG(msg, ...) fprintf(stderr, msg "\n", ##__VA_ARGS__) +#else +#define CHECK(stmt) if(!(stmt)) goto check_failed; +#define DEBUG_MSG(msg, ...) do {} while(0) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0])) +#endif + +#define foreach(item, list) \ + for((item) = (list); (item) != NULL; (item) = (item)->next) + +#define foreach_safe(item, safe, list) \ + for ((item) = (list); \ + (item) && (((safe) = item->next) || 1); \ + (item) = (safe)) + +struct router { + struct router *next; + struct ether_addr src; + struct timespec eol; + struct ether_addr originator; + uint16_t tq; +}; + +static struct global { + int sock; + struct router *routers; + const char *mesh_iface; + const char *chain; + uint16_t max_tq; + uint16_t hysteresis_thresh; + struct router *best_router; + volatile sig_atomic_t stop_daemon; +} G = { + .mesh_iface = "bat0", +}; + +static int fork_execvp_timeout(struct timespec *timeout, const char *file, + const char *const argv[]); + +static void error_message(int status, int errnum, char *message, ...) { + va_list ap; + va_start(ap, message); + fflush(stdout); + vfprintf(stderr, message, ap); + va_end(ap); + + if (errnum) + fprintf(stderr, ": %s", strerror(errnum)); + fprintf(stderr, "\n"); + if (status) + exit(status); +} + +static int timespec_diff(struct timespec *tv1, struct timespec *tv2, + struct timespec *tvdiff) +{ + tvdiff->tv_sec = tv1->tv_sec - tv2->tv_sec; + if (tv1->tv_nsec < tv2->tv_nsec) { + tvdiff->tv_nsec = 1000000000 + tv1->tv_nsec - tv2->tv_nsec; + tvdiff->tv_sec -= 1; + } else { + tvdiff->tv_nsec = tv1->tv_nsec - tv2->tv_nsec; + } + + return (tvdiff->tv_sec >= 0); +} + +static void cleanup(void) { + struct router *router; + struct timespec timeout = { + .tv_nsec = EBTABLES_TIMEOUT, + }; + + close(G.sock); + + while (G.routers != NULL) { + router = G.routers; + G.routers = router->next; + free(router); + } + + if (G.chain) { + /* Reset chain to accept everything again */ + if (fork_execvp_timeout(&timeout, "ebtables-tiny", (const char *[]) + { "ebtables-tiny", "-F", G.chain, NULL })) + DEBUG_MSG("warning: flushing ebtables chain %s failed, not adding a new rule", G.chain); + + if (fork_execvp_timeout(&timeout, "ebtables-tiny", (const char *[]) + { "ebtables-tiny", "-A", G.chain, "-j", "ACCEPT", NULL })) + DEBUG_MSG("warning: adding new rule to ebtables chain %s failed", G.chain); + } +} + +static void usage(const char *msg) { + if (msg != NULL && *msg != '\0') { + fprintf(stderr, "ERROR: %s\n\n", msg); + } + fprintf(stderr, + "Usage: %s [-m ] [-t ] -c -i \n\n" + " -m B.A.T.M.A.N. advanced mesh interface used to get metric\n" + " information (\"TQ\") for the available gateways. Default: bat0\n" + " -t Minimum TQ difference required to switch the gateway.\n" + " Default: 0\n" + " -c ebtables chain that should be managed by the daemon. The\n" + " chain already has to exist on program invocation and should\n" + " have a DROP policy. It will be flushed by the program!\n" + " -i Interface to listen on for router advertisements. Should be\n" + " or a bridge on top of it, as no metric\n" + " information will be available for hosts on other interfaces.\n\n", + program_invocation_short_name); + cleanup(); + if (msg == NULL) + exit(EXIT_SUCCESS); + else + exit(EXIT_FAILURE); +} + +#define exit_errmsg(message, ...) { \ + fprintf(stderr, message "\n", ##__VA_ARGS__); \ + cleanup(); \ + exit(1); \ + } + +static inline void exit_errno(const char *message) { + cleanup(); + error_message(1, errno, "error: %s", message); +} + +static inline void warn_errno(const char *message) { + error_message(0, errno, "warning: %s", message); +} + +static int init_packet_socket(unsigned int ifindex) { + struct sock_filter radv_filter_code[] = { + // check that this is an ICMPv6 packet + BPF_STMT(BPF_LD|BPF_B|BPF_ABS, offsetof(struct ip6_hdr, ip6_nxt)), + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, IPPROTO_ICMPV6, 0, 7), + // check that this is a router advertisement + BPF_STMT(BPF_LD|BPF_B|BPF_ABS, sizeof(struct ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)), + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, ND_ROUTER_ADVERT, 0, 5), + // check that the code field in the ICMPv6 header is 0 + BPF_STMT(BPF_LD|BPF_B|BPF_ABS, sizeof(struct ip6_hdr) + offsetof(struct nd_router_advert, nd_ra_code)), + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0, 0, 3), + // check that this is a default route (lifetime > 0) + BPF_STMT(BPF_LD|BPF_H|BPF_ABS, sizeof(struct ip6_hdr) + offsetof(struct nd_router_advert, nd_ra_router_lifetime)), + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0, 1, 0), + // return true + BPF_STMT(BPF_RET|BPF_K, 0xffffffff), + // return false + BPF_STMT(BPF_RET|BPF_K, 0), + }; + + struct sock_fprog radv_filter = { + .len = ARRAY_SIZE(radv_filter_code), + .filter = radv_filter_code, + }; + + int sock = socket(AF_PACKET, SOCK_DGRAM|SOCK_CLOEXEC, htons(ETH_P_IPV6)); + if (sock < 0) + exit_errno("can't open packet socket"); + int ret = setsockopt(sock, SOL_SOCKET, SO_ATTACH_FILTER, &radv_filter, sizeof(radv_filter)); + if (ret < 0) + exit_errno("can't attach socket filter"); + + struct sockaddr_ll bind_iface = { + .sll_family = AF_PACKET, + .sll_protocol = htons(ETH_P_IPV6), + .sll_ifindex = ifindex, + }; + ret = bind(sock, (struct sockaddr *)&bind_iface, sizeof(bind_iface)); + if (ret < 0) + exit_errno("can't bind socket"); + + return sock; +} + +static void parse_cmdline(int argc, char *argv[]) { + int c; + unsigned int ifindex; + unsigned long int threshold; + char *endptr; + while ((c = getopt(argc, argv, "c:hi:m:t:")) != -1) { + switch (c) { + case 'i': + if (G.sock >= 0) + usage("-i given more than once"); + ifindex = if_nametoindex(optarg); + if (ifindex == 0) + exit_errmsg("Unknown interface: %s", optarg); + G.sock = init_packet_socket(ifindex); + break; + case 'm': + G.mesh_iface = optarg; + break; + case 'c': + G.chain = optarg; + break; + case 't': + threshold = strtoul(optarg, &endptr, 10); + if (*endptr != '\0') + exit_errmsg("Threshold must be a number: %s", optarg); + if (threshold >= LOCAL_TQ) + exit_errmsg("Threshold too large: %ld (max is %d)", threshold, LOCAL_TQ); + G.hysteresis_thresh = (uint16_t) threshold; + break; + case 'h': + usage(NULL); + break; + default: + usage(""); + break; + } + } +} + +static struct router *router_find_src(const struct ether_addr *src) { + struct router *router; + + foreach(router, G.routers) { + if (ether_addr_equal(router->src, *src)) + return router; + } + + return NULL; +} + +static struct router *router_find_orig(const struct ether_addr *orig) { + struct router *router; + + foreach(router, G.routers) { + if (ether_addr_equal(router->originator, *orig)) + return router; + } + + return NULL; +} + +static struct router *router_add(const struct ether_addr *mac) { + struct router *router; + + router = malloc(sizeof(*router)); + if (!router) + return NULL; + + router->src = *mac; + router->next = G.routers; + G.routers = router; + router->eol.tv_sec = 0; + router->eol.tv_nsec = 0; + memset(&router->originator, 0, sizeof(router->originator)); + + return router; +} + +static void router_update(const struct ether_addr *mac, uint16_t timeout) { + struct router *router; + + router = router_find_src(mac); + if (!router) + router = router_add(mac); + if (!router) + return; + + clock_gettime(CLOCK_MONOTONIC, &router->eol); + router->eol.tv_sec += timeout; +} + +static void handle_ra(int sock) { + struct sockaddr_ll src; + struct ether_addr mac; + socklen_t addr_size = sizeof(src); + ssize_t len; + struct { + struct ip6_hdr ip6; + struct nd_router_advert ra; + } pkt; + + len = recvfrom(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *)&src, &addr_size); + CHECK(len >= 0); + + // BPF already checked that this is an ICMPv6 RA of a default router + CHECK((size_t)len >= sizeof(pkt)); + CHECK(ntohs(pkt.ip6.ip6_plen) + sizeof(struct ip6_hdr) >= sizeof(pkt)); + + memcpy(&mac, src.sll_addr, sizeof(mac)); + DEBUG_MSG("received valid RA from " F_MAC, F_MAC_VAR(mac)); + + router_update(&mac, ntohs(pkt.ra.nd_ra_router_lifetime)); + +check_failed: + return; +} + +static void expire_routers(void) { + struct router **prev_ptr = &G.routers; + struct router *router; + struct router *safe; + struct timespec now; + struct timespec diff; + + clock_gettime(CLOCK_MONOTONIC, &now); + + foreach_safe(router, safe, G.routers) { + if (timespec_diff(&now, &router->eol, &diff)) { + DEBUG_MSG("router " F_MAC " expired", F_MAC_VAR(router->src)); + *prev_ptr = router->next; + if (G.best_router == router) + G.best_router = NULL; + free(router); + } else { + prev_ptr = &router->next; + } + } +} + +static int parse_tt_global(struct nl_msg *msg, + void *arg __attribute__((unused))) +{ + static const enum batadv_nl_attrs mandatory[] = { + BATADV_ATTR_TT_ADDRESS, + BATADV_ATTR_ORIG_ADDRESS, + }; + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct ether_addr mac_a, mac_b; + struct genlmsghdr *ghdr; + struct router *router; + uint8_t *addr; + uint8_t *orig; + + // parse netlink entry + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_GLOBAL) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) { + return NL_OK; + } + + if (batadv_genl_missing_attrs(attrs, mandatory, ARRAY_SIZE(mandatory))) + return NL_OK; + + addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]); + orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]); + + if (!attrs[BATADV_ATTR_FLAG_BEST]) + return NL_OK; + + MAC2ETHER(mac_a, addr); + MAC2ETHER(mac_b, orig); + + // update router + router = router_find_src(&mac_a); + if (!router) + return NL_OK; + + DEBUG_MSG("Found originator for " F_MAC ", it's " F_MAC, + F_MAC_VAR(router->src), F_MAC_VAR(mac_b)); + router->originator = mac_b; + + return NL_OK; +} + +static int parse_originator(struct nl_msg *msg, + void *arg __attribute__((unused))) +{ + + static const enum batadv_nl_attrs mandatory[] = { + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_TQ, + }; + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct ether_addr mac_a; + struct genlmsghdr *ghdr; + struct router *router; + uint8_t *orig; + uint8_t tq; + + // parse netlink entry + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) { + return NL_OK; + } + + if (batadv_genl_missing_attrs(attrs, mandatory, ARRAY_SIZE(mandatory))) + return NL_OK; + + orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]); + tq = nla_get_u8(attrs[BATADV_ATTR_TQ]); + + if (!attrs[BATADV_ATTR_FLAG_BEST]) + return NL_OK; + + MAC2ETHER(mac_a, orig); + + // update router + router = router_find_orig(&mac_a); + if (!router) + return NL_OK; + + DEBUG_MSG("Found TQ for router " F_MAC " (originator " F_MAC "), it's %d", + F_MAC_VAR(router->src), F_MAC_VAR(router->originator), tq); + router->tq = tq; + if (router->tq > G.max_tq) + G.max_tq = router->tq; + + return NL_OK; +} + +static int parse_tt_local(struct nl_msg *msg, + void *arg __attribute__((unused))) +{ + static const enum batadv_nl_attrs mandatory[] = { + BATADV_ATTR_TT_ADDRESS, + }; + struct nlattr *attrs[BATADV_ATTR_MAX + 1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct ether_addr mac_a; + struct genlmsghdr *ghdr; + struct router *router; + uint8_t *addr; + + // parse netlink entry + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_TRANSTABLE_LOCAL) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) { + return NL_OK; + } + + if (batadv_genl_missing_attrs(attrs, mandatory, ARRAY_SIZE(mandatory))) + return NL_OK; + + addr = nla_data(attrs[BATADV_ATTR_TT_ADDRESS]); + MAC2ETHER(mac_a, addr); + + // update router + router = router_find_src(&mac_a); + if (!router) + return NL_OK; + + DEBUG_MSG("Found router " F_MAC " in transtable_local, assigning TQ %d", + F_MAC_VAR(router->src), LOCAL_TQ); + router->tq = LOCAL_TQ; + if (router->tq > G.max_tq) + G.max_tq = router->tq; + + return NL_OK; +} + +static void update_tqs(void) { + struct router *router; + bool update_originators = false; + struct ether_addr unspec; + struct batadv_nlquery_opts opts; + int ret; + + // reset TQs + memset(&unspec, 0, sizeof(unspec)); + foreach(router, G.routers) { + router->tq = 0; + if (ether_addr_equal(router->originator, unspec)) + update_originators = true; + } + + // translate all router's MAC addresses to originators simultaneously + if (update_originators) { + opts.err = 0; + ret = batadv_genl_query(G.mesh_iface, + BATADV_CMD_GET_TRANSTABLE_GLOBAL, + parse_tt_global, NLM_F_DUMP, &opts); + if (ret < 0) + fprintf(stderr, "Parsing of global translation table failed\n"); + } + + // look up TQs of originators + G.max_tq = 0; + opts.err = 0; + ret = batadv_genl_query(G.mesh_iface, + BATADV_CMD_GET_ORIGINATORS, + parse_originator, NLM_F_DUMP, &opts); + if (ret < 0) + fprintf(stderr, "Parsing of originators failed\n"); + + // if all routers have a TQ value, we don't need to check translocal + foreach(router, G.routers) { + if (router->tq == 0) + break; + } + if (router != NULL) { + opts.err = 0; + ret = batadv_genl_query(G.mesh_iface, + BATADV_CMD_GET_TRANSTABLE_LOCAL, + parse_tt_local, NLM_F_DUMP, &opts); + if (ret < 0) + fprintf(stderr, "Parsing of global translation table failed\n"); + } + + foreach(router, G.routers) { + if (router->tq == 0) { + if (ether_addr_equal(router->originator, unspec)) + fprintf(stderr, + "Unable to find router " F_MAC " in transtable_{global,local}\n", + F_MAC_VAR(router->src)); + else + fprintf(stderr, + "Unable to find TQ for originator " F_MAC " (router " F_MAC ")\n", + F_MAC_VAR(router->originator), + F_MAC_VAR(router->src)); + } + } +} + +static int fork_execvp_timeout(struct timespec *timeout, const char *file, const char *const argv[]) { + int ret; + pid_t child; + siginfo_t info; + sigset_t signals, oldsignals; + sigemptyset(&signals); + sigaddset(&signals, SIGCHLD); + + sigprocmask(SIG_BLOCK, &signals, &oldsignals); + child = fork(); + if (child == 0) { + sigprocmask(SIG_SETMASK, &oldsignals, NULL); + // casting discards const, but should be safe + // (see http://stackoverflow.com/q/36925388) + execvp(file, (char**) argv); + fprintf(stderr, "can't execvp(\"%s\", ...): %s\n", file, strerror(errno)); + _exit(1); + } + else if (child < 0) { + perror("Failed to fork()"); + return -1; + } + + ret = sigtimedwait(&signals, &info, timeout); + sigprocmask(SIG_SETMASK, &oldsignals, NULL); + + if (ret == SIGCHLD) { + if (info.si_pid != child) { + cleanup(); + error_message(1, 0, + "BUG: We received a SIGCHLD from a child we didn't spawn (expected PID %d, got %d)", + child, info.si_pid); + } + + waitpid(child, NULL, 0); + + return info.si_status; + } + + if (ret < 0 && errno == EAGAIN) + error_message(0, 0, "warning: child %d took too long, killing", child); + else if (ret < 0) + warn_errno("sigtimedwait failed, killing child"); + else + error_message(1, 0, + "BUG: sigtimedwait() returned some other signal than SIGCHLD: %d", + ret); + + kill(child, SIGKILL); + kill(child, SIGCONT); + waitpid(child, NULL, 0); + return -1; +} + +static bool election_required(void) +{ + if (!G.best_router) + return true; + + /* should never happen. G.max_tq also contains G.best_router->tq */ + if (G.max_tq < G.best_router->tq) + return false; + + if ((G.max_tq - G.best_router->tq) <= G.hysteresis_thresh) + return false; + + return true; +} + +static void update_ebtables(void) { + struct timespec timeout = { + .tv_nsec = EBTABLES_TIMEOUT, + }; + char mac[F_MAC_LEN + 1]; + struct router *router; + + if (!election_required()) { + DEBUG_MSG(F_MAC " is still good enough with TQ=%d (max_tq=%d), not executing ebtables", + F_MAC_VAR(G.best_router->src), + G.best_router->tq, + G.max_tq); + return; + } + + foreach(router, G.routers) { + if (router->tq == G.max_tq) { + snprintf(mac, sizeof(mac), F_MAC, F_MAC_VAR(router->src)); + break; + } + } + if (G.best_router) + fprintf(stderr, "Switching from " F_MAC " (TQ=%d) to %s (TQ=%d)\n", + F_MAC_VAR(G.best_router->src), + G.best_router->tq, + mac, + G.max_tq); + else + fprintf(stderr, "Switching to %s (TQ=%d)\n", + mac, + G.max_tq); + G.best_router = router; + + if (fork_execvp_timeout(&timeout, "ebtables-tiny", (const char *[]) + { "ebtables-tiny", "-F", G.chain, NULL })) + error_message(0, 0, "warning: flushing ebtables chain %s failed, not adding a new rule", G.chain); + else if (fork_execvp_timeout(&timeout, "ebtables-tiny", (const char *[]) + { "ebtables-tiny", "-A", G.chain, "-s", mac, "-j", "ACCEPT", NULL })) + error_message(0, 0, "warning: adding new rule to ebtables chain %s failed", G.chain); +} + +static void invalidate_originators(void) +{ + struct router *router; + foreach(router, G.routers) { + memset(&router->originator, 0, sizeof(router->originator)); + } +} + +static void sighandler(int sig __attribute__((unused))) +{ + G.stop_daemon = 1; +} + +int main(int argc, char *argv[]) { + int retval; + fd_set rfds; + struct timeval tv; + struct timespec next_update; + struct timespec next_invalidation; + struct timespec now; + struct timespec diff; + + clock_gettime(CLOCK_MONOTONIC, &next_update); + next_update.tv_sec += MIN_INTERVAL; + + clock_gettime(CLOCK_MONOTONIC, &next_invalidation); + next_invalidation.tv_sec += MIN_INTERVAL; + + G.sock = -1; + parse_cmdline(argc, argv); + + if (G.sock < 0) + usage("No interface set!"); + + if (G.chain == NULL) + usage("No chain set!"); + + G.stop_daemon = 0; + signal(SIGINT, sighandler); + signal(SIGTERM, sighandler); + + while (!G.stop_daemon) { + FD_ZERO(&rfds); + FD_SET(G.sock, &rfds); + + tv.tv_sec = MAX_INTERVAL; + tv.tv_usec = 0; + retval = select(G.sock + 1, &rfds, NULL, NULL, &tv); + + if (retval < 0) { + if (errno != EINTR) + exit_errno("select() failed"); + } else if (retval) { + if (FD_ISSET(G.sock, &rfds)) { + handle_ra(G.sock); + } + } + else + DEBUG_MSG("select() timeout expired"); + + clock_gettime(CLOCK_MONOTONIC, &now); + if (G.routers != NULL && + timespec_diff(&now, &next_update, &diff)) { + expire_routers(); + + // all routers could have expired, check again + if (G.routers != NULL) { + if(timespec_diff(&now, &next_invalidation, &diff)) { + invalidate_originators(); + + next_invalidation = now; + next_invalidation.tv_sec += ORIGINATOR_CACHE_TTL; + } + + update_tqs(); + update_ebtables(); + + next_update = now; + next_update.tv_sec += MIN_INTERVAL; + } + } + } + + cleanup(); + return 0; +} diff --git a/package/gluon-radv-filterd/src/mac.h b/package/gluon-radv-filterd/src/mac.h new file mode 100644 index 00000000..cc24d907 --- /dev/null +++ b/package/gluon-radv-filterd/src/mac.h @@ -0,0 +1,18 @@ +#include +#include + +#define F_MAC "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" +#define F_MAC_LEN 17 +#define F_MAC_VAR(var) \ + (var).ether_addr_octet[0], (var).ether_addr_octet[1], \ + (var).ether_addr_octet[2], (var).ether_addr_octet[3], \ + (var).ether_addr_octet[4], (var).ether_addr_octet[5] +#define F_MAC_VAR_REF(var) \ + &(var).ether_addr_octet[0], &(var).ether_addr_octet[1], \ + &(var).ether_addr_octet[2], &(var).ether_addr_octet[3], \ + &(var).ether_addr_octet[4], &(var).ether_addr_octet[5] +#define MAC2ETHER(_ether, _mac) memcpy((_ether).ether_addr_octet, \ + (_mac), ETH_ALEN) + +#define ether_addr_equal(_a, _b) (memcmp((_a).ether_addr_octet, \ + (_b).ether_addr_octet, ETH_ALEN) == 0) diff --git a/package/gluon-radv-filterd/src/respondd.c b/package/gluon-radv-filterd/src/respondd.c new file mode 100644 index 00000000..8c2c7eb4 --- /dev/null +++ b/package/gluon-radv-filterd/src/respondd.c @@ -0,0 +1,49 @@ +#include + +#include +#include +#include +#include + +#include "mac.h" + +static struct json_object * get_radv_filter() { + FILE *f = popen("exec ebtables-tiny -L RADV_FILTER", "r"); + char *line = NULL; + size_t len = 0; + struct ether_addr mac = {}; + struct ether_addr unspec = {}; + char macstr[F_MAC_LEN + 1] = ""; + + if (!f) + return NULL; + + while (getline(&line, &len, f) > 0) { + if (sscanf(line, "-s " F_MAC " -j ACCEPT\n", F_MAC_VAR_REF(mac)) == ETH_ALEN) + break; + } + free(line); + + pclose(f); + + memset(&unspec, 0, sizeof(unspec)); + if (ether_addr_equal(mac, unspec)) { + return NULL; + } else { + snprintf(macstr, sizeof(macstr), F_MAC, F_MAC_VAR(mac)); + return gluonutil_wrap_string(macstr); + } +} + +static struct json_object * respondd_provider_statistics() { + struct json_object *ret = json_object_new_object(); + + json_object_object_add(ret, "gateway6", get_radv_filter()); + + return ret; +} + +const struct respondd_provider_info respondd_providers[] = { + {"statistics", respondd_provider_statistics}, + {} +}; diff --git a/package/gluon-radvd/Makefile b/package/gluon-radvd/Makefile index 6695673c..a3957530 100644 --- a/package/gluon-radvd/Makefile +++ b/package/gluon-radvd/Makefile @@ -3,33 +3,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-radvd PKG_VERSION:=3 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-radvd - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Advertise an IPv6 prefix from the node - DEPENDS:=+gluon-core +gluon-ebtables +gluon-mesh-batman-adv +uradvd + DEPENDS:=+gluon-core +uradvd endef define Package/gluon-radvd/description Gluon community wifi mesh firmware framework: Advertise an IPv6 prefix from the node endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-radvd/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-radvd)) +$(eval $(call BuildPackageGluon,gluon-radvd)) diff --git a/package/gluon-radvd/files/etc/init.d/gluon-radvd b/package/gluon-radvd/files/etc/init.d/gluon-radvd index d7a981d4..d38b9441 100755 --- a/package/gluon-radvd/files/etc/init.d/gluon-radvd +++ b/package/gluon-radvd/files/etc/init.d/gluon-radvd @@ -1,15 +1,14 @@ #!/bin/sh /etc/rc.common +USE_PROCD=1 START=50 -SERVICE_WRITE_PID=1 -SERVICE_DAEMONIZE=1 +start_service() { + [ -x /lib/gluon/radvd/arguments ] || return 1 - -start() { - service_start /usr/sbin/uradvd -i br-client -p $(lua -e 'print(require("gluon.site_config").prefix6)') -} - -stop() { - service_stop /usr/sbin/uradvd + procd_open_instance + procd_set_param command /usr/sbin/uradvd $(/lib/gluon/radvd/arguments) + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + procd_set_param stderr 1 + procd_close_instance } diff --git a/package/gluon-radvd/files/lib/gluon/upgrade/500-radvd-remove-user b/package/gluon-radvd/luasrc/lib/gluon/upgrade/500-radvd-remove-user similarity index 100% rename from package/gluon-radvd/files/lib/gluon/upgrade/500-radvd-remove-user rename to package/gluon-radvd/luasrc/lib/gluon/upgrade/500-radvd-remove-user diff --git a/package/gluon-respondd/Makefile b/package/gluon-respondd/Makefile index df9f257e..52839a86 100644 --- a/package/gluon-respondd/Makefile +++ b/package/gluon-respondd/Makefile @@ -3,27 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-respondd PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-respondd - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Provides node information to the network - DEPENDS:=+gluon-core +libplatforminfo +libgluonutil +respondd + DEPENDS:=+gluon-core +libplatforminfo +libgluonutil +libuci +ubus +respondd endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/gluon-respondd/install - $(CP) ./files/* $(1)/ - - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/respondd.so -endef - -$(eval $(call BuildPackage,gluon-respondd)) +$(eval $(call BuildPackageGluon,gluon-respondd)) diff --git a/package/gluon-respondd/files/etc/hotplug.d/iface/10-gluon-respondd b/package/gluon-respondd/files/etc/hotplug.d/iface/10-gluon-respondd deleted file mode 100644 index 4f49be52..00000000 --- a/package/gluon-respondd/files/etc/hotplug.d/iface/10-gluon-respondd +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -. /usr/share/libubox/jshn.sh -. /lib/functions/service.sh - -DEVLIST=/var/run/gluon-respondd.devs - -ifname_to_dev () { - json_load "$(ubus call network.interface.$1 status)" - json_get_var dev device - - echo "$dev" -} - -case "$ACTION" in - ifdown) - sed "/ $INTERFACE$/d" $DEVLIST > $DEVLIST.new - mv $DEVLIST.new $DEVLIST - ;; - ifup) - DEVICE="$(ifname_to_dev "$INTERFACE")" - MESH="$(cat "/sys/class/net/$DEVICE/batman_adv/mesh_iface" 2>/dev/null)" - - [ "$MESH" = "bat0" -o "$INTERFACE" = "client" ] || exit 0 - - DEVS=$(cat $DEVLIST 2>/dev/null; echo $DEVICE $INTERFACE) - - echo "$DEVS" | sort -u > $DEVLIST.new - mv $DEVLIST.new $DEVLIST - - /etc/init.d/gluon-respondd restart_if_running & - - ;; -esac diff --git a/package/gluon-respondd/files/etc/init.d/gluon-respondd b/package/gluon-respondd/files/etc/init.d/gluon-respondd index a1bf979f..ca07fa90 100755 --- a/package/gluon-respondd/files/etc/init.d/gluon-respondd +++ b/package/gluon-respondd/files/etc/init.d/gluon-respondd @@ -1,45 +1,29 @@ #!/bin/sh /etc/rc.common -EXTRA_COMMANDS='restart_if_running' - +USE_PROCD=1 START=50 -SERVICE_WRITE_PID=1 -SERVICE_DAEMONIZE=1 - -DEVLIST=/var/run/gluon-respondd.devs DAEMON=/usr/bin/respondd -LOCK=/var/run/gluon-respondd.lock +MAXDELAY=10 +start_service() { + local ifdump="$(ubus call network.interface dump)" -do_start() { - DEVS=$(cat $DEVLIST 2>/dev/null | while read dev iface; do echo -n " -i $dev"; done) - service_start $DAEMON -g ff02::2:1001 -p 1001 -d /lib/gluon/respondd $DEVS + local meshdevs=$(for dev in $(echo "$ifdump" | jsonfilter -e "@.interface[@.proto='gluon_mesh' && @.up=true].device"); do echo " -i $dev";done;) + local clientdevs=$(for dev in $(echo "$ifdump" | jsonfilter -e "@.interface[@.interface='$(cat /lib/gluon/respondd/client.dev 2>/dev/null)' && @.up=true].device"); do echo " -i $dev -t $MAXDELAY";done;) + + procd_open_instance + procd_set_param command $DAEMON -d /usr/lib/respondd -p 1001 -g ff02::2:1001 $meshdevs $clientdevs -g ff05::2:1001 $clientdevs + procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5} + procd_set_param stderr 1 + procd_close_instance } -do_stop() { - service_stop $DAEMON -} - -start() { - lock $LOCK - do_start - lock -u $LOCK -} - -stop() { - lock $LOCK - do_stop - lock -u $LOCK -} - -restart_if_running() { - lock $LOCK - - if service_check $DAEMON; then - do_stop - do_start - fi - - lock -u $LOCK +service_triggers() { + local script=$(readlink "$initscript") + local name=$(basename ${script:-$initscript}) + + procd_open_trigger + procd_add_raw_trigger "interface.*" 0 "/etc/init.d/$name" reload + procd_close_trigger } diff --git a/package/gluon-respondd/files/lib/gluon/upgrade/400-respondd-firewall b/package/gluon-respondd/files/lib/gluon/upgrade/400-respondd-firewall deleted file mode 100755 index a78cfb3d..00000000 --- a/package/gluon-respondd/files/lib/gluon/upgrade/400-respondd-firewall +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/lua - -local uci = require('luci.model.uci').cursor() - -uci:delete('firewall', 'wan_announced') - --- Allow respondd port on WAN to allow resolving neighbours over mesh-on-wan -uci:section('firewall', 'rule', 'wan_respondd', - { - name = 'wan_respondd', - src = 'wan', - src_ip = 'fe80::/64', - dest_port = '1001', - proto = 'udp', - target = 'ACCEPT', - } -) - --- Restrict respondd queries to link-local addresses to prevent amplification attacks from outside -uci:section('firewall', 'rule', 'client_respondd', - { - name = 'client_respondd', - src = 'client', - src_ip = '!fe80::/64', - dest_port = '1001', - proto = 'udp', - target = 'REJECT', - } -) - -uci:save('firewall') diff --git a/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall b/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall new file mode 100755 index 00000000..506de289 --- /dev/null +++ b/package/gluon-respondd/luasrc/lib/gluon/upgrade/400-respondd-firewall @@ -0,0 +1,46 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() +local site = require('gluon.site') + +uci:delete('firewall', 'wan_announced') + +-- Allow respondd port on WAN to allow resolving neighbours over mesh-on-wan +uci:section('firewall', 'rule', 'wan_respondd', { + name = 'wan_respondd', + src = 'wan', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) + +-- Allow respondd-access for local clients +uci:section('firewall', 'rule', 'client_respondd', { + name = 'client_respondd', + src = 'local_client', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:section('firewall', 'rule', 'mesh_respondd_ll', { + name = 'mesh_respondd_ll', + src = 'mesh', + src_ip = 'fe80::/64', + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:section('firewall', 'rule', 'mesh_respondd_siteprefix', { + name = 'mesh_respondd_siteprefix', + src = 'mesh', + src_ip = site.prefix6(), + dest_port = '1001', + proto = 'udp', + target = 'ACCEPT', +}) + +uci:save('firewall') diff --git a/package/gluon-respondd/src/Makefile b/package/gluon-respondd/src/Makefile index eddbe260..f26b59a2 100644 --- a/package/gluon-respondd/src/Makefile +++ b/package/gluon-respondd/src/Makefile @@ -3,4 +3,4 @@ all: respondd.so CFLAGS += -Wall respondd.so: respondd.c - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -lplatforminfo + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -lplatforminfo -luci diff --git a/package/gluon-respondd/src/respondd.c b/package/gluon-respondd/src/respondd.c index be3c9a7a..0cdf5408 100644 --- a/package/gluon-respondd/src/respondd.c +++ b/package/gluon-respondd/src/respondd.c @@ -29,12 +29,14 @@ #include #include #include +#include #include #include #include +#include +#include -#include #include @@ -66,13 +68,36 @@ static struct json_object * get_site_code(void) { return ret; } +static struct json_object * get_domain_code(void) { + return gluonutil_wrap_and_free_string(gluonutil_get_domain()); +} + static struct json_object * get_hostname(void) { - struct utsname utsname; + struct json_object *ret = NULL; - if (uname(&utsname)) + struct uci_context *ctx = uci_alloc_context(); + if (!ctx) return NULL; + ctx->flags &= ~UCI_FLAG_STRICT; - return gluonutil_wrap_string(utsname.nodename); + char section[] = "system.@system[0]"; + struct uci_ptr ptr; + if (uci_lookup_ptr(ctx, &ptr, section, true)) + goto error; + + struct uci_section *s = ptr.s; + + const char *hostname = uci_lookup_option_string(ctx, s, "pretty_hostname"); + + if (!hostname) + hostname = uci_lookup_option_string(ctx, s, "hostname"); + + ret = gluonutil_wrap_string(hostname); + +error: + uci_free_context(ctx); + + return ret; } static struct json_object * respondd_provider_nodeinfo(void) { @@ -82,7 +107,11 @@ static struct json_object * respondd_provider_nodeinfo(void) { json_object_object_add(ret, "hostname", get_hostname()); struct json_object *hardware = json_object_new_object(); - json_object_object_add(hardware, "model", json_object_new_string(platforminfo_get_model())); + + const char *model = platforminfo_get_model(); + if (model) + json_object_object_add(hardware, "model", json_object_new_string(model)); + json_object_object_add(hardware, "nproc", json_object_new_int(sysconf(_SC_NPROCESSORS_ONLN))); json_object_object_add(ret, "hardware", hardware); @@ -99,6 +128,8 @@ static struct json_object * respondd_provider_nodeinfo(void) { struct json_object *system = json_object_new_object(); json_object_object_add(system, "site_code", get_site_code()); + if (gluonutil_has_domains()) + json_object_object_add(system, "domain_code", get_domain_code()); json_object_object_add(ret, "system", system); return ret; @@ -178,6 +209,82 @@ static struct json_object * get_memory(void) { return ret; } +static struct json_object * get_stat(void) { + FILE *f = fopen("/proc/stat", "r"); + if (!f) + return NULL; + + struct json_object *stat = json_object_new_object(); + struct json_object *ret = NULL; + + char *line = NULL; + size_t len = 0; + + while (getline(&line, &len, f) >= 0) { + char label[32]; + + if (sscanf(line, "%31s", label) != 1){ + goto invalid_stat_format; + } + + if (!strcmp(label, "cpu")) { + unsigned long long user, nice, system, idle, iowait, irq, softirq; + if (sscanf(line, "%*s %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64" %"SCNu64, + &user, &nice, &system, &idle, &iowait, &irq, &softirq) != 7) + goto invalid_stat_format; + + struct json_object *cpu = json_object_new_object(); + + json_object_object_add(cpu, "user", json_object_new_int64(user)); + json_object_object_add(cpu, "nice", json_object_new_int64(nice)); + json_object_object_add(cpu, "system", json_object_new_int64(system)); + json_object_object_add(cpu, "idle", json_object_new_int64(idle)); + json_object_object_add(cpu, "iowait", json_object_new_int64(iowait)); + json_object_object_add(cpu, "irq", json_object_new_int64(irq)); + json_object_object_add(cpu, "softirq", json_object_new_int64(softirq)); + + json_object_object_add(stat, "cpu", cpu); + } else if (!strcmp(label, "ctxt")) { + unsigned long long ctxt; + if (sscanf(line, "%*s %"SCNu64, &ctxt) != 1) + goto invalid_stat_format; + + json_object_object_add(stat, "ctxt", json_object_new_int64(ctxt)); + } else if (!strcmp(label, "intr")) { + unsigned long long total_intr; + if (sscanf(line, "%*s %"SCNu64, &total_intr) != 1) + goto invalid_stat_format; + + json_object_object_add(stat, "intr", json_object_new_int64(total_intr)); + } else if (!strcmp(label, "softirq")) { + unsigned long long total_softirq; + if (sscanf(line, "%*s %"SCNu64, &total_softirq) != 1) + goto invalid_stat_format; + + json_object_object_add(stat, "softirq", json_object_new_int64(total_softirq)); + } else if (!strcmp(label, "processes")) { + unsigned long long processes; + if (sscanf(line, "%*s %"SCNu64, &processes) != 1) + goto invalid_stat_format; + + json_object_object_add(stat, "processes", json_object_new_int64(processes)); + } + + } + + ret = stat; + +invalid_stat_format: + if (!ret) + json_object_put(stat); + + free(line); + fclose(f); + + return ret; +} + + static struct json_object * get_rootfs_usage(void) { struct statfs s; if (statfs("/", &s)) @@ -188,13 +295,27 @@ static struct json_object * get_rootfs_usage(void) { return jso; } +static struct json_object * get_time(void) { + struct timespec now; + + if (clock_gettime(CLOCK_REALTIME, &now) != 0) + return NULL; + + return json_object_new_int64(now.tv_sec); +} + static struct json_object * respondd_provider_statistics(void) { struct json_object *ret = json_object_new_object(); json_object_object_add(ret, "node_id", gluonutil_wrap_and_free_string(gluonutil_get_node_id())); + json_object *time = get_time(); + if (time != NULL) + json_object_object_add(ret, "time", time); + json_object_object_add(ret, "rootfs_usage", get_rootfs_usage()); json_object_object_add(ret, "memory", get_memory()); + json_object_object_add(ret, "stat", get_stat()); add_uptime(ret); add_loadavg(ret); diff --git a/package/gluon-setup-mode/Makefile b/package/gluon-setup-mode/Makefile index 55370abe..ff1c730b 100644 --- a/package/gluon-setup-mode/Makefile +++ b/package/gluon-setup-mode/Makefile @@ -6,39 +6,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-setup-mode PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(GLUONDIR)/include/package.mk +include ../gluon.mk define Package/gluon-setup-mode - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Setup mode - DEPENDS:=+gluon-core +uhttpd +dnsmasq - PROVIDES:=gluon-setup-mode-virtual + DEPENDS:=+gluon-core +gluon-lock-password +ubus +dnsmasq endef define Package/gluon-setup-mode/description Offline mode to perform basic setup in a secure manner. endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-setup-mode/install - $(CP) ./files/* $(1)/ -endef - -define Package/gluon-setup-mode/postinst -#!/bin/sh -$(call GluonCheckSite,check_site.lua) -endef - -$(eval $(call BuildPackage,gluon-setup-mode)) +$(eval $(call BuildPackageGluon,gluon-setup-mode)) diff --git a/package/gluon-setup-mode/check_site.lua b/package/gluon-setup-mode/check_site.lua index 07baaad3..b07b103f 100644 --- a/package/gluon-setup-mode/check_site.lua +++ b/package/gluon-setup-mode/check_site.lua @@ -1,2 +1 @@ -need_boolean('setup_mode.skip', false) - +need_boolean(in_site({'setup_mode', 'skip'}), false) diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/K50dropbear b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/K50dropbear deleted file mode 120000 index 066549b3..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/K50dropbear +++ /dev/null @@ -1 +0,0 @@ -/etc/init.d/dropbear \ No newline at end of file diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S13haveged b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S13haveged index b4af677a..27b1a595 100755 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S13haveged +++ b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S13haveged @@ -1,5 +1,5 @@ #!/bin/sh /etc/rc.common -if /etc/init.d/haveged enabled; then +if [ -x /etc/init.d/haveged ] && /etc/init.d/haveged enabled; then . /etc/init.d/haveged fi diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode index df8a0e2b..80127cc4 100755 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode +++ b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S15gluon-setup-mode @@ -10,9 +10,7 @@ boot() { uci set 'gluon-setup-mode.@setup_mode[0].enabled=0' uci commit gluon-setup-mode - if [ "$enabled" = 1 -o "$configured" != 1 ]; then - lua -e 'uci_state=require("luci.model.uci").cursor_state(); uci_state:section("gluon-setup-mode", "setup_mode", nil, { running = "1" }); uci_state:save("gluon-setup-mode")' - else + if [ "$enabled" != 1 -a "$configured" = 1 ]; then # This can happen after an upgrade from a version before the config file was called gluon-setup-mode # We'll just reboot to return to the normal mode... /etc/init.d/done boot diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S20network b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S20network index ef4cc4ad..19ba6221 100755 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S20network +++ b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S20network @@ -46,7 +46,7 @@ init_switch() { start_service() { prepare_config init_switch - iw reg set "$(lua -e 'print(require("gluon.site_config").regdom)')" + iw reg set "$(lua -e 'print(require("gluon.site").regdom())')" procd_open_instance procd_set_param command /sbin/netifd -c /var/gluon/setup-mode/config diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear deleted file mode 120000 index 066549b3..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear +++ /dev/null @@ -1 +0,0 @@ -/etc/init.d/dropbear \ No newline at end of file diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear new file mode 100755 index 00000000..590aede3 --- /dev/null +++ b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50dropbear @@ -0,0 +1,21 @@ +#!/bin/sh /etc/rc.common + +USE_PROCD=1 +PROG=/usr/sbin/dropbear +NAME=dropbear + +start_service() { + [ -x /etc/init.d/dropbear ] || return 0 + + . /etc/init.d/dropbear + + [ -s /etc/dropbear/dropbear_rsa_host_key ] || keygen + + . /lib/functions.sh + . /lib/functions/network.sh + + procd_open_instance + procd_set_param command "$PROG" -F -f + procd_set_param respawn + procd_close_instance +} diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50telnet b/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50telnet deleted file mode 100755 index b524b2ce..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/rc.d/S50telnet +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh /etc/rc.common - -START=50 - -USE_PROCD=1 -PROG=/usr/sbin/telnetd - -start_service() { - procd_open_instance - procd_set_param command "$PROG" -F -l /lib/gluon/setup-mode/ash-login - procd_close_instance -} diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/cgi-bin/luci b/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/cgi-bin/luci deleted file mode 100755 index c5c98473..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/cgi-bin/luci +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/lua -require "luci.cacheloader" -require "luci.sgi.cgi" -luci.dispatcher.indexcache = "/tmp/luci-indexcache" -luci.sgi.cgi.run() diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/index.html b/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/index.html deleted file mode 100644 index 0a7238b5..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - -LuCI - Lua Configuration Interface - - diff --git a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/luci-static b/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/luci-static deleted file mode 120000 index aea80e05..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/setup-mode/www/luci-static +++ /dev/null @@ -1 +0,0 @@ -/www/luci-static \ No newline at end of file diff --git a/package/gluon-setup-mode/files/lib/gluon/upgrade/300-setup-mode b/package/gluon-setup-mode/files/lib/gluon/upgrade/300-setup-mode deleted file mode 100755 index 481a4fa0..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/upgrade/300-setup-mode +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -local c = uci.cursor() - -if site.setup_mode - and site.setup_mode.skip - and not c:get_first('gluon-setup-mode', 'setup_mode', 'configured', false) then - local name = c:get_first("gluon-setup-mode", "setup_mode") - c:set("gluon-setup-mode", name, "configured", 1) - c:save('gluon-setup-mode') -end - diff --git a/package/gluon-setup-mode/files/lib/gluon/upgrade/310-setup-mode-migrate b/package/gluon-setup-mode/files/lib/gluon/upgrade/310-setup-mode-migrate deleted file mode 100755 index 3b5165c4..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/upgrade/310-setup-mode-migrate +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/lua - -local site = require 'gluon.site_config' -local uci = require 'luci.model.uci' - -local c = uci.cursor() - - -local old = c:get_first('gluon-config-mode', 'wizard', 'configured') -if old == '1' then - local setup_mode = c:get_first('gluon-setup-mode', 'setup_mode') - c:set('gluon-setup-mode', setup_mode, 'configured', '1') - - c:save('gluon-setup-mode') -end - -os.remove('/etc/config/gluon-config-mode') diff --git a/package/gluon-setup-mode/files/lib/gluon/upgrade/320-setup-ifname b/package/gluon-setup-mode/files/lib/gluon/upgrade/320-setup-ifname deleted file mode 100755 index a2b4f796..00000000 --- a/package/gluon-setup-mode/files/lib/gluon/upgrade/320-setup-ifname +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/lua - -local platform = require 'gluon.platform' -local sysconfig = require 'gluon.sysconfig' - - -if sysconfig.setup_ifname then - os.exit(0) -end - -if platform.match('ar71xx', 'generic', {'cpe510', 'nanostation-m', 'nanostation-m-xw', 'unifi-outdoor-plus', 'uap-pro', 'unifiac-pro'}) then - sysconfig.setup_ifname = sysconfig.config_ifname or sysconfig.wan_ifname or sysconfig.lan_ifname -else - sysconfig.setup_ifname = sysconfig.config_ifname or sysconfig.lan_ifname or sysconfig.wan_ifname -end - --- Remove the old sysconfig setting -sysconfig.config_ifname = nil diff --git a/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/300-setup-mode b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/300-setup-mode new file mode 100755 index 00000000..0456a087 --- /dev/null +++ b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/300-setup-mode @@ -0,0 +1,11 @@ +#!/usr/bin/lua + +local site = require 'gluon.site' +local uci = require('simple-uci').cursor() + + +if site.setup_mode.skip(false) and not uci:get_first('gluon-setup-mode', 'setup_mode', 'configured', false) then + local name = uci:get_first("gluon-setup-mode", "setup_mode") + uci:set("gluon-setup-mode", name, "configured", true) + uci:save('gluon-setup-mode') +end diff --git a/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/310-setup-mode-migrate b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/310-setup-mode-migrate new file mode 100755 index 00000000..ecaa07f9 --- /dev/null +++ b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/310-setup-mode-migrate @@ -0,0 +1,14 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + + +local old = uci:get_first('gluon-config-mode', 'wizard', 'configured') +if old == '1' then + local setup_mode = uci:get_first('gluon-setup-mode', 'setup_mode') + uci:set('gluon-setup-mode', setup_mode, 'configured', true) + + uci:save('gluon-setup-mode') +end + +os.remove('/etc/config/gluon-config-mode') diff --git a/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname new file mode 100755 index 00000000..7f0ca7b8 --- /dev/null +++ b/package/gluon-setup-mode/luasrc/lib/gluon/upgrade/320-setup-ifname @@ -0,0 +1,29 @@ +#!/usr/bin/lua + +local platform = require 'gluon.platform' +local sysconfig = require 'gluon.sysconfig' + + +if sysconfig.setup_ifname then + os.exit(0) +end + +if platform.match('ar71xx', 'generic', { + 'cpe210', + 'cpe510', + 'wbs210', + 'wbs510', + 'airgateway', + 'nanostation-m', + 'nanostation-m-xw', + 'unifi-outdoor-plus', + 'uap-pro', + 'unifiac-pro' +}) or platform.match('ar71xx', 'mikrotik') then + sysconfig.setup_ifname = sysconfig.config_ifname or sysconfig.wan_ifname or sysconfig.lan_ifname +else + sysconfig.setup_ifname = sysconfig.config_ifname or sysconfig.lan_ifname or sysconfig.wan_ifname +end + +-- Remove the old sysconfig setting +sysconfig.config_ifname = nil diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index a7084ad0..91452264 100644 --- a/package/gluon-site/Makefile +++ b/package/gluon-site/Makefile @@ -1,42 +1,76 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-site -PKG_VERSION:=$(if $(GLUON_SITE_CODE),$(GLUON_SITE_CODE),1) -PKG_RELEASE:=$(GLUON_RELEASE) -PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/site.conf $(GLUON_SITEDIR)/i18n/ -PKG_BUILD_DEPENDS := luci-base/host lua-cjson/host +GLUON_SITEDIR = $(call qstrip,$(CONFIG_GLUON_SITEDIR)) +GLUON_SITE_VERSION = $(shell ( cd '$(GLUON_SITEDIR)' && git --git-dir=.git describe --always --dirty=+ ) 2>/dev/null || echo unknown) +PKG_VERSION:=$(if $(DUMP),x,$(GLUON_SITE_VERSION)) + +PKG_CONFIG_DEPENDS := CONFIG_GLUON_RELEASE CONFIG_GLUON_SITEDIR CONFIG_GLUON_MULTIDOMAIN +PKG_FILE_DEPENDS := $(GLUON_SITEDIR)/site.conf $(GLUON_SITEDIR)/domains/ $(GLUON_SITEDIR)/i18n/ +PKG_BUILD_DEPENDS := lua-cjson/host PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) -include $(GLUONDIR)/include/package.mk +include ../gluon.mk PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) - define Package/gluon-site - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Site-specific files of Gluon endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) +define Package/gluon-site/config +config GLUON_RELEASE + string "Gluon release number" + depends on PACKAGE_gluon-site + default "" + +config GLUON_SITEDIR + string "Gluon site configuration directory" + depends on PACKAGE_gluon-site + default "" + +config GLUON_MULTIDOMAIN + bool "Gluon multi-domain support" + endef -define Build/Configure +define GenerateJSON + GLUON_SITEDIR='$$(GLUON_SITEDIR)' GLUON_SITE_CONFIG='$(1).conf' lua -e 'print(require("cjson").encode(assert(dofile("../../scripts/site_config.lua"))))' > '$$(PKG_BUILD_DIR)/$(1).json' endef define Build/Compile - $(call GluonBuildI18N,gluon-site,$(GLUON_SITEDIR)/i18n) + $(call GenerateJSON,site) + + ifdef CONFIG_GLUON_MULTIDOMAIN + rm -rf $(PKG_BUILD_DIR)/domains + mkdir -p $(PKG_BUILD_DIR)/domains + $(foreach domain,$(patsubst $(GLUON_SITEDIR)/domains/%.conf,%,$(wildcard $(GLUON_SITEDIR)/domains/*.conf)), + [ ! -e '$(PKG_BUILD_DIR)/domains/$(domain).json' ] + $(call GenerateJSON,domains/$(domain)) + lua ../../scripts/domain_aliases.lua '$(PKG_BUILD_DIR)/domains/$(domain).json' | while read alias; do \ + [ "$$$${alias}" != '$(domain)' ] || continue; \ + ln -s '$(domain).json' $(PKG_BUILD_DIR)/domains/$$$${alias}.json || exit 1; \ + done + ) + endif + + $(call GluonBuildI18N,$(GLUON_SITEDIR)/i18n) endef define Package/gluon-site/install $(INSTALL_DIR) $(1)/lib/gluon - lua -e 'print(require("cjson").encode(assert(dofile("$(GLUONDIR)/scripts/site_config.lua"))))' > $(1)/lib/gluon/site.json - echo "$(GLUON_RELEASE)" > $(1)/lib/gluon/release - $(call GluonInstallI18N,gluon-site,$(1)) + $(INSTALL_DATA) $(PKG_BUILD_DIR)/site.json $(1)/lib/gluon/ + ifdef CONFIG_GLUON_MULTIDOMAIN + $(CP) $(PKG_BUILD_DIR)/domains $(1)/lib/gluon/ + endif + + echo '$(GLUON_SITE_VERSION)' > $(1)/lib/gluon/site-version + echo '$(call qstrip,$(CONFIG_GLUON_RELEASE))' > $(1)/lib/gluon/release + + $(GluonInstallI18N) endef -$(eval $(call BuildPackage,gluon-site)) +$(eval $(call BuildPackageGluon,gluon-site)) diff --git a/package/gluon-status-page-api/Makefile b/package/gluon-status-page-api/Makefile deleted file mode 100644 index 174e2e85..00000000 --- a/package/gluon-status-page-api/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -include $(TOPDIR)/rules.mk - -PKG_NAME:=gluon-status-page-api -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS := respondd - -include $(INCLUDE_DIR)/package.mk - -define Package/gluon-status-page-api - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=API for gluon-status-page - DEPENDS:=+gluon-core +uhttpd +sse-multiplex +gluon-neighbour-info +gluon-respondd +libiwinfo +libjson-c -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Package/gluon-status-page-api/install - $(INSTALL_DIR) $(1)/lib/gluon/status-page/providers - $(INSTALL_BIN) $(PKG_BUILD_DIR)/neighbours-batadv $(1)/lib/gluon/status-page/providers/ - $(INSTALL_BIN) $(PKG_BUILD_DIR)/stations $(1)/lib/gluon/status-page/providers/ - - $(INSTALL_DIR) $(1)/lib/gluon/respondd - $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/lib/gluon/respondd/status-page-api.so - - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-status-page-api)) diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo deleted file mode 100755 index 657f17e5..00000000 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -badrequest() { - echo 'Status: 400 Bad Request' - echo - exit 1 -} - -echo 'Access-Control-Allow-Origin: *' - -batctl if | cut -d: -f1 | grep -qxF "$QUERY_STRING" || badrequest - -exec /usr/bin/gluon-neighbour-info -s neighbour -i "$QUERY_STRING" -d ff02::2:1001 -p 1001 -r nodeinfo diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/interfaces b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/interfaces deleted file mode 100755 index 4eabf815..00000000 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/interfaces +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/lua - -util = require 'luci.util' -json = require 'luci.jsonc' -fs = require 'nixio.fs' - -io.write("Access-Control-Allow-Origin: *\n") -io.write("Content-type: application/json\n\n") - -list = util.exec('batctl if') - -interfaces = {} - -for _, line in ipairs(util.split(list)) do - ifname = line:match('^(.-):') - if ifname ~= nil then - pcall(function() - local address = util.trim(fs.readfile('/sys/class/net/' .. ifname .. '/address')) - interfaces[ifname] = { address = address } - end) - end -end - -io.write(json.stringify(interfaces)) diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/nodeinfo b/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/nodeinfo deleted file mode 100755 index d34381fa..00000000 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/nodeinfo +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh - -cat < -#include -#include -#include -#include - -#define STR(x) #x -#define XSTR(x) STR(x) - -static json_object *neighbours(void) { - struct json_object *obj = json_object_new_object(); - - FILE *f; - - f = fopen("/sys/kernel/debug/batman_adv/bat0/originators" , "r"); - - if (f == NULL) - return NULL; - - while (!feof(f)) { - char mac1[18]; - char mac2[18]; - char ifname[IF_NAMESIZE+1]; - int tq; - double lastseen; - - int count = fscanf(f, "%17s%*[\t ]%lfs%*[\t (]%d) %17s%*[[ ]%" XSTR(IF_NAMESIZE) "[^]]]", mac1, &lastseen, &tq, mac2, ifname); - - if (count != 5) - continue; - - if (strcmp(mac1, mac2) == 0) { - struct json_object *neigh = json_object_new_object(); - - json_object_object_add(neigh, "tq", json_object_new_int(tq)); - json_object_object_add(neigh, "lastseen", json_object_new_double(lastseen)); - json_object_object_add(neigh, "ifname", json_object_new_string(ifname)); - - json_object_object_add(obj, mac1, neigh); - } - } - - fclose(f); - - return obj; -} - -int main(void) { - struct json_object *obj; - - printf("Content-type: text/event-stream\n\n"); - fflush(stdout); - - while (1) { - obj = neighbours(); - if (obj) { - printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)); - fflush(stdout); - json_object_put(obj); - } - sleep(10); - } - - return 0; -} diff --git a/package/gluon-status-page-api/src/respondd.c b/package/gluon-status-page-api/src/respondd.c deleted file mode 100644 index f6a0e51e..00000000 --- a/package/gluon-status-page-api/src/respondd.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - Copyright (c) 2016, Matthias Schiffer - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - -#include - -#include - - -static struct json_object * respondd_provider_nodeinfo(void) { - struct json_object *ret = json_object_new_object(); - - struct json_object *software = json_object_new_object(); - struct json_object *software_status_page = json_object_new_object(); - json_object_object_add(software_status_page, "api", json_object_new_int(1)); - json_object_object_add(software, "status-page", software_status_page); - json_object_object_add(ret, "software", software); - - return ret; -} - -const struct respondd_provider_info respondd_providers[] = { - {"nodeinfo", respondd_provider_nodeinfo}, - {} -}; diff --git a/package/gluon-status-page-mesh-batman-adv/Makefile b/package/gluon-status-page-mesh-batman-adv/Makefile new file mode 100644 index 00000000..4d2ed8f0 --- /dev/null +++ b/package/gluon-status-page-mesh-batman-adv/Makefile @@ -0,0 +1,20 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-status-page-mesh-batman-adv +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-status-page-mesh-batman-adv + TITLE:=Batman-data provider for gluon-status-page + DEPENDS:=+gluon-status-page gluon-mesh-batman-adv +libnl-tiny +libbatadv +libjson-c +endef + +define Package/gluon-status-page-mesh-batman-adv/install + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/lib/gluon/status-page/providers + $(INSTALL_BIN) $(PKG_BUILD_DIR)/neighbours-batadv $(1)/lib/gluon/status-page/providers/ +endef + +$(eval $(call BuildPackageGluon,gluon-status-page-mesh-batman-adv)) diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv b/package/gluon-status-page-mesh-batman-adv/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv similarity index 73% rename from package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv rename to package/gluon-status-page-mesh-batman-adv/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv index 075e8b8b..abd99032 100755 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv +++ b/package/gluon-status-page-mesh-batman-adv/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-batadv @@ -1,7 +1,5 @@ #!/bin/sh -echo 'Access-Control-Allow-Origin: *' - CMD='exec /lib/gluon/status-page/providers/neighbours-batadv' exec /usr/sbin/sse-multiplex "$CMD" diff --git a/package/gluon-status-page-mesh-batman-adv/luasrc/lib/gluon/status-page/mesh.lua b/package/gluon-status-page-mesh-batman-adv/luasrc/lib/gluon/status-page/mesh.lua new file mode 100644 index 00000000..733e6d7c --- /dev/null +++ b/package/gluon-status-page-mesh-batman-adv/luasrc/lib/gluon/status-page/mesh.lua @@ -0,0 +1,10 @@ +return { + provider = '/cgi-bin/dyn/neighbours-batadv', + -- List of mesh-specific attributes, each a tuple of + -- 1) the internal identifier (JSON key) + -- 2) human-readable key (not translatable yet) + -- 3) value suffix (optional) + attrs = { + {'tq', 'TQ', ' %'}, + }, +} diff --git a/package/gluon-status-page-mesh-batman-adv/src/Makefile b/package/gluon-status-page-mesh-batman-adv/src/Makefile new file mode 100644 index 00000000..5fb4ef4f --- /dev/null +++ b/package/gluon-status-page-mesh-batman-adv/src/Makefile @@ -0,0 +1,40 @@ +all: neighbours-batadv + +CFLAGS += -Wall -D_GNU_SOURCE + +ifeq ($(origin PKG_CONFIG), undefined) + PKG_CONFIG = pkg-config + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif +endif + +ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined) + LIBNL_NAME ?= libnl-tiny + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),) + $(error No $(LIBNL_NAME) development libraries found!) + endif + LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME)) + LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME)) +endif +CFLAGS += $(LIBNL_CFLAGS) +LDLIBS += $(LIBNL_LDLIBS) + +CFLAGS_JSONC = $(shell pkg-config --cflags json-c) +LDFLAGS_JSONC = $(shell pkg-config --libs json-c) + + +ifeq ($(origin LIBBATADV_CFLAGS) $(origin LIBBATADV_LDLIBS), undefined undefined) + LIBBATADV_NAME ?= libbatadv + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBBATADV_NAME) 2>/dev/null),) + $(error No $(LIBBATADV_NAME) development libraries found!) + endif + LIBBATADV_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBBATADV_NAME)) + LIBBATADV_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBBATADV_NAME)) +endif +CFLAGS += $(LIBBATADV_CFLAGS) +LDLIBS += $(LIBBATADV_LDLIBS) + +neighbours-batadv: neighbours-batadv.c + $(CC) $(CFLAGS) $(CFLAGS_JSONC) $(LDFLAGS) $(LDFLAGS_JSONC) -o $@ $^ $(LDLIBS) + diff --git a/package/gluon-status-page-mesh-batman-adv/src/neighbours-batadv.c b/package/gluon-status-page-mesh-batman-adv/src/neighbours-batadv.c new file mode 100644 index 00000000..b923d7f1 --- /dev/null +++ b/package/gluon-status-page-mesh-batman-adv/src/neighbours-batadv.c @@ -0,0 +1,127 @@ +#include +#include +#include +#include +#include + +#include + +#define STR(x) #x +#define XSTR(x) STR(x) + +struct neigh_netlink_opts { + struct json_object *obj; + struct batadv_nlquery_opts query_opts; +}; + +static const enum batadv_nl_attrs parse_orig_list_mandatory[] = { + BATADV_ATTR_ORIG_ADDRESS, + BATADV_ATTR_NEIGH_ADDRESS, + BATADV_ATTR_TQ, + BATADV_ATTR_HARD_IFINDEX, + BATADV_ATTR_LAST_SEEN_MSECS, +}; + +static int parse_orig_list_netlink_cb(struct nl_msg *msg, void *arg) +{ + struct nlattr *attrs[BATADV_ATTR_MAX+1]; + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct batadv_nlquery_opts *query_opts = arg; + struct genlmsghdr *ghdr; + uint8_t *orig; + uint8_t *dest; + uint8_t tq; + uint32_t hardif; + char ifname_buf[IF_NAMESIZE], *ifname; + struct neigh_netlink_opts *opts; + char mac1[18]; + + opts = batadv_container_of(query_opts, struct neigh_netlink_opts, query_opts); + + if (!genlmsg_valid_hdr(nlh, 0)) + return NL_OK; + + ghdr = nlmsg_data(nlh); + + if (ghdr->cmd != BATADV_CMD_GET_ORIGINATORS) + return NL_OK; + + if (nla_parse(attrs, BATADV_ATTR_MAX, genlmsg_attrdata(ghdr, 0), + genlmsg_len(ghdr), batadv_genl_policy)) + return NL_OK; + + if (batadv_genl_missing_attrs(attrs, parse_orig_list_mandatory, + BATADV_ARRAY_SIZE(parse_orig_list_mandatory))) + return NL_OK; + + if (!attrs[BATADV_ATTR_FLAG_BEST]) + return NL_OK; + + orig = nla_data(attrs[BATADV_ATTR_ORIG_ADDRESS]); + dest = nla_data(attrs[BATADV_ATTR_NEIGH_ADDRESS]); + tq = nla_get_u8(attrs[BATADV_ATTR_TQ]); + hardif = nla_get_u32(attrs[BATADV_ATTR_HARD_IFINDEX]); + + if (memcmp(orig, dest, 6) != 0) + return NL_OK; + + ifname = if_indextoname(hardif, ifname_buf); + if (!ifname) + return NL_OK; + + sprintf(mac1, "%02x:%02x:%02x:%02x:%02x:%02x", + orig[0], orig[1], orig[2], orig[3], orig[4], orig[5]); + + struct json_object *neigh = json_object_new_object(); + if (!neigh) + return NL_OK; + + json_object_object_add(neigh, "tq", json_object_new_int(tq * 100 / 255)); + json_object_object_add(neigh, "ifname", json_object_new_string(ifname)); + + json_object_object_add(opts->obj, mac1, neigh); + + return NL_OK; +} + +static json_object *neighbours(void) { + struct neigh_netlink_opts opts = { + .query_opts = { + .err = 0, + }, + }; + int ret; + + opts.obj = json_object_new_object(); + if (!opts.obj) + return NULL; + + ret = batadv_genl_query("bat0", BATADV_CMD_GET_ORIGINATORS, + parse_orig_list_netlink_cb, NLM_F_DUMP, + &opts.query_opts); + if (ret < 0) { + json_object_put(opts.obj); + return NULL; + } + + return opts.obj; +} + +int main(void) { + struct json_object *obj; + + printf("Content-type: text/event-stream\n\n"); + fflush(stdout); + + while (1) { + obj = neighbours(); + if (obj) { + printf("data: %s\n\n", json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN)); + fflush(stdout); + json_object_put(obj); + } + sleep(10); + } + + return 0; +} diff --git a/package/gluon-status-page/Makefile b/package/gluon-status-page/Makefile index 460764d0..923f68c7 100644 --- a/package/gluon-status-page/Makefile +++ b/package/gluon-status-page/Makefile @@ -1,67 +1,24 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-status-page -PKG_VERSION:=2 -PKG_RELEASE:=1 +PKG_VERSION:=3 -PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME) -PKG_BUILD_DEPENDS:=node/host - -include $(INCLUDE_DIR)/package.mk - -define Download/rjs - FILE:=r.js - URL:=http://requirejs.org/docs/release/2.1.10 - MD5SUM:=270154b3f5d417c3a42f1e58d03e6607 -endef - -define Download/Bacon - FILE:=Bacon.js - URL:=http://cdnjs.cloudflare.com/ajax/libs/bacon.js/0.7.71 - MD5SUM:=4600a60e1d7ffdb2259dfcce97c860ed -endef - -define Download/almond - FILE:=almond.js - URL:=https://raw.githubusercontent.com/jrburke/almond/0.3.1 - MD5SUM:=aa66c0c0cb55a4627bb706df73f3aff5 -endef - -$(eval $(call Download,rjs)) -$(eval $(call Download,Bacon)) -$(eval $(call Download,almond)) +include ../gluon.mk define Package/gluon-status-page - SECTION:=gluon - CATEGORY:=Gluon - TITLE:=Adds a status page showing information about the node. - DEPENDS:=+gluon-status-page-api -endef - -define Package/gluon-status-page/description - Adds a status page showing information about the node. - Especially useful in combination with the next-node feature. -endef - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) -t $(PKG_BUILD_DIR) $(DL_DIR)/r.js $(DL_DIR)/Bacon.js $(DL_DIR)/almond.js -endef - -define Build/Configure - $(CP) ./src/* $(PKG_BUILD_DIR)/ -endef - -define Build/Compile - cd $(PKG_BUILD_DIR) && \ - node r.js -o build.js && \ - node r.js -o cssIn=css/main.css out=style.css && \ - $(M4) index.html.m4 > index.html + TITLE:=Status page showing information about the node + DEPENDS:=+gluon-web +gluon-neighbour-info +gluon-respondd +uhttpd +sse-multiplex +libiwinfo +libjson-c +libnl-tiny +libubus-lua endef define Package/gluon-status-page/install - $(INSTALL_DIR) $(1)/lib/gluon/status-page/www/ - $(INSTALL_DATA) $(PKG_BUILD_DIR)/index.html $(1)/lib/gluon/status-page/www/ + $(Gluon/Build/Install) + + $(INSTALL_DIR) $(1)/lib/gluon/status-page/providers + $(INSTALL_BIN) $(PKG_BUILD_DIR)/stations $(1)/lib/gluon/status-page/providers/ + + $(INSTALL_DIR) $(1)/lib/gluon/status-page/view/ + $(LN) /lib/gluon/web/i18n $(1)/lib/gluon/status-page/ + $(LN) /lib/gluon/web/view/error $(1)/lib/gluon/status-page/view/ endef -$(eval $(call BuildPackage,gluon-status-page)) +$(eval $(call BuildPackageGluon,gluon-status-page)) diff --git a/package/gluon-status-page/files/lib/gluon/status-page/view/layout.html b/package/gluon-status-page/files/lib/gluon/status-page/view/layout.html new file mode 100644 index 00000000..11969ddc --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/view/layout.html @@ -0,0 +1,24 @@ +<%- + http:prepare_content("application/xhtml+xml") +-%> + + + + + + + <%:Error%> + + + + +
+

<%:Error%>

+
+
+
+ <% renderer.render(content, scope, pkg) %> +
+
+ + diff --git a/package/gluon-status-page/files/lib/gluon/status-page/view/status-page.html b/package/gluon-status-page/files/lib/gluon/status-page/view/status-page.html new file mode 100644 index 00000000..bf55eab6 --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/view/status-page.html @@ -0,0 +1,178 @@ +<%- + local fs = require 'nixio.fs' + local ubus = require 'ubus' + local util = require 'gluon.util' + + local translations = {} + + local function _(v) + translations[v] = translate(v) + end + + -- i18n strings for JavaScript + _('.') -- decimal point + _('connected') + _('not connected') + _('1 day') + _('%s days') + _('%s used') + _('%s packets/s') + + local function get_mesh() + local f = loadfile('/lib/gluon/status-page/mesh.lua') + if f then + return f() + end + return {} + end + + local mesh = get_mesh() + + local function get_interfaces() + local uconn = ubus.connect() + if not uconn then + error('failed to connect to ubus') + end + local interfaces = util.get_mesh_devices(uconn) + ubus.close(uconn) + table.sort(interfaces) + return interfaces + end + + local function is_wireless(iface) + while true do + local pattern = '/sys/class/net/' .. iface .. '/lower_*' + local lower = fs.glob(pattern)() + if not lower then break end + + iface = lower:sub(pattern:len()) + end + + return fs.access('/sys/class/net/' .. iface .. '/wireless') ~= nil + end + + local interfaces = get_interfaces() + + local function sorted(t) + t = {unpack(t)} + table.sort(t) + return t + end + + local function enabled(v) + return v and translate('enabled') or translate('disabled') + end + + local function statistics(key, format) + return string.format('', pcdata(key), pcdata(format or 'id')) + end + + local function statisticsTraffic(key) + return string.format('%s
%s
%s', + statistics(key .. '/packets', 'packetsDiff'), + statistics(key .. '/bytes', 'bytesDiff'), + statistics(key .. '/bytes', 'bytes') + ) + end + + http:prepare_content("application/xhtml+xml") +-%> + + + + + + + <%| nodeinfo.hostname %> - <%:Status%> + + + + > +
+

<%| nodeinfo.hostname %>

+
+
+
+

<%:Overview%>

+
+
<%:Node name%>
<%| nodeinfo.hostname %>
+ <% if nodeinfo.owner and nodeinfo.owner.contact then -%> +
<%:Contact%>
<%| nodeinfo.owner.contact %>
+ <%- end %> +
<%:Model%>
<%| nodeinfo.hardware.model %>
+
<%:Primary MAC address%>
<%| nodeinfo.network.mac %>
+
<%:IP address%>
<%= pcdata(table.concat(sorted(nodeinfo.network.addresses), '\n')):gsub('\n', '
') %>
+
<%:Firmware%>
<%| nodeinfo.software.firmware.release %>
+ <% if nodeinfo.software.fastd then -%> +
<%:Mesh VPN%>
<%| enabled(nodeinfo.software.fastd.enabled) %>
+ <%- end %> + <% if nodeinfo.software.autoupdater then -%> +
<%:Automatic updates%>
<%| enabled(nodeinfo.software.autoupdater.enabled) %><%| + nodeinfo.software.autoupdater.enabled and + string.format(' (%s)', nodeinfo.software.autoupdater.branch) + %>
+ <%- end %> +
+
+
+

<%:Monitoring%>

+ + + + + + + +
<%:Uptime%><%= statistics('uptime', 'time') %>
<%:Load average%><%= statistics('loadavg', 'decimal') %>
<%:RAM%><%= statistics('memory', 'memory') %>
<%:Filesystem%><%= statistics('rootfs_usage', 'percent') %>
<%:Gateway%><%= statistics('gateway') %>
<%:Clients%><%= statistics('clients/total') %>
+ +

<%:Traffic%>

+ + + + +
<%:Transmitted%><%= statisticsTraffic('traffic/tx') %>
<%:Received%><%= statisticsTraffic('traffic/rx') %>
<%:Forwarded%><%= statisticsTraffic('traffic/forward') %>
+ + +
+
+

<%:Neighbors%>

+ + <% + for _, iface in ipairs(interfaces) do + local wireless = is_wireless(iface) + local address = fs.readfile('/sys/class/net/' .. iface .. '/address') + if address then + %> +

<%| iface %>

+
> + + + + <% for i, v in ipairs(mesh.attrs or {}) do %> + ><%| v[2] %> + <% end %> + <% if wireless then %> + + + + <% end %> + +
<%:Node%>dBm<%:Distance%><%:Last seen%>
+
+ <% + end + end + %> +
+
+ + + diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo new file mode 100755 index 00000000..3f149100 --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/neighbours-nodeinfo @@ -0,0 +1,11 @@ +#!/bin/sh + +badrequest() { + echo 'Status: 400 Bad Request' + echo + exit 1 +} + +( gluon-list-mesh-interfaces | grep -qxF "$QUERY_STRING" ) 2>/dev/null || badrequest + +exec gluon-neighbour-info -s neighbour -i "$QUERY_STRING" -d ff02::2:1001 -p 1001 -r nodeinfo diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/stations b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations similarity index 54% rename from package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/stations rename to package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations index 258122fb..5ff1f125 100755 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/stations +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/stations @@ -6,10 +6,8 @@ badrequest() { exit 1 } -echo 'Access-Control-Allow-Origin: *' - -batctl if | cut -d: -f1 | grep -qxF "$QUERY_STRING" || badrequest +( gluon-list-mesh-interfaces | grep -qxF "$QUERY_STRING" ) 2>/dev/null || badrequest CMD="exec /lib/gluon/status-page/providers/stations '$QUERY_STRING'" -exec /usr/sbin/sse-multiplex "$CMD" +exec sse-multiplex "$CMD" diff --git a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics similarity index 75% rename from package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics rename to package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics index ef0dd3d8..502d35ea 100755 --- a/package/gluon-status-page-api/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/cgi-bin/dyn/statistics @@ -1,7 +1,5 @@ #!/bin/sh -echo 'Access-Control-Allow-Origin: *' - CMD='exec gluon-neighbour-info -s "" -l -d ::1 -p 1001 -t 3 -r statistics' exec /usr/sbin/sse-multiplex "$CMD" diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/index.html b/package/gluon-status-page/files/lib/gluon/status-page/www/index.html new file mode 100644 index 00000000..d5da1c84 --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/index.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.css b/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.css new file mode 100644 index 00000000..a6a974e2 --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.css @@ -0,0 +1 @@ +html,body,div,span,h1,h2,h3,dl,dt,dd,canvas,header,table,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent}body{background:rgba(0,0,0,0.12);font-family:Roboto, Lucida Grande, sans, Arial;color:rgba(0,0,0,0.87);font-size:14px;line-height:1}a{color:rgba(220,0,103,0.87);text-decoration:none;margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent}a:hover{text-decoration:underline}h1{font-weight:bold}h2{font-size:16px;margin-bottom:16px;color:rgba(0,0,0,0.54)}h3{font-size:15px;margin-top:16px;margin-bottom:8px;color:rgba(0,0,0,0.54)}header{display:flex;padding:0 14px;background:#dc0067;color:rgba(255,255,255,0.98);position:absolute;top:0;width:100%;box-sizing:border-box;height:20vh;z-index:-1;box-shadow:0px 5px 6px rgba(0,0,0,0.16),0px 1.5px 3px rgba(0,0,0,0.23);white-space:nowrap}header h1{font-size:24px;margin:10px 0;padding:6px 0;text-overflow:ellipsis;overflow:hidden;flex:1}.container{display:flex;max-width:90vw;margin:64px auto 24px auto;background:#fdfdfd;box-shadow:0px 5px 20px rgba(0,0,0,0.19),0px 3px 6px rgba(0,0,0,0.23)}.container>.frame{flex:1;border-style:solid;border-color:rgba(0,0,0,0.12);box-sizing:border-box;padding:16px}.container>.frame+.frame{border-width:0 0 0 1px}dt,th{font-weight:bold;color:rgba(0,0,0,0.87)}dt{margin-bottom:4px}th,td{text-align:left;padding:4px 16px 4px 0}th:last-child,td:last-child{padding-right:0}dd,td{font-weight:normal;font-size:0.9em;color:rgba(0,0,0,0.54)}dd{margin-bottom:16px}table{border-collapse:collapse;border-spacing:0}table.datatable{width:100%}table.datatable th,table.datatable td{font-size:1em;white-space:nowrap}table.datatable th:last-child,table.datatable td:last-child{width:100%}table.datatable tr.inactive{opacity:0.33}table.datatable tr.highlight{background:rgba(255,180,0,0.25)}canvas.signalgraph{margin-top:8px;width:100%}@media only screen and (max-width: 1250px){.container{max-width:none;margin:56px 0 0}header{height:56px;z-index:1;position:fixed}}@media only screen and (max-width: 700px){.container{display:block}.container>.frame+.frame{border-width:1px 0 0 0}} diff --git a/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.js b/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.js new file mode 100644 index 00000000..61d5f016 --- /dev/null +++ b/package/gluon-status-page/files/lib/gluon/status-page/www/static/status-page.js @@ -0,0 +1 @@ +"use strict";!function(){var a=JSON.parse(document.body.getAttribute("data-translations"));function i(t,e){return t.toFixed(e).replace(/\./,a["."])}function o(t,e){e--;for(var n=t;10<=n&&0e[0]?-1:t[1]e[1]?1:0});var e=t[0][2];return e&&!/^fe80:/i.test(e)?e:void 0}}(t.network.addresses);if(u){if("span"===h.nodeName.toLowerCase()){var f=h;h=document.createElement("a"),f.parentNode.replaceChild(h,f)}h.href="http://["+u+"]/"}if(h.textContent=t.hostname,y&&t.location){var l=(e=y.latitude,n=y.longitude,r=t.location.latitude,i=t.location.longitude,a=Math.PI/180,o=(r*=a)-(e*=a),c=(i*=a)-(n*=a),s=Math.sin(o/2)*Math.sin(o/2)+Math.sin(c/2)*Math.sin(c/2)*Math.cos(e)*Math.cos(r),2*Math.asin(Math.sqrt(s))*6372.8);d.textContent=Math.round(1e3*l)+" m"}p()},update_mesh:function(n){Object.keys(v).forEach(function(t){var e=v[t];e.td.textContent=n[t]+e.suffix}),p()},update_wifi:function(t){s.textContent=t.signal,u.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200\n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "%s days" +msgstr "%s Tage" + +msgid "%s packets/s" +msgstr "%s Pakete/s" + +msgid "%s used" +msgstr "%s belegt" + +msgid "." +msgstr "," + +msgid "1 day" +msgstr "1 Tag" + +msgid "Automatic updates" +msgstr "Automatische Updates" + +msgid "Clients" +msgstr "Clients" + +msgid "Contact" +msgstr "Kontakt" + +msgid "Distance" +msgstr "Entfernung" + +msgid "Error" +msgstr "Fehler" + +msgid "Filesystem" +msgstr "Dateisystem" + +msgid "Firmware" +msgstr "Firmware" + +msgid "Forwarded" +msgstr "Weitergeleitet" + +msgid "Gateway" +msgstr "Gateway" + +msgid "IP address" +msgstr "IP-Adresse" + +msgid "Last seen" +msgstr "Zuletzt gesehen" + +msgid "Load average" +msgstr "Systemlast" + +msgid "Mesh VPN" +msgstr "Mesh-VPN" + +msgid "Model" +msgstr "Modell" + +msgid "Monitoring" +msgstr "" + +msgid "Neighbors" +msgstr "Nachbarknoten" + +msgid "Node" +msgstr "Knoten" + +msgid "Node name" +msgstr "Knotenname" + +msgid "Overview" +msgstr "Übersicht" + +msgid "Primary MAC address" +msgstr "Primäre MAC-Adresse" + +msgid "RAM" +msgstr "RAM" + +msgid "Received" +msgstr "Empfangen" + +msgid "Status" +msgstr "Status" + +msgid "Traffic" +msgstr "" + +msgid "Transmitted" +msgstr "Gesendet" + +msgid "Uptime" +msgstr "Laufzeit" + +msgid "connected" +msgstr "verbunden" + +msgid "disabled" +msgstr "deaktiviert" + +msgid "enabled" +msgstr "aktiviert" + +msgid "not connected" +msgstr "nicht verbunden" diff --git a/package/gluon-status-page/i18n/gluon-status-page.pot b/package/gluon-status-page/i18n/gluon-status-page.pot new file mode 100644 index 00000000..56b02dae --- /dev/null +++ b/package/gluon-status-page/i18n/gluon-status-page.pot @@ -0,0 +1,107 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "%s days" +msgstr "" + +msgid "%s packets/s" +msgstr "" + +msgid "%s used" +msgstr "" + +msgid "." +msgstr "" + +msgid "1 day" +msgstr "" + +msgid "Automatic updates" +msgstr "" + +msgid "Clients" +msgstr "" + +msgid "Contact" +msgstr "" + +msgid "Distance" +msgstr "" + +msgid "Error" +msgstr "" + +msgid "Filesystem" +msgstr "" + +msgid "Firmware" +msgstr "" + +msgid "Forwarded" +msgstr "" + +msgid "Gateway" +msgstr "" + +msgid "IP address" +msgstr "" + +msgid "Last seen" +msgstr "" + +msgid "Load average" +msgstr "" + +msgid "Mesh VPN" +msgstr "" + +msgid "Model" +msgstr "" + +msgid "Monitoring" +msgstr "" + +msgid "Neighbors" +msgstr "" + +msgid "Node" +msgstr "" + +msgid "Node name" +msgstr "" + +msgid "Overview" +msgstr "" + +msgid "Primary MAC address" +msgstr "" + +msgid "RAM" +msgstr "" + +msgid "Received" +msgstr "" + +msgid "Status" +msgstr "" + +msgid "Traffic" +msgstr "" + +msgid "Transmitted" +msgstr "" + +msgid "Uptime" +msgstr "" + +msgid "connected" +msgstr "" + +msgid "disabled" +msgstr "" + +msgid "enabled" +msgstr "" + +msgid "not connected" +msgstr "" diff --git a/package/gluon-status-page/i18n/ru.README b/package/gluon-status-page/i18n/ru.README new file mode 100644 index 00000000..3f5101af --- /dev/null +++ b/package/gluon-status-page/i18n/ru.README @@ -0,0 +1,31 @@ +THe previous version of the status page had a Russian translation; +if we ever add Russion to gluon-web, the following strings can be reused: + +"Node": "Узел", +"Distance": "Дальность", +"Inactive": "Не активен", +"Node name": "Имя узла", +"Contact": "Контакт", +"Model": "Модель", +"Primary MAC": "Основной MAC", +"IP Address": "IP Адрес", +"Automatic updates": "Автоматические обновления", +"Overview": "Обзор", +"used": "используется", +"Uptime": "Время работы", +"Load average": "Загрузка системы", +"Gateway": "Шлюз", +"Clients": "Клиенты", +"Transmitted": "Передано", +"Received": "Получено", +"Forwarded": "Переправленно", +"Day": "День", +"Days": "Дней", +"connected": "подключено", +"not connected": "не подключено", +"Packets/s": "Пакетов/c", +"Statistic": "Статистика", +"Traffic": "Трафик", +"Neighbors": "Соседи", +"Firmware": "Прошивка", +"Branch": "Ветка" diff --git a/package/gluon-status-page/iconfont-config.json b/package/gluon-status-page/iconfont-config.json deleted file mode 100644 index af8718cc..00000000 --- a/package/gluon-status-page/iconfont-config.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "statuspage", - "css_prefix_text": "icon-", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "12f4ece88e46abd864e40b35e05b11cd", - "css": "ok", - "code": 59397, - "src": "fontawesome" - }, - { - "uid": "5211af474d3a9848f67f945e2ccaf143", - "css": "cancel", - "code": 59399, - "src": "fontawesome" - }, - { - "uid": "e15f0d620a7897e2035c18c80142f6d9", - "css": "link-ext", - "code": 59407, - "src": "fontawesome" - }, - { - "uid": "c76b7947c957c9b78b11741173c8349b", - "css": "attention", - "code": 59403, - "src": "fontawesome" - }, - { - "uid": "559647a6f430b3aeadbecd67194451dd", - "css": "menu", - "code": 59392, - "src": "fontawesome" - }, - { - "uid": "2d6150442079cbda7df64522dc24f482", - "css": "down-dir", - "code": 59393, - "src": "fontawesome" - }, - { - "uid": "80cd1022bd9ea151d554bec1fa05f2de", - "css": "up-dir", - "code": 59394, - "src": "fontawesome" - }, - { - "uid": "9dc654095085167524602c9acc0c5570", - "css": "left-dir", - "code": 59395, - "src": "fontawesome" - }, - { - "uid": "fb1c799ffe5bf8fb7f8bcb647c8fe9e6", - "css": "right-dir", - "code": 59396, - "src": "fontawesome" - }, - { - "uid": "a73c5deb486c8d66249811642e5d719a", - "css": "arrows-cw", - "code": 59400, - "src": "fontawesome" - }, - { - "uid": "750058837a91edae64b03d60fc7e81a7", - "css": "ellipsis-vert", - "code": 59401, - "src": "fontawesome" - }, - { - "uid": "56a21935a5d4d79b2e91ec00f760b369", - "css": "sort", - "code": 59404, - "src": "fontawesome" - }, - { - "uid": "94103e1b3f1e8cf514178ec5912b4469", - "css": "sort-down", - "code": 59405, - "src": "fontawesome" - }, - { - "uid": "65b3ce930627cabfb6ac81ac60ec5ae4", - "css": "sort-up", - "code": 59406, - "src": "fontawesome" - }, - { - "uid": "cda0cdcfd38f5f1d9255e722dad42012", - "css": "spinner", - "code": 59402, - "src": "fontawesome" - } - ] -} \ No newline at end of file diff --git a/package/gluon-status-page/javascript/status-page.js b/package/gluon-status-page/javascript/status-page.js new file mode 100644 index 00000000..fcd6fd95 --- /dev/null +++ b/package/gluon-status-page/javascript/status-page.js @@ -0,0 +1,765 @@ +/* + Build using: + + uglifyjs javascript/status-page.js -o files/lib/gluon/status-page/www/static/status-page.js -c -m +*/ + +'use strict'; + +(function() { + var _ = JSON.parse(document.body.getAttribute('data-translations')); + + String.prototype.sprintf = function() { + var i = 0; + var args = arguments; + + return this.replace(/%s/g, function() { + return args[i++]; + }); + }; + + function formatNumberFixed(d, digits) { + return d.toFixed(digits).replace(/\./, _['.']) + } + + function formatNumber(d, digits) { + digits--; + + for (var v = d; v >= 10 && digits > 0; v /= 10) + digits--; + + // avoid toPrecision as it might produce strings in exponential notation + return formatNumberFixed(d, digits); + } + + function prettyPackets(d) { + return _['%s packets/s'].sprintf(formatNumberFixed(d, 0)); + } + + function prettyPrefix(prefixes, step, d) { + var prefix = 0; + + if (d === undefined) + return "- "; + + while (d > step && prefix < prefixes.length - 1) { + d /= step; + prefix++; + } + + d = formatNumber(d, 3); + return d + " " + prefixes[prefix]; + } + + function prettySize(d) { + return prettyPrefix([ "", "K", "M", "G", "T" ], 1024, d); + } + + function prettyBits(d) { + return prettySize(8 * d) + "bps"; + } + + function prettyBytes(d) { + return prettySize(d) + "B"; + } + + var formats = { + 'id': function(value) { + return value; + }, + 'decimal': function(value) { + return formatNumberFixed(value, 2); + }, + 'percent': function(value) { + return _['%s used'].sprintf(formatNumber(100 * value, 3) + '%'); + }, + 'memory': function(memory) { + var usage = 1 - (memory.free + memory.buffers + memory.cached) / memory.total + return formats.percent(usage); + }, + 'time': function(seconds) { + var minutes = Math.round(seconds / 60); + + var days = Math.floor(minutes / 1440); + var hours = Math.floor((minutes % 1440) / 60); + minutes = Math.floor(minutes % 60); + + var out = ''; + + if (days === 1) + out += _['1 day'] + ', '; + else if (days > 1) + out += _['%s days'].sprintf(days) + ", "; + + out += hours + ":"; + + if (minutes < 10) + out += "0"; + + out += minutes; + + return out; + }, + 'packetsDiff': function(packets, packetsPrev, diff) { + if (diff > 0) + return prettyPackets((packets-packetsPrev) / diff); + + }, + 'bytesDiff': function(bytes, bytesPrev, diff) { + if (diff > 0) + return prettyBits((bytes-bytesPrev) / diff); + }, + 'bytes': function(bytes) { + return prettyBytes(bytes); + }, + } + + + function resolve_key(obj, key) { + key.split('/').forEach(function(part) { + if (obj) + obj = obj[part]; + }); + + return obj; + } + + function add_event_source(url, handler) { + var source = new EventSource(url); + var prev = {}; + source.onmessage = function(m) { + var data = JSON.parse(m.data); + handler(data, prev); + prev = data; + } + source.onerror = function() { + source.close(); + window.setTimeout(function() { + add_event_source(url, handler); + }, 3000); + } + } + + var node_address = document.body.getAttribute('data-node-address'); + + var location; + try { + location = JSON.parse(document.body.getAttribute('data-node-location')); + } catch (e) { + } + + + function update_mesh_vpn(data) { + function add_group(peers, d) { + Object.keys(d.peers || {}).forEach(function(peer) { + peers.push([peer, d.peers[peer]]); + }); + + Object.keys(d.groups || {}).forEach(function(group) { + add_group(peers, d.groups[group]); + }); + + return peers; + } + + var div = document.getElementById('mesh-vpn'); + if (!data) { + div.style.display = 'none'; + return; + } + + div.style.display = ''; + var table = document.getElementById('mesh-vpn-peers'); + while (table.lastChild) + table.removeChild(table.lastChild); + + var peers = add_group([], data); + peers.sort(); + + peers.forEach(function (peer) { + var tr = document.createElement('tr'); + + var th = document.createElement('th'); + th.textContent = peer[0]; + tr.appendChild(th); + + var td = document.createElement('td'); + if (peer[1]) + td.textContent = _['connected'] + ' (' + formats.time(peer[1].established) + ')'; + else + td.textContent = _['not connected']; + tr.appendChild(td); + + table.appendChild(tr); + }); + } + + var statisticsElems = document.querySelectorAll('[data-statistics]'); + + add_event_source('/cgi-bin/dyn/statistics', function(data, dataPrev) { + var diff = data.uptime - dataPrev.uptime; + + statisticsElems.forEach(function(elem) { + var stat = elem.getAttribute('data-statistics'); + var format = elem.getAttribute('data-format'); + + var valuePrev = resolve_key(dataPrev, stat); + var value = resolve_key(data, stat); + try { + var text = formats[format](value, valuePrev, diff); + if (text !== undefined) + elem.textContent = text; + } catch (e) { + console.error(e); + } + }); + + try { + update_mesh_vpn(data.mesh_vpn); + } catch (e) { + console.error(e); + } + }) + + function haversine(lat1, lon1, lat2, lon2) { + var rad = Math.PI / 180; + lat1 *= rad; lon1 *= rad; lat2 *= rad; lon2 *= rad; + + var R = 6372.8; // km + var dLat = lat2 - lat1; + var dLon = lon2 - lon1; + var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2); + var c = 2 * Math.asin(Math.sqrt(a)); + return R * c; + } + + var interfaces = {}; + + function Signal(color) { + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + var value = null; + var radius = 1.2; + + function drawPixel(x, y) { + ctx.beginPath(); + ctx.fillStyle = color; + ctx.arc(x, y, radius, 0, 2 * Math.PI, false); + ctx.closePath(); + ctx.fill(); + } + + return { + 'canvas': canvas, + 'highlight': false, + + 'resize': function(w, h) { + var lastImage; + try { + ctx.getImageData(0, 0, w, h); + } catch (e) {} + canvas.width = w; + canvas.height = h; + if (lastImage) + ctx.putImageData(lastImage, 0, 0); + }, + + 'draw': function(x, scale) { + var y = scale(value); + + ctx.clearRect(x, 0, 5, canvas.height) + + if (y) + drawPixel(x, y) + }, + + 'set': function (d) { + value = d; + }, + }; + } + + function SignalGraph() { + var min = -100, max = 0; + var i = 0; + + var signals = []; + + var canvas = document.createElement('canvas'); + canvas.className = 'signalgraph'; + canvas.height = 200; + + var ctx = canvas.getContext('2d'); + + function scaleInverse(n, min, max, height) { + return (min * n + max * (height - n)) / height; + } + + function scale(n, min, max, height) { + return (1 - (n - min) / (max - min)) * height; + } + + function drawGrid() { + var nLines = Math.floor(canvas.height / 40); + ctx.save(); + ctx.lineWidth = 0.5; + ctx.strokeStyle = 'rgba(0, 0, 0, 0.25)'; + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.textAlign = 'end'; + ctx.textBaseline = 'bottom'; + + ctx.beginPath(); + + for (var i = 0; i < nLines; i++) { + var y = canvas.height - i * 40; + ctx.moveTo(0, y - 0.5); + ctx.lineTo(canvas.width, y - 0.5); + var dBm = Math.round(scaleInverse(y, min, max, canvas.height)) + ' dBm'; + + ctx.save(); + ctx.strokeStyle = 'rgba(255, 255, 255, 0.9)'; + ctx.lineWidth = 4; + ctx.miterLimit = 2; + ctx.strokeText(dBm, canvas.width - 5, y - 2.5); + ctx.fillText(dBm, canvas.width - 5, y - 2.5); + ctx.restore(); + } + + ctx.stroke(); + + ctx.strokeStyle = 'rgba(0, 0, 0, 0.83)'; + ctx.lineWidth = 1.5; + ctx.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1); + + ctx.restore(); + } + + function resize() { + canvas.width = canvas.clientWidth; + signals.forEach(function(signal) { + signal.resize(canvas.width, canvas.height); + }); + } + resize(); + + function draw() { + if (canvas.clientWidth === 0) + return; + + if (canvas.width !== canvas.clientWidth) + resize(); + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + var highlight = false; + signals.forEach(function(signal) { + if (signal.highlight) + highlight = true; + }); + + ctx.save(); + signals.forEach(function(signal) { + if (highlight) + ctx.globalAlpha = 0.2; + + if (signal.highlight) + ctx.globalAlpha = 1; + + signal.draw(i, function(value) { + return scale(value, min, max, canvas.height); + }); + ctx.drawImage(signal.canvas, 0, 0); + }); + ctx.restore(); + + ctx.save(); + ctx.beginPath(); + ctx.strokeStyle = 'rgba(255, 180, 0, 0.15)'; + ctx.lineWidth = 5; + ctx.moveTo(i + 2.5, 0); + ctx.lineTo(i + 2.5, canvas.height); + ctx.stroke(); + + drawGrid(); + } + + window.addEventListener('resize', draw); + + var last = 0; + function step(timestamp) { + var delta = timestamp - last; + + if (delta > 40) { + draw(); + i = (i + 1) % canvas.width; + last = timestamp; + }; + + window.requestAnimationFrame(step); + } + + window.requestAnimationFrame(step); + + return { + 'el': canvas, + + 'addSignal': function(signal) { + signals.push(signal); + signal.resize(canvas.width, canvas.height); + }, + + 'removeSignal': function(signal) { + signals.splice(signals.indexOf(signal), 1); + }, + }; + } + + function Neighbour(iface, addr, color, destroy) { + var th = iface.table.firstElementChild; + var el = iface.table.insertRow(); + + var tdHostname = el.insertCell(); + + if (iface.wireless) { + var marker = document.createElement("span"); + marker.textContent = "⬤ "; + marker.style.color = color; + tdHostname.appendChild(marker); + } + + var hostname = document.createElement("span"); + hostname.textContent = addr; + tdHostname.appendChild(hostname); + + var meshAttrs = {}; + + function add_attr(attr) { + var key = attr.getAttribute('data-key'); + if (!key) + return; + + var suffix = attr.getAttribute('data-suffix') || ''; + + var td = el.insertCell(); + td.textContent = '-'; + + meshAttrs[key] = { + 'td': td, + 'suffix': suffix, + }; + } + + for (var i = 0; i < th.children.length; i++) + add_attr(th.children[i]); + + var tdSignal; + var tdDistance; + var tdInactive; + var signal; + + if (iface.wireless) { + tdSignal = el.insertCell(); + tdSignal.textContent = '-'; + tdDistance = el.insertCell(); + tdDistance.textContent = '-'; + tdInactive = el.insertCell(); + tdInactive.textContent = '-'; + + signal = Signal(color); + iface.signalgraph.addSignal(signal); + } + + el.onmouseenter = function () { + el.classList.add("highlight"); + if (signal) + signal.highlight = true; + } + + el.onmouseleave = function () { + el.classList.remove("highlight") + if (signal) + signal.highlight = false; + } + + var timeout; + + function updated() { + if (timeout) + window.clearTimeout(timeout); + + timeout = window.setTimeout(function() { + if (signal) + iface.signalgraph.removeSignal(signal); + + el.parentNode.removeChild(el); + destroy(); + }, 60000); + } + updated(); + + function address_to_groups(addr) { + if (addr.slice(0, 2) == '::') + addr = '0' + addr; + if (addr.slice(-2) == '::') + addr = addr + '0'; + + var parts = addr.split(':'); + var n = parts.length; + var groups = []; + + parts.forEach(function(part, i) { + if (part === '') { + while (n++ <= 8) + groups.push(0); + } else { + if (!/^[a-f0-9]{1,4}$/i.test(part)) + return; + + groups.push(parseInt(part, 16)); + } + }); + + return groups; + } + + function address_to_binary(addr) { + var groups = address_to_groups(addr); + if (!groups) + return; + + var ret = ''; + groups.forEach(function(group) { + ret += ('0000000000000000' + group.toString(2)).slice(-16); + }); + + return ret; + } + + function common_length(a, b) { + var i; + for (i = 0; i < a.length && i < b.length; i++) { + if (a[i] !== b[i]) + break; + } + return i; + } + + function choose_address(addresses) { + var node_bin = address_to_binary(node_address); + + if (!addresses || !addresses[0]) + return; + + addresses = addresses.map(function(addr) { + var addr_bin = address_to_binary(addr); + if (!addr_bin) + return [-1]; + + var common_prefix = 0; + if (node_bin) + common_prefix = common_length(node_bin, addr_bin); + + return [common_prefix, addr_bin, addr]; + }); + + addresses.sort(function(a, b) { + if (a[0] < b[0]) + return 1; + else if (a[0] > b[0]) + return -1; + else if (a[1] < b[1]) + return -1; + else if (a[1] > b[1]) + return 1; + else + return 0; + + }); + + var address = addresses[0][2]; + if (address && !/^fe80:/i.test(address)) + return address; + } + + return { + 'update_nodeinfo': function(nodeinfo) { + var addr = choose_address(nodeinfo.network.addresses); + if (addr) { + if (hostname.nodeName.toLowerCase() === 'span') { + var oldHostname = hostname; + hostname = document.createElement('a'); + oldHostname.parentNode.replaceChild(hostname, oldHostname); + } + + hostname.href = 'http://[' + addr + ']/'; + } + + hostname.textContent = nodeinfo.hostname; + + if (location && nodeinfo.location) { + var distance = haversine( + location.latitude, location.longitude, + nodeinfo.location.latitude, nodeinfo.location.longitude + ); + tdDistance.textContent = Math.round(distance * 1000) + " m" + } + + updated(); + }, + 'update_mesh': function(mesh) { + Object.keys(meshAttrs).forEach(function(key) { + var attr = meshAttrs[key]; + attr.td.textContent = mesh[key] + attr.suffix; + }); + + updated(); + }, + 'update_wifi': function(wifi) { + var inactiveLimit = 200; + + tdSignal.textContent = wifi.signal; + tdInactive.textContent = Math.round(wifi.inactive / 1000) + ' s'; + + el.classList.toggle('inactive', wifi.inactive > inactiveLimit); + signal.set(wifi.inactive > inactiveLimit ? null : wifi.signal); + + updated(); + }, + }; + } + + function Interface(el, ifname, wireless) { + + var neighs = {}; + + var signalgraph; + if (wireless) { + signalgraph = SignalGraph(); + el.appendChild(signalgraph.el); + } + + var info = { + 'table': el.firstElementChild, + 'signalgraph': signalgraph, + 'ifname': ifname, + 'wireless': wireless, + }; + + var nodeinfo_running = false; + var want_nodeinfo = {}; + + var graphColors = []; + function get_color() { + if (!graphColors[0]) + graphColors = ["#396AB1", "#DA7C30", "#3E9651", "#CC2529", "#535154", "#6B4C9A", "#922428", "#948B3D"]; + + return graphColors.shift(); + } + + function neigh_addresses(nodeinfo) { + var addrs = []; + + var mesh = nodeinfo.network.mesh; + Object.keys(mesh).forEach(function(meshif) { + var ifaces = mesh[meshif].interfaces; + Object.keys(ifaces).forEach(function(ifaceType) { + ifaces[ifaceType].forEach(function(addr) { + addrs.push(addr); + }); + }); + }); + + return addrs; + } + + function load_nodeinfo() { + if (nodeinfo_running) + return; + + nodeinfo_running = true; + + var source = new EventSource('/cgi-bin/dyn/neighbours-nodeinfo?' + encodeURIComponent(ifname)); + source.addEventListener("neighbour", function(m) { + try { + var data = JSON.parse(m.data); + neigh_addresses(data).forEach(function(addr) { + var neigh = neighs[addr]; + if (neigh) { + delete want_nodeinfo[addr]; + try { + neigh.update_nodeinfo(data); + } catch (e) { + console.error(e); + } + } + }); + } catch (e) { + console.error(e); + } + }, false); + + source.onerror = function() { + source.close(); + nodeinfo_running = false; + + Object.keys(want_nodeinfo).forEach(function (addr) { + if (want_nodeinfo[addr] > 0) { + want_nodeinfo[addr]--; + load_nodeinfo(); + } + }); + } + } + + + function get_neigh(addr) { + var neigh = neighs[addr]; + if (!neigh) { + want_nodeinfo[addr] = 3; + neigh = neighs[addr] = Neighbour(info, addr, get_color(), function() { + delete want_nodeinfo[addr]; + delete neighs[addr]; + }); + load_nodeinfo(); + } + + return neigh; + } + + if (wireless) { + add_event_source('/cgi-bin/dyn/stations?' + encodeURIComponent(ifname), function(data) { + Object.keys(data).forEach(function (addr) { + var wifi = data[addr]; + + get_neigh(addr).update_wifi(wifi); + }); + }); + } + + return { + 'get_neigh': get_neigh, + }; + } + + document.querySelectorAll('[data-interface]').forEach(function(elem) { + var ifname = elem.getAttribute('data-interface'); + var address = elem.getAttribute('data-interface-address'); + var wireless = !!elem.getAttribute('data-interface-wireless'); + + interfaces[ifname] = Interface(elem, ifname, wireless); + }); + + var mesh_provider = document.body.getAttribute('data-mesh-provider'); + if (mesh_provider) { + add_event_source(mesh_provider, function(data) { + Object.keys(data).forEach(function (addr) { + var mesh = data[addr]; + var iface = interfaces[mesh.ifname]; + if (!iface) + return; + + iface.get_neigh(addr).update_mesh(mesh); + }); + }); + } +})(); diff --git a/package/gluon-status-page/luasrc/lib/gluon/status-page/controller/status-page.lua b/package/gluon-status-page/luasrc/lib/gluon/status-page/controller/status-page.lua new file mode 100644 index 00000000..bdd46979 --- /dev/null +++ b/package/gluon-status-page/luasrc/lib/gluon/status-page/controller/status-page.lua @@ -0,0 +1,86 @@ +local json = require 'jsonc' +local site = require 'gluon.site' +local util = require 'gluon.util' + +local function parse_ip(addr) + if not addr then return end + + local ip4 = {addr:match('(%d+)%.(%d+)%.(%d+)%.(%d+)')} + if ip4[1] then + local ret = {} + + for i, part in ipairs(ip4) do + ret[i] = tonumber(part) + end + return ret + end + + if not addr:match('^[:%x]+$') then + return + end + + if addr:sub(0, 2) == '::' then + addr = '0' .. addr + end + if addr:sub(-2) == '::' then + addr = addr .. '0' + end + + addr = addr .. ':' + + local groups, groups1 = {}, {} + for part in addr:gmatch('([^:]*):') do + if part == '' then + groups1 = groups + groups = {} + else + groups[#groups+1] = tonumber(part, 16) + end + end + + while #groups + #groups1 < 8 do + groups1[#groups1+1] = 0 + end + for _, group in ipairs(groups) do + groups1[#groups1+1] = group + end + + return groups1 +end + +local function match(a, b, n) + if not a or not b then return false end + + for i = 1, n do + if a[i] ~= b[i] then + return false + end + end + + return true +end + +entry({}, call(function(http, renderer) + local nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 1 -c 1 -r nodeinfo')) + + local node_ip = parse_ip(http:getenv('SERVER_ADDR')) + if node_ip and ( + match(node_ip, parse_ip(site.next_node.ip4()), 8) or + match(node_ip, parse_ip(site.next_node.ip6()), 8) + ) then + -- The user has visited the status page via a next-node address + -- Redirect the user to a unique address to avoid switching nodes + local prefix = parse_ip(site.prefix6():match('^[^/]+')) + for _, addr in ipairs(nodeinfo.network.addresses) do + if match(prefix, parse_ip(addr), 4) then + http:header('Cache-Control', 'no-cache, no-store, must-revalidate') + http:redirect('http://[' .. addr .. ']' .. http:getenv('REQUEST_URI')) + http:close() + return + end + end + end + + + renderer.render('status-page', { nodeinfo = nodeinfo }, 'gluon-status-page') +end)) diff --git a/package/gluon-status-page/luasrc/lib/gluon/status-page/www/cgi-bin/status b/package/gluon-status-page/luasrc/lib/gluon/status-page/www/cgi-bin/status new file mode 100755 index 00000000..7e5079ac --- /dev/null +++ b/package/gluon-status-page/luasrc/lib/gluon/status-page/www/cgi-bin/status @@ -0,0 +1,8 @@ +#!/usr/bin/lua + +require 'gluon.web.cgi' { + base_path = '/lib/gluon/status-page', + + layout_package = 'gluon-status-page', + layout_template = 'layout', -- only used for error pages +} diff --git a/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page b/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page new file mode 100755 index 00000000..9771a034 --- /dev/null +++ b/package/gluon-status-page/luasrc/lib/gluon/upgrade/500-status-page @@ -0,0 +1,38 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() + + +local function get_mem_total() + for line in io.lines('/proc/meminfo') do + local match = line:match('^MemTotal:%s+(%d+)') + if match then + return tonumber(match) + end + end +end + +local max_requests = 32 +if get_mem_total() < 48*1024 then + max_requests = 16 +end + +uci:section('uhttpd', 'uhttpd', 'main', { + listen_http = { '0.0.0.0:80', '[::]:80' }, + listen_https = {}, + + home = '/lib/gluon/status-page/www', + max_requests = max_requests, +}) +uci:save('uhttpd') + + +for _, zone in ipairs({'mesh', 'local_client'}) do + uci:section('firewall', 'rule', zone .. '_http', { + src = zone, + dest_port = '80', + proto = 'tcp', + target = 'ACCEPT', + }) +end +uci:save('firewall') diff --git a/package/gluon-status-page/sass/status-page.scss b/package/gluon-status-page/sass/status-page.scss new file mode 100644 index 00000000..cfaa561f --- /dev/null +++ b/package/gluon-status-page/sass/status-page.scss @@ -0,0 +1,195 @@ +/* + ATTENTION: This file is not compiled when building gluon. + The compiled version is at ../files/lib/gluon/status-page/www/static/status-page.css + + Use sass like this to update it: + + sass --sourcemap=none -C -t compressed sass/status-page.scss files/lib/gluon/status-page/www/static/status-page.css + + When commiting changes to this file make sure to commit the respective + changes to the compiled version within the same commit! +*/ + +html, body, div, span, +h1, h2, h3, +dl, dt, dd, +canvas, header, +table, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-size: 100%; + vertical-align: baseline; + background: transparent; +} + +body { + background: rgba(0, 0, 0, 0.12); + font-family: Roboto, Lucida Grande, sans, Arial; + color: rgba(0, 0, 0, 0.87); + font-size: 14px; + line-height: 1; +} + + +a { + color: rgba(220, 0, 103, 0.87); + text-decoration: none; + + margin: 0; + padding: 0; + font-size: 100%; + vertical-align: baseline; + background: transparent; + + &:hover { + text-decoration: underline; + } +} + +h1 { + font-weight: bold; +} + +h2 { + font-size: 16px; + margin-bottom: 16px; + color: rgba(0, 0, 0, 0.54); +} + +h3 { + font-size: 15px; + margin-top: 16px; + margin-bottom: 8px; + color: rgba(0, 0, 0, 0.54); +} + +header { + display: flex; + padding: 0 14px; + background: #dc0067; + color: rgba(255, 255, 255, 0.98); + position: absolute; + top: 0; + width: 100%; + box-sizing: border-box; + height: 20vh; + z-index: -1; + box-shadow: 0px 5px 6px rgba(0, 0, 0, 0.16), 0px 1.5px 3px rgba(0, 0, 0, 0.23); + white-space: nowrap; + + h1 { + font-size: 24px; + margin: 10px 0; + padding: 6px 0; + + text-overflow: ellipsis; + overflow: hidden; + flex: 1; + } +} + +.container { + display: flex; + + max-width: 90vw; + margin: 64px auto 24px auto; + background: rgb(253, 253, 253); + box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); + + & > .frame { + flex: 1; + border-style: solid; + border-color: rgba(0, 0, 0, 0.12); + + box-sizing: border-box; + padding: 16px; + + & + .frame { + border-width: 0 0 0 1px; + } + } +} + +dt, th { + font-weight: bold; + color: rgba(0, 0, 0, 0.87); +} + +dt { + margin-bottom: 4px; +} + +th, td { + text-align: left; + padding: 4px 16px 4px 0; + + &:last-child { + padding-right: 0; + } +} + +dd, td { + font-weight: normal; + font-size: 0.9em; + color: rgba(0, 0, 0, 0.54); +} + +dd { + margin-bottom: 16px; +} + +table { + border-collapse: collapse; + border-spacing: 0; + + &.datatable { + width: 100%; + + th, td { + font-size: 1em; + white-space: nowrap; + + &:last-child { + width: 100%; + } + } + + tr.inactive { + opacity: 0.33; + } + + tr.highlight { + background: rgba(255, 180, 0, 0.25); + } + } +} + +canvas.signalgraph { + margin-top: 8px; + width: 100%; +} + +@media only screen and (max-width: 1250px) { + .container { + max-width: none; + margin: 56px 0 0; + } + + header { + height: 56px; + z-index: 1; + position: fixed; + } +} + +@media only screen and (max-width: 700px) { + .container { + display: block; + + & > .frame + .frame { + border-width: 1px 0 0 0; + } + } +} diff --git a/package/gluon-status-page/src/Makefile b/package/gluon-status-page/src/Makefile new file mode 100644 index 00000000..a0a14e16 --- /dev/null +++ b/package/gluon-status-page/src/Makefile @@ -0,0 +1,26 @@ +CFLAGS += -std=c99 -D_BSD_SOURCE +CPPFLAGS += -D_GNU_SOURCE + +ifeq ($(origin PKG_CONFIG), undefined) + PKG_CONFIG = pkg-config + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif +endif + +ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined) + LIBNL_NAME ?= libnl-tiny + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),) + $(error No $(LIBNL_NAME) development libraries found!) + endif + LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME)) + LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME)) +endif + +CFLAGS_JSONC = $(shell pkg-config --cflags json-c) +LDFLAGS_JSONC = $(shell pkg-config --libs json-c) + +all: stations + +stations: stations.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_JSONC) $(LDFLAGS) $(LDFLAGS_JSONC) -Wall -o $@ $^ $(LDLIBS) -liwinfo diff --git a/package/gluon-status-page/src/build.js b/package/gluon-status-page/src/build.js deleted file mode 100644 index a1b1d703..00000000 --- a/package/gluon-status-page/src/build.js +++ /dev/null @@ -1,10 +0,0 @@ -({ - paths: { - "bacon": "../Bacon" - }, - baseUrl: "js/", - name: "../almond", - include: "main", - optimize: "uglify2", - out: "app.js", -}) diff --git a/package/gluon-status-page/src/css/animation.css b/package/gluon-status-page/src/css/animation.css deleted file mode 100644 index ac5a9562..00000000 --- a/package/gluon-status-page/src/css/animation.css +++ /dev/null @@ -1,85 +0,0 @@ -/* - Animation example, for spinners -*/ -.animate-spin { - -moz-animation: spin 2s infinite linear; - -o-animation: spin 2s infinite linear; - -webkit-animation: spin 2s infinite linear; - animation: spin 2s infinite linear; - display: inline-block; -} -@-moz-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -moz-transform: rotate(359deg); - -o-transform: rotate(359deg); - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@-webkit-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -moz-transform: rotate(359deg); - -o-transform: rotate(359deg); - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@-o-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -moz-transform: rotate(359deg); - -o-transform: rotate(359deg); - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@-ms-keyframes spin { - 0% { - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -moz-transform: rotate(359deg); - -o-transform: rotate(359deg); - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes spin { - 0% { - -moz-transform: rotate(0deg); - -o-transform: rotate(0deg); - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - - 100% { - -moz-transform: rotate(359deg); - -o-transform: rotate(359deg); - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} diff --git a/package/gluon-status-page/src/css/font.css b/package/gluon-status-page/src/css/font.css deleted file mode 100644 index c26ee355..00000000 --- a/package/gluon-status-page/src/css/font.css +++ /dev/null @@ -1,53 +0,0 @@ -@font-face { - font-family: 'statuspage'; - src: url(data:application/font-woff;charset=utf-8;base64,d09GRgABAAAAABBIABEAAAAAGvAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABgAAAABwAAAAcbmIpTEdERUYAAAGcAAAAHQAAACAAQAAET1MvMgAAAbwAAABEAAAAVolbUzJjbWFwAAACAAAAAFAAAAFaNCnF72N2dCAAAAJQAAAACgAAAAoAAAAAZnBnbQAAAlwAAAWUAAALcIiQkFlnYXNwAAAH8AAAAAgAAAAIAAAAEGdseWYAAAf4AAAFIQAAB5Aqg1+6aGVhZAAADRwAAAAvAAAANgs/y+hoaGVhAAANTAAAAB8AAAAkD4gG32htdHgAAA1sAAAAOAAAAExf6AFkbG9jYQAADaQAAAAoAAAAKA0UDxRtYXhwAAANzAAAAB4AAAAgALUAX25hbWUAAA3sAAABUQAAAo4VwGZqcG9zdAAAD0AAAACYAAAAzEaEO/VwcmVwAAAP2AAAAGUAAAB73WsDhXdlYmYAABBAAAAABgAAAAaP4VXgAAAAAQAAAADMPaLPAAAAANAeRhwAAAAA0gZAYHjaY2BkYGDgA2IJBhBgYmAEQiEgZgHzGAAFEABFAAAAeNpjYGQNZpzAwMrAwirEOouBgVEeQjNfZ0hhEmBgYGJgZWbACgLSXFMYHFT/vOBnO/vvLMMOtrMMS4DCjCA5AKFmDF942mNgYGBmgGAZBkYGEAgB8hjBfBYGCyDNxcDBwASEDKp/XrC+4P//H6QIyGZ4wQ5i32KXYJFghuqFAkY2BrgAI1AnSDcKYGQY9gAAyR8MCgAAAAAAAAAAAAAAAHjarVZpcxNHEJ3VYcs2PoIPEjaBWcZyjHZWmMsIEMbsShbgHPKV7EKOXUt27otP/Ab9ml6RVJFv/LS8Hh3YYCdVVChK/ab37Uz3655ek9CSxF5Yj6TcfCmmtjZpZOdJSDdsWo7iQ9nZCylTTP4uiIJotdS+7TgkIhKBqnWFJYLY98jSJONDjzJatiW9alJu6Ul32RoP6q369tPQUY7dCSU1m6FD65EtqcKoEkUy7ZGSNi3D1V9JWuHnK8x81QwlgugkksabYQyP5GfjjFYZrcZ2HEWRTZYbRYpEMzyIIo+yWmKfXDFBQPmgGVJe+TSifIQfkRV7lNMKccl2mt/3JT/pHc6/JOJ6i7IlB/5AdmQHe6cr+SLS2grjpp1sR6GK8HR9J8Qjm5Pqn+xRXtNo4HZFpifNCJbKV5BY+Qll9g/JauF8ypc8GtWSg5wIWi9zYl/yDrQeR0yJaybIgu6OToig7pecodhj+rj4471dLBchBMg4lvWOSrgQRilhs5okbQQ5iJKyRZXUekdMnPI6LeItYb9O7ehLZ7RJqDsxnq2Hjq2cqOR4NKnTTKZO7aTm0ZQGUUo6Ezzm1wGUH9Ekr7axmsTKo2lsM2MkkVCghXNpKohlJ5Y0BdE8mtGbu2Gaa9eiRZo8UM89ek9vboWbOz2n7cA/a/xndSqmg70wnZ4OyEp8mna5SdG6fnqGfybxQ9YCKpEtNsOUxUO2fgfl5WNLjsJrA2z3nvMr6H32RMikgfgb8B4v1SkFTIWYVVAL3bTWtSzL1GpWi1Rk6rshTStf1mkCTTkOfWNfxjj+r5kZS0wJ3+/E6dkRl5659iXINIfcZl2P5nVqsV2AzmzP6TTL9n2d5th+oNM82/M6HWFr63SU7Yc6LbD9SKdjbC9oQZPuOwRyEYFcwAYSgbB1EAjbSwiErUIgbBcRCNsiAmG7hEDYfoxA2C4jELaXtayafippHDsTywBFiAOjOe7IZW4qV1PJpRKui0anNuQpcqukonhW/SsD/eKRN6yBtUC6RNb8ikmufFSV44+uaHnTxLkCjlV/e3NcnxMPZb9Y+FPwv9qaqqRXrHlkchV5I9CT40TXJhWPrunyuapH1/+Lig5rgX4DpRALRVmWDb6ZkPBRp9NQDVzlEDMbMw/X9bplzc/h/JsYIQvofvw3FBoL3INOWUlZ7WCv1dePZbm3B+WwJ1iSYr7M61vhi4zMSvtFZil7PvJ5wBUwKpVhqw1creDNexLzkOlN8kwQtxVlg6SNx5kgsYFjHjBvvpMgJExdtYHaKZywgbxgzCnY74RDVG+U5XB7oX0ejZR/a1fsyBkVTRD4bfZG2OuzUPJbrIGEJ7/U10BVIU3FuKmASyPlhmrwYVyt20YyTqCvqNgNy7KKDx9H3HdKjmUg+UgRq0dHP629Qp3Uuf3KKG7fO/0IgkFpYv72vpnioJR3tZJlVm0DU7calVPXmsPFqw7dzaPue8fZJ3LWNN10T9z0vqZVt4ODuVkQ7dsclKVMLqjrww4bqMvNpdDqZVyS3nYPMCwwoN+hFRv/V/dx+DxXqgqj40i9nagfo89iDPIPOH9H9QXo5zFMuYaU53uXE59u3MPZMl3FXayf4t/ArLXmZukacEPTDZiHrFodusoNfKcGOj3S3I70EPCx7grxAGATwGLwie5axvMpgPF8xhwf4HPmMGgyh8EWcxhsM2cNYIc5DHaZw2CPOQy+YM46wJfMYRAyh0HEHAZPmBMAPGUOg6+Yw+Br5jD4hjn3Ab5lDoOYOQwS5jDY13RrKHOLF3QXqG1QFejA9BMW97A41FQZsr/jhWF/bxCzfzCIqT9quj2k/sQLQ/3ZIKb+YhBTf9V0Z0j9jReG+rtBTP3DIKY+0y/GcpnBX0a+S4UDyi42n/P3xPsHwhpAtgABAAH//wAPeNp9VU1oG0cUnje7WlmKvJKsXa0dR9qMFK+symslki1VUezEgtiN6gajhkBFUcE9RSY1rZuWYoIIpqQmh+IkB9OmoYeS+lCCoTQ/t+TQlBB0aKGU4qan5pBLKD4EHOR13+zKpHFJdRjNmzfvm+/Nm/ctAbL9EwgpCHzcWpfWXCvET3SSJt6bA/He0C5RMFMjMJTLs0zYrSpSgsUMYXgop73EdqNtRqQJ3aRJtnFbT9L/sYoX9X5hcM9FfYD201OXIwM0Gb0cQS89tWRvWuIRhCBXqIlLwjqRifS9VwAzFXQoSW6QYgnAI0USGRC7LKIVwjgIKzzyIJ9qlISJg6EhxoqDIdoYeRgFDcKKFEfauFEZUXFIRltET0JND6MBKmKM9PcTG6NMFuiaS3uOEUKMHKYeVGweZYUigwNicixkEYU2dW4P7mmRiPmcB2IsIUYnYuziGMPBIYcGT8YwC5yIwjMxmyLR+109CDXKF0w7/gKh7jOuKaJifNBjcziMHDQPDnobBalc0K+w6l6Yok/w74qut5KsyjZ/0umKyb5kzLpO/2bsCnuLtZK6TgvMxj679dD1wJUi+xC7l2Pnh/IeMHYc4MHBz0/x4JAG4yyDKWuVIWwVZzDlHGitwpSu8xOsVfRW0f0orTt+mwH6MUav6dyv16IYw3EwZi8hFN9jTVqTiiROxknHD9lEr0DNlIqFz/LC+yEK2cy+fC6f07KZcAQoYbF9Cbc0CKHhLsIyopZvF4YXN3cYjHhMdEtuKQX8iVL7vVytNN9fBs+Ub7+3+4+AUrYGrXvXrPvzl/DylTL8BgevQZFbWFJmOSErj76wntoRf8k9MsfBkn01WVluKHO90O3zWE1roXHmsgamcL0DsnC28eElzYxguIlP8upVe2OP03lb63ADc9zuuVS8V/EJ7Z7jedk9FXd6LN+2E227CI7NEyqZa+YYHUmvpUfpS+a1h2aJjqYfmiN0jJ7ZduIS/QT3jPF5iZCO9r0v4CxIduPtD5BhMkomiHqk6+jYyKvZ/a8YLNKt+H0S7bAbMRPl7zaEjzgsA14/rmBLxQzgExm4y54MAvxrTxRkuu2JGfXlGXHu87nmR9/Mi3PfvcemP52ePl+Dewurn4mN2/PjJz+uipXGcSqXZ94Qj86VWO7YQTFTMX8sVcfEwrsF2pys15frdTp54gPX/NcI0joxXnvnQq3mYm83GrcajWfXiic5ypuwe7gsVqYrHSWx0FcQD1QOiAWrD2+gyvMXSNdWzf1EamL2cZLFmgwmoqpdE64WmTA2qlsGrnMJA0JKGKuSy4eGEgaWwS3hApYth+XjtqR2CbNd48fHFeF0MqWUEhuxvqOhlDAX6vb/ElCp6pX9z2S/N6TIf8qKPeSlcjyZjG/ceG0i3ocSOCHObj71Bmmnj8o+j8/naR3CwB7594CqBojTJ9+KSy6ujRHsk90hL6V2WbJtfTRQDIK2TNlS5yj0i3K5U/rW7TeNDkAJVOFXW8Y0LkPbeszPpEVHByn857ydB+xAdHRQqLV5t3VwB8kdpFDSX2Th5L7eQbBWCXIEcz+UjouYe0/7exUBu/cl1IAwfp9yqLN2z6htTQA8L2E4xDVcM9Lg6NndRaGPl6O1NjlDZ8vCjcm6GigH1LuLrfLiXUHupI8fKElGJ/hHpqDd39S8zHuuE4rCzfN3qMK3zrzeOjZZp7PH4DQvlHVp8c4d+Dmwiz6+j9JiRjZv6Xg9DzbDPt+5TkzlH7P8hqoAAAB42mNgZGBgAOI5Ufuj4vltvjLIczCAwCU2hwQE/T+Og4HtLJDLwcAEEgUACxEJCgB42mNgZGBgO/vvLMMODgYGhv//gCRQBAUIAwCOkwV5AHja42CAAKZVDAwsQJrtNpCeCMFMtxm8gJiBg4Ghm82doRYkx7iNgYGdASwmBFMHwkA+AwBxgwmlAAAAAAAAAAAACABWAHgAmgC8ANwBCgFQAcICDAKMAuQDHgNAA2IDyHjaY2BkYGAQZvBg4GAAASYwWQzEagyiICYAEIYBFQAAeNp1kU1OwlAUhc8TNP4kjAwDRx0YoxNEgsYw0mhwrgmOC1YoImKpJk6IC3ARrsA4dAHG+LMCXYRr8OvrowOCaW577rnn3nfuq6SCnpSTyS9I6hIpNlomS/EMmpHDOfgHh/Na1aPDsyrq1eE5ND8OL6qhX4eXtGYOHX5X0Yznf6hs7h3+1Lx5dvhLBfOS4u+cVsybDnSlge4UKVRbHcXytA67wbeisrZUBTVReChTVai+fPVgfN3Q0bGVIfkecU7Whw1Q9MAltXhfUo/Rx3QMOdFnTqBjog3TI4+mKqZx3kRfgyzpDu3JHp5LOJ/WeUT0rdq3Ds+y3Ya6RVGBjdkg2SKyrj3VJ/bxmJbUujAt+JK9tRi2pk2e//Y/hWlm1bHLur1TT/v4bNs737W1CtOqPDXwTvYvtnXBlICzBm7nwO5Xz6ae6BompBYlDv4AFmJmQgAAAHjabY1bDsIgFEQZrAV8G90GPyauwMR9NC0qKV4aHtblK/XXk8zM+RvG2Y8j+8/hGzAOjhkqzFFDQEJhgSVWWGODLXbYi0z2dL5eqqehLDs/ku5sqPNQRjpzS0VUsPfHZNz3ddtQa5xqQvBj1O24Ns7ZIdqoXyYkEQdLZIJqUjKUrKcq+pBUKV0OxGR5kM5Sr807fQBTyi/YeNpj8N7BcCIoYiMjY1/kBsadHAwcDMkFGxlYnTYyMGhBaA4UeicDAwMnMouZwWWjCmNHYMQGh46IjcwpLhvVQLxdHA0MjCwOHckhESAlkUCwkYFHawfj/9YNLL0bmRhcAAfTIrgAAAAAAVXgj+AAAA==) format('woff'); - font-weight: normal; - font-style: normal; -} - -[class^="icon-"]:before, [class*=" icon-"]:before { - font-family: "statuspage"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - /* opacity: .8; */ - - /* For safety - reset parent styles, that can break glyph codes*/ - font-variant: normal; - text-transform: none; - - /* fix buttons height, for twitter bootstrap */ - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - /* remove if not needed */ - margin-left: .2em; - - /* you can be more comfortable with increased icons size */ - /* font-size: 120%; */ - - /* Uncomment for 3D effect */ - /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ -} - -.icon-menu:before { content: '\e800'; } /* '' */ -.icon-down-dir:before { content: '\e801'; } /* '' */ -.icon-up-dir:before { content: '\e802'; } /* '' */ -.icon-left-dir:before { content: '\e803'; } /* '' */ -.icon-right-dir:before { content: '\e804'; } /* '' */ -.icon-ok:before { content: '\e805'; } /* '' */ -.icon-cancel:before { content: '\e807'; } /* '' */ -.icon-arrows-cw:before { content: '\e808'; } /* '' */ -.icon-ellipsis-vert:before { content: '\e809'; } /* '' */ -.icon-spinner:before { content: '\e80a'; } /* '' */ -.icon-attention:before { content: '\e80b'; } /* '' */ -.icon-sort:before { content: '\e80c'; } /* '' */ -.icon-sort-down:before { content: '\e80d'; } /* '' */ -.icon-sort-up:before { content: '\e80e'; } /* '' */ -.icon-link-ext:before { content: '\e80f'; } /* '' */ diff --git a/package/gluon-status-page/src/css/main.css b/package/gluon-status-page/src/css/main.css deleted file mode 100644 index 0604802e..00000000 --- a/package/gluon-status-page/src/css/main.css +++ /dev/null @@ -1,171 +0,0 @@ -@import "reset.css"; -@import "font.css"; -@import "menu.css"; -@import "animation.css"; - -body { - background: rgba(0, 0, 0, 0.12); - font-family: Roboto, Lucida Grande, sans, Arial; - color: rgba(0, 0, 0, 0.87); - font-size: 14px; -} - - -a { - color: rgba(220, 0, 103, 0.87); - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -header { - display: flex; - padding: 0 14px; - background: #dc0067; - color: rgba(255, 255, 255, 0.98); - position: absolute; - top: 0; - width: 100%; - box-sizing: border-box; - height: 20vh; - z-index: -1; - box-shadow: 0px 5px 6px rgba(0, 0, 0, 0.16), 0px 1.5px 3px rgba(0, 0, 0, 0.23); - white-space: nowrap; -} - -header h1, header .icons { - font-size: 24px; - margin: 10px 0; - padding: 6px 0; -} - -header h1 { - text-overflow: ellipsis; - overflow: hidden; - flex: 1; -} - -header h1:hover { - text-decoration: underline; - cursor: pointer; -} - -h1 { - font-weight: bold; -} - -h2, h3 { - font-size: 16px; - color: rgba(0, 0, 0, 0.54); -} - -h2 { - padding: 16px 16px; -} - -h3 { - padding: 16px 16px 8px; -} - -.container { - max-width: 90vw; - margin: 64px auto 24px auto; - background: rgb(253, 253, 253); - box-shadow: 0px 5px 20px rgba(0, 0, 0, 0.19), 0px 3px 6px rgba(0, 0, 0, 0.23); -} - -.container .frame { - box-sizing: border-box; -} - -.vertical-split { - display: flex; -} - -.vertical-split > .frame { - flex: 1; - border-style: solid; - border-color: rgba(0, 0, 0, 0.12); -} - -.vertical-split > .frame + .frame { - border-width: 0 0 0 1px; -} - -dl, pre { - padding: 0 16px 16px; -} - -table { - margin: 0 16px; -} - -dt, th { - font-weight: bold; - color: rgba(0, 0, 0, 0.87); -} - -dt { - margin-bottom: 4px; -} - -th { - text-align: left; - padding: 4px 16px 4px 0; -} - -dd, td { - font-weight: normal; - font-size: 0.9em; - color: rgba(0, 0, 0, 0.54); -} - -dd { - padding-bottom: 16px; -} - -table.datatable { - width: calc(100% - 32px); -} - -table.datatable td { - font-size: 1em; - padding: 4px 0; -} - -table.datatable tr.inactive { - opacity: 0.33; -} - -table.datatable tr.highlight { - background: rgba(255, 180, 0, 0.25); -} - -div.signalgraph { - margin: 16px; -} - -@media only screen and (max-width: 1250px) { - .container { - max-width: none; - margin: 56px 0 0; - } - - header { - height: 56px; - z-index: 1; - position: fixed; - } -} - -@media only screen and (max-width: 700px) { - .vertical-split { - display: block; - } - - .vertical-split > .frame + .frame { - border-width: 1px 0 0 0; - } -} diff --git a/package/gluon-status-page/src/css/menu.css b/package/gluon-status-page/src/css/menu.css deleted file mode 100644 index c865c648..00000000 --- a/package/gluon-status-page/src/css/menu.css +++ /dev/null @@ -1,60 +0,0 @@ -.noscroll { - overflow: hidden; -} - -.menu-background { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - z-index: 10; -} - -.menu { - background: rgba(255, 255, 255, 1); - position: fixed; - z-index: 11; - padding: 8px 0; - box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12), 0 1px 4px rgba(0, 0, 0, 0.24); - overflow-y: auto; - max-height: 80vh; - - transform-origin: top left; - -webkit-animation: new-menu-animation .08s ease-out forwards; - -moz-animation: new-menu-animation .08s ease-out forwards; -} - -@-webkit-keyframes new-menu-animation { - from { - transform: scaleY(0); - } - to { - transform: scaleY(1); - } -} - -@-moz-keyframes new-menu-animation { - from { - transform: scaleY(0); - } - to { - transform: scaleY(1); - } -} - -.menu li { - cursor: pointer; - display: block; - font-size: 16px; - padding: 16px 32px 16px 16px; - color: rgba(0, 0, 0, 0.87); -} - -.menu li:hover { - background: rgba(0, 0, 0, 0.07); -} - -.menu li:active { - background: rgba(0, 0, 0, 0.07); -} diff --git a/package/gluon-status-page/src/css/reset.css b/package/gluon-status-page/src/css/reset.css deleted file mode 100644 index f6ca1484..00000000 --- a/package/gluon-status-page/src/css/reset.css +++ /dev/null @@ -1,86 +0,0 @@ -/* -html5doctor.com Reset Stylesheet v1.6.1 -Last Updated: 2010-09-17 -Author: Richard Clark - http://richclarkdesign.com -*/ -html, body, div, span, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -abbr, address, cite, code, -del, dfn, em, img, ins, kbd, q, samp, -small, strong, sub, sup, var, -b, i, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, figcaption, figure, -footer, header, hgroup, menu, nav, section, summary, -time, mark, audio, video { - margin:0; - padding:0; - border:0; - outline:0; - font-size:100%; - vertical-align:baseline; - background:transparent; -} -body { - line-height:1; -} -article,aside,details,figcaption,figure, -footer,header,hgroup,menu,nav,section { - display:block; -} -nav ul { - list-style:none; -} -blockquote, q { - quotes:none; -} -blockquote:before, blockquote:after, -q:before, q:after { - content:''; - content:none; -} -a { - margin:0; - padding:0; - font-size:100%; - vertical-align:baseline; - background:transparent; -} -/* change colours to suit your needs */ -ins { - background-color:#ff9; - color:#000; - text-decoration:none; -} -/* change colours to suit your needs */ -mark { - background-color:#ff9; - color:#000; - font-style:italic; - font-weight:bold; -} -del { - text-decoration: line-through; -} -abbr[title], dfn[title] { - border-bottom:1px dotted; - cursor:help; -} -table { - border-collapse:collapse; - border-spacing:0; -} -/* change border colour to suit your needs */ -hr { - display:block; - height:1px; - border:0; - border-top:1px solid #cccccc; - margin:1em 0; - padding:0; -} -input, select { - vertical-align:middle; -} diff --git a/package/gluon-status-page/src/index.html.m4 b/package/gluon-status-page/src/index.html.m4 deleted file mode 100644 index 489c1cf0..00000000 --- a/package/gluon-status-page/src/index.html.m4 +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - diff --git a/package/gluon-status-page/src/js/lib/gui.js b/package/gluon-status-page/src/js/lib/gui.js deleted file mode 100644 index 3d771005..00000000 --- a/package/gluon-status-page/src/js/lib/gui.js +++ /dev/null @@ -1,157 +0,0 @@ -"use strict" -define([ "lib/gui/nodeinfo" - , "lib/gui/statistics" - , "lib/gui/neighbours" - , "lib/gui/menu" - , "lib/streams" - , "lib/neighbourstream" - ], function ( NodeInfo - , Statistics - , Neighbours - , Menu - , Streams - , NeighbourStream - ) { - - function VerticalSplit(parent) { - var el = document.createElement("div") - el.className = "vertical-split" - parent.appendChild(el) - - el.push = function (child) { - var header = document.createElement("h2") - header.appendChild(child.title) - - var div = document.createElement("div") - div.className = "frame" - div.node = child - div.appendChild(header) - - el.appendChild(div) - - child.render(div) - - return function () { - div.node.destroy() - el.removeChild(div) - } - } - - el.clear = function () { - while (el.firstChild) { - el.firstChild.node.destroy() - el.removeChild(el.firstChild) - } - } - - return el - } - - var h1 - - return function (mgmtBus, nodesBus) { - function setTitle(node, state) { - var title = node ? node.hostname : "(not connected)" - - document.title = title - h1.textContent = title - - var icon = document.createElement("i") - icon.className = "icon-down-dir" - - h1.appendChild(icon) - - switch (state) { - case "connect": - stateIcon.className = "icon-arrows-cw animate-spin" - break - case "fail": - stateIcon.className = "icon-attention" - break - default: - stateIcon.className = "" - break - } - } - - var nodes = [] - - function nodeMenu() { - var myNodes = nodes.slice() - - myNodes.sort(function (a, b) { - a = a.hostname - b = b.hostname - return (a < b) ? -1 : (a > b) - }) - - var menu = myNodes.map(function (d) { - return [d.hostname, function () { - mgmtBus.pushEvent("goto", d) - }] - }) - - new Menu(menu).apply(this) - } - - var header = document.createElement("header") - h1 = document.createElement("h1") - header.appendChild(h1) - - h1.onclick = nodeMenu - - var icons = document.createElement("p") - icons.className = "icons" - header.appendChild(icons) - - var stateIcon = document.createElement("i") - icons.appendChild(stateIcon) - - document.body.appendChild(header) - - var container = document.createElement("div") - container.className = "container" - - document.body.appendChild(container) - - setTitle() - - var content = new VerticalSplit(container) - - function nodeChanged(nodeInfo) { - setTitle(nodeInfo, "connect") - - content.clear() - content.push(new NodeInfo(nodeInfo)) - } - - function nodeNotArrived(nodeInfo) { - setTitle(nodeInfo, "fail") - } - - function nodeArrived(nodeInfo, ip) { - setTitle(nodeInfo) - - var neighbourStream = new NeighbourStream(mgmtBus, nodesBus, ip) - var statisticsStream = new Streams.Statistics(ip) - - content.push(new Statistics(statisticsStream)) - content.push(new Neighbours(nodeInfo, neighbourStream, mgmtBus)) - } - - function newNodes(d) { - nodes = [] - for (var nodeId in d) - nodes.push(d[nodeId]) - } - - mgmtBus.onEvent({ "goto": nodeChanged - , "arrived": nodeArrived - , "gotoFailed": nodeNotArrived - }) - - nodesBus.map(".nodes").onValue(newNodes) - - return this - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/menu.js b/package/gluon-status-page/src/js/lib/gui/menu.js deleted file mode 100644 index 712f2d0f..00000000 --- a/package/gluon-status-page/src/js/lib/gui/menu.js +++ /dev/null @@ -1,39 +0,0 @@ -"use strict" -define(function () { - return function (menu) { - return function () { - var background = document.createElement("div") - background.className = "menu-background" - document.body.appendChild(background) - document.body.classList.add("noscroll") - - var offset = this.getBoundingClientRect() - var container = document.createElement("ul") - container.className = "menu" - container.style.top = offset.top + "px" - container.style.left = offset.left + "px" - - background.onclick = destroy - - menu.forEach(function (item) { - var li = document.createElement("li") - li.textContent = item[0] - li.action = item[1] - li.onclick = function () { - destroy() - this.action() - } - - container.appendChild(li) - }) - - document.body.appendChild(container) - - function destroy() { - document.body.classList.remove("noscroll") - document.body.removeChild(background) - document.body.removeChild(container) - } - } - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/neighbours.js b/package/gluon-status-page/src/js/lib/gui/neighbours.js deleted file mode 100644 index 56933667..00000000 --- a/package/gluon-status-page/src/js/lib/gui/neighbours.js +++ /dev/null @@ -1,274 +0,0 @@ -"use strict" -define([ "lib/helper", "lib/gui/signalgraph", "lib/gui/signal"], -function (Helper, SignalGraph, Signal) { - - var graphColors = ["#396AB1", "#DA7C30", "#3E9651", "#CC2529", "#535154", "#6B4C9A", "#922428", "#948B3D"] - //graphColors = ["#7293CB", "#E1974C", "#84BA5B", "#D35E60", "#808585", "#9067A7", "#AB6857", "#CCC210"]; - - var inactiveTime = 200 - - function SignalEntry(graph, color, stream) { - var signal = new Signal(color) - var remove = graph.add(signal) - - var unsubscribe = stream.onValue(update) - - this.destroy = function () { - unsubscribe() - remove() - } - - this.getSignal = function () { - return signal - } - - return this - - function update(d) { - if ("wifi" in d) - signal.set(d.wifi.inactive > inactiveTime ? null : d.wifi.signal) - } - } - - function TableEntry(parent, nodeInfo, color, stream, mgmtBus, signal) { - var el = parent.insertRow() - - var tdHostname = el.insertCell() - var tdTQ = el.insertCell() - var tdSignal = el.insertCell() - var tdDistance = el.insertCell() - var tdInactive = el.insertCell() - - var marker = document.createElement("span") - marker.textContent = "⬤ " - marker.style.color = color - tdHostname.appendChild(marker) - - var hostname = document.createElement("span") - tdHostname.appendChild(hostname) - - var infoSet = false - var unsubscribe = stream.onValue(update) - - el.onmouseenter = function () { - el.classList.add("highlight") - signal.setHighlight(true) - } - - el.onmouseleave = function () { - el.classList.remove("highlight") - signal.setHighlight(false) - } - - el.destroy = function () { - unsubscribe() - parent.tBodies[0].removeChild(el) - } - - return el - - function update(d) { - if ("wifi" in d) { - var signal = d.wifi.signal - var inactive = d.wifi.inactive - - el.classList.toggle("inactive", inactive > inactiveTime) - - tdSignal.textContent = signal - tdInactive.textContent = Math.round(inactive / 1000) + " s" - } - - if ("batadv" in d) - tdTQ.textContent = Math.round(d.batadv.tq / 2.55) + " %" - else - tdTQ.textContent = "‒" - - if (infoSet) - return - - if ("nodeInfo" in d) { - infoSet = true - - var link = document.createElement("a") - link.textContent = d.nodeInfo.hostname - link.href = "#" - link.nodeInfo = d.nodeInfo - link.onclick = function () { - mgmtBus.pushEvent("goto", this.nodeInfo) - return false - } - - while (hostname.firstChild) - hostname.removeChild(hostname.firstChild) - - hostname.appendChild(link) - - try { - var distance = Helper.haversine(nodeInfo.location.latitude, nodeInfo.location.longitude, - d.nodeInfo.location.latitude, d.nodeInfo.location.longitude) - - tdDistance.textContent = Math.round(distance * 1000) + " m" - } catch (e) { - tdDistance.textContent = "‒" - } - } else - hostname.textContent = d.id - } - } - - function Interface(parent, nodeInfo, iface, stream, mgmtBus) { - var colors = graphColors.slice(0) - - var el = document.createElement("div") - el.ifname = iface - parent.appendChild(el) - - var h = document.createElement("h3") - h.textContent = iface - el.appendChild(h) - - var table = document.createElement("table") - var tr = table.insertRow() - table.classList.add("datatable") - - var th = document.createElement("th") - th.textContent = "Knoten" - tr.appendChild(th) - - th = document.createElement("th") - th.textContent = "TQ" - tr.appendChild(th) - - th = document.createElement("th") - th.textContent = "dBm" - tr.appendChild(th) - - th = document.createElement("th") - th.textContent = "Entfernung" - tr.appendChild(th) - - th = document.createElement("th") - th.textContent = "Inaktiv" - tr.appendChild(th) - - el.appendChild(table) - - var wrapper = document.createElement("div") - wrapper.className = "signalgraph" - el.appendChild(wrapper) - - var canvas = document.createElement("canvas") - canvas.className = "signal-history" - canvas.height = 200 - wrapper.appendChild(canvas) - - var graph = new SignalGraph(canvas, -100, 0, true) - - var stopStream = stream.skipDuplicates(sameKeys).onValue(update) - - var managedNeighbours = {} - - function update(d) { - var notUpdated = new Set() - var id - - for (id in managedNeighbours) - notUpdated.add(id) - - for (id in d) { - if (!(id in managedNeighbours)) { - var neighbourStream = stream.map("." + id).filter( function (d) { return d !== undefined }) - var color = colors.shift() - var signal = new SignalEntry(graph, color, neighbourStream) - managedNeighbours[id] = { views: [ signal, - new TableEntry(table, nodeInfo, color, neighbourStream, mgmtBus, signal.getSignal()) - ], - color: color - } - } - - notUpdated.delete(id) - } - - notUpdated.forEach(function (id) { - managedNeighbours[id].views.forEach( function (d) { d.destroy() }) - colors.push(managedNeighbours[id].color) - delete managedNeighbours[id] - }) - } - - - el.destroy = function () { - stopStream() - - for (var id in managedNeighbours) - managedNeighbours[id].views.forEach( function (d) { d.destroy() }) - - el.removeChild(h) - el.removeChild(wrapper) - el.removeChild(table) - } - } - - function sameKeys(a, b) { - a = Object.keys(a).sort() - b = Object.keys(b).sort() - - return !(a < b || a > b) - } - - function getter(k) { - return function(obj) { - return obj[k] - } - } - - return function (nodeInfo, stream, mgmtBus) { - var stopStream, div - - function render(el) { - div = document.createElement("div") - el.appendChild(div) - - stopStream = stream.skipDuplicates(sameKeys).onValue(update) - - function update(d) { - var have = {} - var remove = [] - if (div.hasChildNodes()) { - var children = div.childNodes - for (var i = 0; i < children.length; i++) { - var a = children[i] - if (a.ifname in d) - have[a.ifname] = true - else { - a.destroy() - remove.push(a) - } - } - } - - remove.forEach(function (d) { div.removeChild(d) }) - - for (var k in d) { - if (!(k in have)) - new Interface(div, nodeInfo, k, stream.map(getter(k)), mgmtBus) - } - } - } - - function destroy() { - stopStream() - - while (div.firstChild) { - div.firstChild.destroy() - div.removeChild(div.firstChild) - } - } - - return { title: document.createTextNode("Nachbarknoten") - , render: render - , destroy: destroy - } - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/nodeinfo.js b/package/gluon-status-page/src/js/lib/gui/nodeinfo.js deleted file mode 100644 index 75910aae..00000000 --- a/package/gluon-status-page/src/js/lib/gui/nodeinfo.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict" -define(["lib/helper"], function (Helper) { - return function (nodeInfo) { - var el = document.createElement("div") - - update(nodeInfo) - - function dlEntry(dl, dict, key, prettyName) { - var v = Helper.dictGet(dict, key.split(".")) - - if (v === null) - return - - var dt = document.createElement("dt") - var dd = document.createElement("dd") - - dt.textContent = prettyName - if (v instanceof Array) { - var tn = v.map(function (d) { return document.createTextNode(d) }) - tn.forEach(function (node) { - if (dd.hasChildNodes()) - dd.appendChild(document.createElement("br")) - - dd.appendChild(node) - }) - } else - dd.textContent = v - - dl.appendChild(dt) - dl.appendChild(dd) - } - - function update(nodeInfo) { - var list = document.createElement("dl") - - dlEntry(list, nodeInfo, "hostname", "Knotenname") - dlEntry(list, nodeInfo, "owner.contact", "Kontakt") - dlEntry(list, nodeInfo, "hardware.model", "Modell") - dlEntry(list, nodeInfo, "network.mac", "Primäre MAC") - dlEntry(list, nodeInfo, "network.addresses", "IP-Adresse") - dlEntry(list, nodeInfo, "software.firmware.release", "Firmware") - dlEntry(list, nodeInfo, "software.fastd.enabled", "Mesh-VPN") - dlEntry(list, nodeInfo, "software.autoupdater.enabled", "Automatische Updates") - dlEntry(list, nodeInfo, "software.autoupdater.branch", "Branch") - - el.appendChild(list) - } - - return { title: document.createTextNode("Übersicht") - , render: function (d) { d.appendChild(el) } - , destroy: function () {} - } - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/signal.js b/package/gluon-status-page/src/js/lib/gui/signal.js deleted file mode 100644 index d91c63fb..00000000 --- a/package/gluon-status-page/src/js/lib/gui/signal.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict" -define(function () { - return function (color) { - var canvas = document.createElement("canvas") - var ctx = canvas.getContext("2d") - var v = null - var radius = 1.2 - var highlight = false - - function drawPixel(x, y) { - ctx.beginPath() - ctx.fillStyle = color - ctx.arc(x, y, radius, 0, Math.PI * 2, false) - ctx.closePath() - ctx.fill() - } - - this.resize = function (w, h) { - canvas.width = w - canvas.height = h - } - - this.draw = function (x, scale) { - var y = scale(v) - - ctx.clearRect(x, 0, 5, canvas.height) - - if (y) - drawPixel(x, y) - } - - this.canvas = canvas - - this.set = function (d) { - v = d - } - - this.setHighlight = function (d) { - highlight = d - } - - this.getHighlight = function () { - return highlight - } - - return this - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/signalgraph.js b/package/gluon-status-page/src/js/lib/gui/signalgraph.js deleted file mode 100644 index 231ce628..00000000 --- a/package/gluon-status-page/src/js/lib/gui/signalgraph.js +++ /dev/null @@ -1,137 +0,0 @@ -"use strict" -define(function () { - return function (canvas, min, max) { - var i = 0 - var graphWidth - var last = 0 - - var signals = [] - - var ctx = canvas.getContext("2d") - - resize() - - window.addEventListener("resize", resize, false) - window.requestAnimationFrame(step) - - function step(timestamp) { - var delta = timestamp - last - - if (delta > 40) { - draw() - last = timestamp - } - - window.requestAnimationFrame(step) - } - - function drawGrid() { - var gridctx = ctx - var nLines = Math.floor(canvas.height / 40) - gridctx.save() - gridctx.lineWidth = 0.5 - gridctx.strokeStyle = "rgba(0, 0, 0, 0.25)" - gridctx.fillStyle = "rgba(0, 0, 0, 0.5)" - gridctx.textAlign = "end" - gridctx.textBaseline = "bottom" - - gridctx.beginPath() - - for (var i = 0; i < nLines; i++) { - var y = canvas.height - i * 40 - gridctx.moveTo(0, y - 0.5) - gridctx.lineTo(canvas.width, y - 0.5) - var dBm = Math.round(scaleInverse(y, min, max, canvas.height)) + " dBm" - - gridctx.save() - gridctx.strokeStyle = "rgba(255, 255, 255, 0.9)" - gridctx.lineWidth = 4 - gridctx.miterLimit = 2 - gridctx.strokeText(dBm, canvas.width - 5, y - 2.5) - gridctx.fillText(dBm, canvas.width - 5, y - 2.5) - gridctx.restore() - } - - gridctx.stroke() - - gridctx.strokeStyle = "rgba(0, 0, 0, 0.83)" - gridctx.lineWidth = 1.5 - gridctx.strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1) - - gridctx.restore() - } - - function draw() { - var anyHighlight = signals.some( function (d) { return d.getHighlight() }) - - signals.forEach( function (d) { - d.draw(i, function (v) { - return scale(v, min, max, canvas.height) - }) - }) - - ctx.clearRect(0, 0, canvas.width, canvas.height) - - ctx.save() - - signals.forEach( function (d) { - if (anyHighlight) - ctx.globalAlpha = 0.1 - - if (d.getHighlight()) - ctx.globalAlpha = 1 - - ctx.drawImage(d.canvas, 0, 0) - }) - - ctx.restore() - - ctx.save() - ctx.beginPath() - ctx.strokeStyle = "rgba(255, 180, 0, 0.15)" - ctx.lineWidth = 5 - ctx.moveTo(i + 2.5, 0) - ctx.lineTo(i + 2.5, canvas.height) - ctx.stroke() - - drawGrid() - - i = (i + 1) % graphWidth - } - - function scaleInverse(n, min, max, height) { - return (min * n + max * height - max * n) / height - } - - function scale(n, min, max, height) { - return (1 - (n - min) / (max - min)) * height - } - - function resize() { - var newWidth = canvas.parentNode.clientWidth - - if (newWidth === 0 || newWidth === canvas.width) - return - - var lastImage = ctx.getImageData(0, 0, newWidth, canvas.height) - canvas.width = newWidth - graphWidth = canvas.width - ctx.putImageData(lastImage, 0, 0) - - signals.forEach( function (d) { - d.resize(canvas.width, canvas.height) - }) - } - - this.add = function (d) { - signals.push(d) - d.resize(canvas.width, canvas.height) - - return function () { - signals = signals.filter( function (e) { return e !== d } ) - } - } - - return this - } -}) diff --git a/package/gluon-status-page/src/js/lib/gui/statistics.js b/package/gluon-status-page/src/js/lib/gui/statistics.js deleted file mode 100644 index 244a2e96..00000000 --- a/package/gluon-status-page/src/js/lib/gui/statistics.js +++ /dev/null @@ -1,282 +0,0 @@ -"use strict" -define(["lib/helper"], function (Helper) { - function streamElement(type, stream) { - var el = document.createElement(type) - el.destroy = stream.onValue(update) - - function update(d) { - el.textContent = d - } - - return el - } - - function streamNode(stream) { - var el = document.createTextNode("") - el.destroy = stream.onValue(update) - - function update(d) { - el.textContent = d - } - - return el - } - - function mkRow(table, label, stream, sorted) { - - var i = -1 - - if (sorted) { - for (i = 0; i < table.rows.length; i++) { - if (label < table.rows[i].firstChild.textContent) - break - } - } - - var tr = table.insertRow(i) - var th = document.createElement("th") - var td = streamElement("td", stream) - th.textContent = label - tr.appendChild(th) - tr.appendChild(td) - - tr.destroy = function () { - td.destroy() - table.tBodies[0].removeChild(tr) - } - - return tr - } - - function mkTrafficRow(table, children, label, stream, selector) { - var tr = table.insertRow() - var th = document.createElement("th") - th.textContent = label - tr.appendChild(th) - var td = tr.insertCell() - - var traffic = stream.slidingWindow(2, 2) - var pkts = streamNode(traffic.map(deltaUptime(selector + ".packets")).map(prettyPackets)) - var bw = streamNode(traffic.map(deltaUptime(selector + ".bytes")).map(prettyBits)) - var bytes = streamNode(stream.map(selector).map(".bytes").map(prettyBytes)) - - td.appendChild(pkts) - td.appendChild(document.createElement("br")) - td.appendChild(bw) - td.appendChild(document.createElement("br")) - td.appendChild(bytes) - - children.push(pkts) - children.push(bw) - children.push(bytes) - } - - function mkMeshVPN(el, stream) { - var children = {} - var init = false - var h = document.createElement("h3") - h.textContent = "Mesh-VPN" - - var table = document.createElement("table") - - var unsubscribe = stream.onValue( function (d) { - function addPeer(peer, path) { - return { peer: peer, path: path } - } - - function addPeers(d, path) { - if (!("peers" in d)) - return [] - - var peers = [] - - for (var peer in d.peers) - peers.push(addPeer(peer, path + ".peers." + peer)) - - return peers - } - - function addGroup(d, path) { - var peers = [] - - peers = peers.concat(addPeers(d, path)) - - if ("groups" in d) - for (var group in d.groups) - peers = peers.concat(addGroup(d.groups[group], path + ".groups." + group)) - - return peers - } - - if (d === undefined) - clear() - - else { - if (!init) { - init = true - el.appendChild(h) - el.appendChild(table) - } - - var peers = addGroup(d, "") - var paths = new Set(peers.map(function (d) { return d.path } )) - - for (var path in children) - if (!paths.has(path)) { - children[path].destroy() - delete children[path] - } - - peers.forEach( function (peer) { - if (!(peer.path in children)) - children[peer.path] = mkRow(table, peer.peer, - stream.startWith(d) - .map(peer.path) - .filter(function (d) { return d !== undefined }) - .map(prettyPeer), true) - }) - } - }) - - function clear() { - if (init) { - init = false - el.removeChild(h) - el.removeChild(table) - } - - for (var peer in children) - children[peer].destroy() - - children = {} - } - - function destroy() { - unsubscribe() - clear() - } - - return { destroy: destroy } - } - - function deltaUptime(selector) { - return function (d) { - var deltaTime = d[1].uptime - d[0].uptime - var d0 = Helper.dictGet(d[0], selector.split(".").splice(1)) - var d1 = Helper.dictGet(d[1], selector.split(".").splice(1)) - - return (d1 - d0) / deltaTime - } - } - - function prettyPeer(d) { - if (d === null) - return "nicht verbunden" - else - return "verbunden (" + prettyUptime(d.established) + ")" - } - - function prettyPackets(d) { - var v = Helper.formatNumberFixed(d, 0) - return v + " Pakete/s" - } - - function prettyPrefix(prefixes, step, d) { - var prefix = 0 - - while (d > step && prefix < prefixes.length - 1) { - d /= step - prefix++ - } - - d = Helper.formatNumber(d, 3) - return d + " " + prefixes[prefix] - } - - function prettySize(d) { - return prettyPrefix([ "", "k", "M", "G", "T" ], 1024, d) - } - - function prettyBits(d) { - return prettySize(d * 8) + "bps" - } - - function prettyBytes(d) { - return prettySize(d) + "B" - } - - function prettyUptime(seconds) { - var minutes = Math.round(seconds / 60) - - var days = Math.floor(minutes / 1440) - var hours = Math.floor((minutes % 1440) / 60) - minutes = Math.floor(minutes % 60) - - var out = "" - - if (days === 1) - out += "1 Tag, " - else if (days > 1) - out += days + " Tage, " - - out += hours + ":" - - if (minutes < 10) - out += "0" - - out += minutes - - return out - } - - function prettyNVRAM(usage) { - return Helper.formatNumber(usage * 100, 3) + "% belegt" - } - - function prettyLoad(load) { - return Helper.formatNumberFixed(load, 2) - } - - function prettyRAM(memory) { - var usage = 1 - (memory.free + memory.buffers + memory.cached) / memory.total - return prettyNVRAM(usage) - } - - return function (stream) { - var children = [] - var el = document.createElement("div") - var table = document.createElement("table") - - children.push(mkRow(table, "Laufzeit", stream.map(".uptime").map(prettyUptime))) - children.push(mkRow(table, "Systemlast", stream.map(".loadavg").map(prettyLoad))) - children.push(mkRow(table, "RAM", stream.map(".memory").map(prettyRAM))) - children.push(mkRow(table, "NVRAM", stream.map(".rootfs_usage").map(prettyNVRAM))) - children.push(mkRow(table, "Gateway", stream.map(".gateway"))) - children.push(mkRow(table, "Clients", stream.map(".clients.total"))) - - el.appendChild(table) - - var h = document.createElement("h3") - h.textContent = "Traffic" - el.appendChild(h) - - table = document.createElement("table") - - mkTrafficRow(table, children, "Gesendet", stream, ".traffic.tx") - mkTrafficRow(table, children, "Empfangen", stream, ".traffic.rx") - mkTrafficRow(table, children, "Weitergeleitet", stream, ".traffic.forward") - - el.appendChild(table) - - children.push(mkMeshVPN(el, stream.map(".mesh_vpn"))) - - function destroy() { - children.forEach(function (d) {d.destroy()}) - } - - return { title: document.createTextNode("Statistik") - , render: function (d) { d.appendChild(el) } - , destroy: destroy - } - } -}) diff --git a/package/gluon-status-page/src/js/lib/helper.js b/package/gluon-status-page/src/js/lib/helper.js deleted file mode 100644 index c0c0ce2f..00000000 --- a/package/gluon-status-page/src/js/lib/helper.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict" -define([ "bacon" ], function (Bacon) { - function get(url) { - return Bacon.fromBinder(function(sink) { - var req = new XMLHttpRequest() - req.open("GET", url) - - req.onload = function() { - if (req.status === 200) - sink(new Bacon.Next(req.response)) - else - sink(new Bacon.Error(req.statusText)) - sink(new Bacon.End()) - } - - req.onerror = function() { - sink(new Bacon.Error("network error")) - sink(new Bacon.End()) - } - - req.send() - - return function () {} - }) - } - - function getJSON(url) { - return get(url).map(JSON.parse) - } - - function buildUrl(ip, object, param) { - var url = "http://[" + ip + "]/cgi-bin/" + object - if (param) url += "?" + param - - return url - } - - function request(ip, object, param) { - return getJSON(buildUrl(ip, object, param)) - } - - function dictGet(dict, key) { - var k = key.shift() - - if (!(k in dict)) - return null - - if (key.length === 0) - return dict[k] - - return dictGet(dict[k], key) - } - - function localizeNumber(d) { - var sep = ',' - return d.replace('.', sep) - } - - function formatNumberFixed(d, digits) { - return localizeNumber(d.toFixed(digits)) - } - - function formatNumber(d, digits) { - digits-- - - for (var v = d; v >= 10 && digits > 0; v /= 10) - digits-- - - // avoid toPrecision as it might produce strings in exponential notation - return formatNumberFixed(d, digits) - } - - function haversine() { - var radians = Array.prototype.map.call(arguments, function(deg) { return deg / 180.0 * Math.PI }) - var lat1 = radians[0], lon1 = radians[1], lat2 = radians[2], lon2 = radians[3] - var R = 6372.8 // km - var dLat = lat2 - lat1 - var dLon = lon2 - lon1 - var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2) - var c = 2 * Math.asin(Math.sqrt(a)) - return R * c - } - - return { buildUrl: buildUrl - , request: request - , getJSON: getJSON - , dictGet: dictGet - , formatNumber: formatNumber - , formatNumberFixed: formatNumberFixed - , haversine: haversine - } -}) diff --git a/package/gluon-status-page/src/js/lib/neighbourstream.js b/package/gluon-status-page/src/js/lib/neighbourstream.js deleted file mode 100644 index dbe42a34..00000000 --- a/package/gluon-status-page/src/js/lib/neighbourstream.js +++ /dev/null @@ -1,132 +0,0 @@ -"use strict" -define([ "bacon" - , "lib/helper" - , "lib/streams" - ], function(Bacon, Helper, Streams) { - - return function (mgmtBus, nodesBus, ip) { - function nodeQuerier() { - var asked = {} - var timeout = 6000 - - return function (ifname) { - var now = new Date().getTime() - - if (ifname in asked && now - asked[ifname] < timeout) - return Bacon.never() - - asked[ifname] = now - return Streams.nodeInfo(ip, ifname).map(function (d) { - return { "ifname": ifname - , "nodeInfo": d - } - }) - } - } - - var querierAsk = new Bacon.Bus() - var querier = querierAsk.flatMap(nodeQuerier()) - querier.map(".nodeInfo").onValue(mgmtBus, "pushEvent", "nodeinfo") - - function wrapIfname(ifname, d) { - return [ifname, d] - } - - function extractIfname(d) { - var r = {} - - for (var station in d) { - var ifname = d[station].ifname - delete d[station].ifname - - if (!(ifname in r)) - r[ifname] = {} - - r[ifname][station] = d[station] - } - - return r - } - - function stationsStream(ifname) { - return new Streams.Stations(ip, ifname).map(wrapIfname, ifname) - } - - function magic(interfaces) { - var ifnames = Object.keys(interfaces) - ifnames.forEach(querierAsk.push) - - var wifiStream = Bacon.fromArray(ifnames) - .flatMap(stationsStream) - .scan({}, function (a, b) { - a[b[0]] = b[1] - return a - }) - - var batadvStream = new Streams.Batadv(ip).toProperty({}) - - return Bacon.combineWith(combine, wifiStream - , batadvStream.map(extractIfname) - , nodesBus.map(".macs") - ) - } - - function combine(wifi, batadv, macs) { - var interfaces = combineWithIfnames(wifi, batadv) - - for (var ifname in interfaces) { - var stations = interfaces[ifname] - for (var station in stations) { - stations[station].id = station - - if (station in macs) - stations[station].nodeInfo = macs[station] - else - querierAsk.push(ifname) - } - } - - return interfaces - } - - function combineWithIfnames(wifi, batadv) { - var ifnames = Object.keys(wifi).concat(Object.keys(batadv)) - - // remove duplicates - ifnames.filter(function(e, i) { - return ifnames.indexOf(e) === i - }) - - var out = {} - - ifnames.forEach(function (ifname) { - out[ifname] = combineWifiBatadv(wifi[ifname], batadv[ifname]) - }) - - return out - } - - function combineWifiBatadv(wifi, batadv) { - var station - var out = {} - - for (station in batadv) { - if (!(station in out)) - out[station] = {} - - out[station].batadv = batadv[station] - } - - for (station in wifi) { - if (!(station in out)) - out[station] = {} - - out[station].wifi = wifi[station] - } - - return out - } - - return Helper.request(ip, "interfaces").flatMap(magic) - } -}) diff --git a/package/gluon-status-page/src/js/lib/streams.js b/package/gluon-status-page/src/js/lib/streams.js deleted file mode 100644 index 68667cb2..00000000 --- a/package/gluon-status-page/src/js/lib/streams.js +++ /dev/null @@ -1,66 +0,0 @@ -"use strict" -define(["bacon", "lib/helper"], function(Bacon, Helper) { - function nodeInfo(ip, ifname) { - return Bacon.fromBinder(function (sink) { - var url = Helper.buildUrl(ip, "dyn/neighbours-nodeinfo", ifname) - var evtSource = new EventSource(url) - - evtSource.addEventListener("neighbour", function(e) { - var r = sink(new Bacon.Next(JSON.parse(e.data))) - - if (r === Bacon.noMore) - tearDown() - }, false) - - evtSource.addEventListener("eot", function() { - evtSource.close() - sink(new Bacon.End()) - }, false) - - function tearDown() { - evtSource.close() - } - - return tearDown - }) - } - - function simpleStream(url) { - return Bacon.fromBinder(function (sink) { - var evtSource = new EventSource(url) - - evtSource.onmessage = function (e) { - var r = sink(new Bacon.Next(JSON.parse(e.data))) - if (r === Bacon.noMore) - tearDown() - } - - function tearDown() { - evtSource.close() - } - - return tearDown - }) - } - - function batadv(ip) { - var url = Helper.buildUrl(ip, "dyn/neighbours-batadv") - return simpleStream(url) - } - - function stations(ip, ifname) { - var url = Helper.buildUrl(ip, "dyn/stations", ifname) - return simpleStream(url) - } - - function statistics(ip) { - var url = Helper.buildUrl(ip, "dyn/statistics") - return simpleStream(url).skipDuplicates(function (a, b) {return (a.uptime === b.uptime)}) - } - - return { nodeInfo: nodeInfo - , Batadv: batadv - , Stations: stations - , Statistics: statistics - } -}) diff --git a/package/gluon-status-page/src/js/main.js b/package/gluon-status-page/src/js/main.js deleted file mode 100644 index 3bdbe2a0..00000000 --- a/package/gluon-status-page/src/js/main.js +++ /dev/null @@ -1,108 +0,0 @@ -"use strict" -require([ "bacon" - , "lib/helper" - , "lib/streams" - , "lib/gui" - ], function(Bacon, Helper, Streams, GUI) { - - var mgmtBus = new Bacon.Bus() - - mgmtBus.pushEvent = function (key, a) { - var v = [key].concat(a) - return this.push(v) - } - - mgmtBus.onEvent = function (events) { - return this.onValue(function (e) { - var d = e.slice() // shallow copy so calling shift doesn't change it - var ev = d.shift() - if (ev in events) - events[ev].apply(this, d) - }) - } - - var nodesBusIn = new Bacon.Bus() - - var nodesBus = nodesBusIn.scan({ "nodes": {} - , "macs": {} - }, scanNodeInfo) - - new GUI(mgmtBus, nodesBus) - - mgmtBus.onEvent({ "goto": gotoNode - , "nodeinfo": function (d) { nodesBusIn.push(d) } - }) - - function tryIp(ip) { - return Helper.request(ip, "nodeinfo").map(function () { return ip }) - } - - var gotoEpoch = 0 - - function onEpoch(epoch, f) { - return function (d) { - if (epoch === gotoEpoch) - return f(d) - } - } - - function gotoNode(nodeInfo) { - gotoEpoch++ - - var addresses = nodeInfo.network.addresses.filter(function (d) { return !/^fe80:/.test(d) }) - var race = Bacon.fromArray(addresses).flatMap(tryIp).withStateMachine([], function (acc, ev) { - if (ev.isError()) - return [acc.concat(ev.error), []] - else if (ev.isEnd() && acc.length > 0) - return [undefined, [new Bacon.Error(acc), ev]] - else if (ev.hasValue()) - return [[], [ev, new Bacon.End()]] - }) - - race.onValue(onEpoch(gotoEpoch, function (d) { - mgmtBus.pushEvent("arrived", [nodeInfo, d]) - })) - - race.onError(onEpoch(gotoEpoch, function () { - mgmtBus.pushEvent("gotoFailed", nodeInfo) - })) - } - - function scanNodeInfo(a, nodeInfo) { - a.nodes[nodeInfo.node_id] = nodeInfo - - var mesh = Helper.dictGet(nodeInfo, ["network", "mesh"]) - - if (mesh) - for (var m in mesh) - for (var ifname in mesh[m].interfaces) - mesh[m].interfaces[ifname].forEach( function (d) { - a.macs[d] = nodeInfo - }) - - return a - } - - if (localStorage.nodes) - JSON.parse(localStorage.nodes).forEach(nodesBusIn.push) - - nodesBus.map(".nodes").onValue(function (nodes) { - var out = [] - - for (var k in nodes) - out.push(nodes[k]) - - localStorage.nodes = JSON.stringify(out) - }) - - var bootstrap = Helper.getJSON(bootstrapUrl) - - bootstrap.onError(function () { - console.log("FIXME bootstrapping failed") - }) - - bootstrap.onValue(function (d) { - mgmtBus.pushEvent("nodeinfo", d) - mgmtBus.pushEvent("goto", d) - }) -}) diff --git a/package/gluon-status-page-api/src/stations.c b/package/gluon-status-page/src/stations.c similarity index 100% rename from package/gluon-status-page-api/src/stations.c rename to package/gluon-status-page/src/stations.c diff --git a/package/gluon-wan-dnsmasq/Makefile b/package/gluon-wan-dnsmasq/Makefile index 3722210f..adbe0f78 100644 --- a/package/gluon-wan-dnsmasq/Makefile +++ b/package/gluon-wan-dnsmasq/Makefile @@ -3,33 +3,15 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-wan-dnsmasq PKG_VERSION:=1 -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk +include ../gluon.mk define Package/gluon-wan-dnsmasq - SECTION:=gluon - CATEGORY:=Gluon TITLE:=Support for a secondary DNS server using the WAN interface - DEPENDS:=+gluon-core +dnsmasq +libpacketmark + DEPENDS:=+gluon-core +libubus-lua +dnsmasq +libpacketmark endef define Package/gluon-wan-dnsmasq/description Gluon community wifi mesh firmware framework: Support for a secondary DNS server using the WAN interface endef -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) -endef - -define Build/Configure -endef - -define Build/Compile -endef - -define Package/gluon-wan-dnsmasq/install - $(CP) ./files/* $(1)/ -endef - -$(eval $(call BuildPackage,gluon-wan-dnsmasq)) +$(eval $(call BuildPackageGluon,gluon-wan-dnsmasq)) diff --git a/package/gluon-wan-dnsmasq/files/lib/gluon/wan-dnsmasq/update.lua b/package/gluon-wan-dnsmasq/luasrc/lib/gluon/wan-dnsmasq/update.lua similarity index 59% rename from package/gluon-wan-dnsmasq/files/lib/gluon/wan-dnsmasq/update.lua rename to package/gluon-wan-dnsmasq/luasrc/lib/gluon/wan-dnsmasq/update.lua index 88a86507..d1a3d99e 100755 --- a/package/gluon-wan-dnsmasq/files/lib/gluon/wan-dnsmasq/update.lua +++ b/package/gluon-wan-dnsmasq/luasrc/lib/gluon/wan-dnsmasq/update.lua @@ -5,28 +5,41 @@ local RESOLV_CONF = RESOLV_CONF_DIR .. '/resolv.conf' local ubus = require('ubus').connect() -local uci = require('luci.model.uci').cursor() +local uci = require('simple-uci').cursor() local fs = require 'nixio.fs' local new_servers = '' +local function append_server(server) + new_servers = new_servers .. 'nameserver ' .. server .. '\n' +end + + +local function handle_interface(status) + local ifname = status.device + local servers = status.inactive['dns-server'] -local function append_servers(servers) for _, server in ipairs(servers) do - new_servers = new_servers .. 'nameserver ' .. server .. '\n' + if server:match('^fe80:') then + append_server(server .. '%' .. ifname) + else + append_server(server) + end end end local function append_interface_servers(iface) - append_servers(ubus:call('network.interface.' .. iface, 'status', {}).inactive['dns-server']) + handle_interface(ubus:call('network.interface.' .. iface, 'status', {})) end local static = uci:get_first('gluon-wan-dnsmasq', 'static', 'server') if type(static) == 'table' and #static > 0 then - append_servers(static) + for _, server in ipairs(static) do + append_server(server) + end else pcall(append_interface_servers, 'wan6') pcall(append_interface_servers, 'wan') diff --git a/package/gluon-web-admin/Makefile b/package/gluon-web-admin/Makefile new file mode 100644 index 00000000..d555be61 --- /dev/null +++ b/package/gluon-web-admin/Makefile @@ -0,0 +1,17 @@ +# Copyright (C) 2013 Nils Schneider +# This is free software, licensed under the Apache 2.0 license. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-admin +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-admin + TITLE:=Web-based simple administration interface for mesh nodes + DEPENDS:=+gluon-config-mode-core +pretty-hostname +endef + +$(eval $(call BuildPackageGluon,gluon-web-admin)) diff --git a/package/gluon-web-admin/check_site.lua b/package/gluon-web-admin/check_site.lua new file mode 100644 index 00000000..4f307e5a --- /dev/null +++ b/package/gluon-web-admin/check_site.lua @@ -0,0 +1,2 @@ +need_boolean(in_site({'config_mode', 'remote_login', 'show_password_form'}), false) +need_number(in_site({'config_mode', 'remote_login', 'min_password_length'}), false) diff --git a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html new file mode 100644 index 00000000..7e060f57 --- /dev/null +++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/info.html @@ -0,0 +1,38 @@ +<%- + local fs = require 'nixio.fs' + local uci = require('simple-uci').cursor() + local pretty_hostname = require 'pretty_hostname' + + local site = require 'gluon.site' + local sysconfig = require 'gluon.sysconfig' + local platform = require 'gluon.platform' + local util = require "gluon.util" + + local _ = translate + + + local pubkey + local meshvpn_enabled = uci:get_bool("fastd", "mesh_vpn", "enabled") + if meshvpn_enabled then + pubkey = util.trim(util.exec('/etc/init.d/fastd show_key mesh_vpn')) + if pubkey == '' then + pubkey = nil + end + end + + local values = { + { _('Hostname'), pretty_hostname.get(uci) }, + { _('MAC address'), sysconfig.primary_mac }, + { _('Hardware model'), platform.get_model() }, + { _('Gluon version'), util.trim(fs.readfile('/lib/gluon/gluon-version')) }, + { _('Firmware release'), util.trim(fs.readfile('/lib/gluon/release')) }, + { _('Site'), site.site_name() }, + { _('Public VPN key'), pubkey }, + } +-%> +

<%:Information%>

+<% for _, v in ipairs(values) do %> +
+
<%|v[1]%>
<%|v[2] or 'n/a'%>
+
+<% end %> diff --git a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade.html b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade.html new file mode 100644 index 00000000..456b9e5c --- /dev/null +++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade.html @@ -0,0 +1,50 @@ +<%# +Copyright 2008 Steven Barth +Copyright 2008-2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +

<%:Upgrade firmware%>

+ +
+

+ <%:You can manually upgrade your firmware here.%> +

+ <% if bad_image then %> +

<%:The provided firmware image is not valid for this device.%>

+ <% end %> +
+
+ +
+ +
+
+ +
+ + +
+ + +
+
+
+ +
+ + + +
+
diff --git a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_confirm.htm b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_confirm.html similarity index 64% rename from package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_confirm.htm rename to package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_confirm.html index 5618728f..92c25a63 100644 --- a/package/gluon-luci-admin/files/usr/lib/lua/luci/view/admin/upgrade_confirm.htm +++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_confirm.html @@ -1,5 +1,4 @@ <%# -LuCI - Lua Configuration Interface Copyright 2008 Steven Barth Copyright 2008-2009 Jo-Philipp Wich @@ -8,17 +7,12 @@ you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - -%> -<%+header%> -

<%:Upgrade firmware%>

- <%:The firmware image has been transmitted. Please ensure the MD5 checksum and image size are correct and click "continue".%> + <%:The firmware image has been transmitted. Please ensure the SHA-256 checksum and image size are correct and click "continue".%>

<% if flashsize > 0 and filesize > flashsize then %> @@ -27,7 +21,7 @@ $Id$

    -
  • md5sum: <%=checksum%>
  • +
  • sha256sum: <%=checksum%>
  • <%:Size%>: <% function byte_format(byte) local suff = {"B", "KB", "MB", "GB", "TB"} @@ -43,25 +37,25 @@ $Id$ write(byte_format(filesize)) if flashsize > 0 then - write(luci.i18n.translatef( + write(translatef( " (%s available)", - w.byte_format(flashsize) + byte_format(flashsize) )) end %>

-
-
+
+ " /> - + + -
+ " /> - + +
-<%+footer%> - diff --git a/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_reboot.html b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_reboot.html new file mode 100644 index 00000000..44f0e3cc --- /dev/null +++ b/package/gluon-web-admin/files/lib/gluon/config-mode/view/admin/upgrade_reboot.html @@ -0,0 +1,5 @@ +

+ <%:The firmware is currently being upgraded.%> + <%:Don't switch off the device in any circumstance!%> + <%:The upgrade will take a few minutes. When it is finished, your node will reboot automatically.%> +

diff --git a/package/gluon-luci-admin/i18n/de.po b/package/gluon-web-admin/i18n/de.po similarity index 81% rename from package/gluon-luci-admin/i18n/de.po rename to package/gluon-web-admin/i18n/de.po index ec109ae0..95c27e5f 100644 --- a/package/gluon-luci-admin/i18n/de.po +++ b/package/gluon-web-admin/i18n/de.po @@ -10,8 +10,14 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +msgid "(%s available)" +msgstr "(%s verfügbar)" + +msgid "Advanced settings" +msgstr "Erweiterte Einstellungen" + msgid "" -"Alternatively, you can set a password to access you node. Please choose a " +"Alternatively, you can set a password to access your node. Please choose a " "secure password you don't use anywhere else.

If you set an empty " "password, login via password will be disabled. This is the default." msgstr "" @@ -20,15 +26,21 @@ msgstr "" "leeren Passworts wird der Login per Passwort gesperrt (dies ist die Standard-" "Einstellung)." +msgid "Cancel" +msgstr "Abbrechen" + +msgid "Confirmation" +msgstr "Bestätigung" + +msgid "%u characters min." +msgstr "Mindestens %u Zeichen" + msgid "Continue" msgstr "Fortfahren" msgid "Don't switch off the device in any circumstance!" msgstr "Unterbrich auf keinen Fall die Stromversorgung!" -msgid "Expert Mode" -msgstr "Expert Mode" - msgid "Firmware image" msgstr "Firmware-Datei" @@ -41,12 +53,21 @@ msgstr "Gluon-Version" msgid "Hardware model" msgstr "Hardware-Modell" +msgid "Hostname" +msgstr "Hostname" + msgid "Information" msgstr "Info" +msgid "Keep settings" +msgstr "Konfiguration behalten" + msgid "MAC address" msgstr "MAC-Adresse" +msgid "Password" +msgstr "Passwort" + msgid "Password changed." msgstr "Passwort geändert." @@ -65,11 +86,14 @@ msgstr "SSH-Schlüssel" msgid "Site" msgstr "Site" +msgid "Size" +msgstr "Größe" + msgid "" -"The firmware image has been transmitted. Please ensure the MD5 checksum and " +"The firmware image has been transmitted. Please ensure the SHA-256 checksum and " "image size are correct and click \"continue\"." msgstr "" -"Die Firmwaredatei wurde übermittelt. Bitte vergleiche MD5-Checksumme und " +"Die Firmwaredatei wurde übermittelt. Bitte vergleiche SHA-256-Checksumme und " "Dateigröße und klicke anschließend auf \"fortfahren\"." msgid "The firmware is currently being upgraded." @@ -97,9 +121,6 @@ msgstr "Das Passwort konnte nicht geändert werden." msgid "Upgrade firmware" msgstr "Firmware aktualisieren" -msgid "Upgrading firmware" -msgstr "Firmware wird aktualisiert" - msgid "Upload image" msgstr "Datei hochladen" diff --git a/package/gluon-luci-admin/i18n/fr.po b/package/gluon-web-admin/i18n/fr.po similarity index 72% rename from package/gluon-luci-admin/i18n/fr.po rename to package/gluon-web-admin/i18n/fr.po index 23eeb7ff..2e6b8739 100644 --- a/package/gluon-luci-admin/i18n/fr.po +++ b/package/gluon-web-admin/i18n/fr.po @@ -1,24 +1,40 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-08-19 20:20+0100\n" "Last-Translator: Bernot Tobias \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +msgid "(%s available)" +msgstr "" + +msgid "Advanced settings" +msgstr "Paramètres avancés" + msgid "" -"Alternatively, you can set a password to access you node. Please choose a " +"Alternatively, you can set a password to access your node. Please choose a " "secure password you don't use anywhere else.

If you set an empty " "password, login via password will be disabled. This is the default." msgstr "" -"Alternativement, vous pouvez mettre un mot de passe pour accéder à votre nœud, " -"Penseiz à choisir un mot de passe sûr, que vous n'utilisez nulle part ailleurs. " -"

Si vous n'entrez pas de mot de passe, la connexion par mot de passe " -"sera désactivée. La connexion par mot de passe est désactivée par défaut." +"Alternativement, vous pouvez mettre un mot de passe pour accéder à votre " +"nœud, Penseiz à choisir un mot de passe sûr, que vous n'utilisez nulle part " +"ailleurs.

Si vous n'entrez pas de mot de passe, la connexion " +"par mot de passe sera désactivée. La connexion par mot de passe est " +"désactivée par défaut." + +msgid "Cancel" +msgstr "Annuler" + +msgid "Confirmation" +msgstr "Confirmation" + +msgid "%u characters min." +msgstr "Au moins %u caractères" msgid "Continue" msgstr "Continuer" @@ -26,9 +42,6 @@ msgstr "Continuer" msgid "Don't switch off the device in any circumstance!" msgstr "N'interrompez en aucun cas l'alimentation!" -msgid "Expert Mode" -msgstr "Mode Expert" - msgid "Firmware image" msgstr "Fichier image" @@ -41,12 +54,21 @@ msgstr "Version de Gluon" msgid "Hardware model" msgstr "Modèle du Matériel" +msgid "Hostname" +msgstr "Nom d'hôte" + msgid "Information" msgstr "Informations" +msgid "Keep settings" +msgstr "Garder le paramètrage" + msgid "MAC address" msgstr "Adresse MAC" +msgid "Password" +msgstr "Mot de passe" + msgid "Password changed." msgstr "Mot de passe changé." @@ -65,11 +87,14 @@ msgstr "Clé SSH" msgid "Site" msgstr "Site" +msgid "Size" +msgstr "Taille" + msgid "" -"The firmware image has been transmitted. Please ensure the MD5 checksum and " +"The firmware image has been transmitted. Please ensure the SHA-256 checksum and " "image size are correct and click \"continue\"." msgstr "" -"L'image de firmware a été transmise. Vérifiez que la somme MD5 et la taille " +"L'image de firmware a été transmise. Vérifiez que la somme SHA-256 et la taille " "de l'image correspondent, et appuiez ensuite sur \"continuer\"." msgid "The firmware is currently being upgraded." @@ -88,8 +113,8 @@ msgid "" "The upgrade will take a few minutes. When it is finished, your node will " "reboot automatically." msgstr "" -"La mise à jour va prendre quelques minutes. Quand elle sera finie, " -"votre nœud va redémarrer automatiquement." +"La mise à jour va prendre quelques minutes. Quand elle sera finie, votre " +"nœud va redémarrer automatiquement." msgid "Unable to change the password." msgstr "Le mot de passe n'a pas pu être changé." @@ -97,9 +122,6 @@ msgstr "Le mot de passe n'a pas pu être changé." msgid "Upgrade firmware" msgstr "Mettre à jour la firmware" -msgid "Upgrading firmware" -msgstr "Mise à jour de la firmware" - msgid "Upload image" msgstr "Transférer l'image" diff --git a/package/gluon-luci-admin/i18n/gluon-luci-admin.pot b/package/gluon-web-admin/i18n/gluon-web-admin.pot similarity index 77% rename from package/gluon-luci-admin/i18n/gluon-luci-admin.pot rename to package/gluon-web-admin/i18n/gluon-web-admin.pot index 197b6367..ce44d56b 100644 --- a/package/gluon-luci-admin/i18n/gluon-luci-admin.pot +++ b/package/gluon-web-admin/i18n/gluon-web-admin.pot @@ -1,21 +1,33 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" +msgid "(%s available)" +msgstr "" + +msgid "Advanced settings" +msgstr "" + msgid "" -"Alternatively, you can set a password to access you node. Please choose a " +"Alternatively, you can set a password to access your node. Please choose a " "secure password you don't use anywhere else.

If you set an empty " "password, login via password will be disabled. This is the default." msgstr "" +msgid "Cancel" +msgstr "" + +msgid "Confirmation" +msgstr "" + +msgid "%u characters min." +msgstr "" + msgid "Continue" msgstr "" msgid "Don't switch off the device in any circumstance!" msgstr "" -msgid "Expert Mode" -msgstr "" - msgid "Firmware image" msgstr "" @@ -28,12 +40,21 @@ msgstr "" msgid "Hardware model" msgstr "" +msgid "Hostname" +msgstr "" + msgid "Information" msgstr "" +msgid "Keep settings" +msgstr "" + msgid "MAC address" msgstr "" +msgid "Password" +msgstr "" + msgid "Password changed." msgstr "" @@ -52,8 +73,11 @@ msgstr "" msgid "Site" msgstr "" +msgid "Size" +msgstr "" + msgid "" -"The firmware image has been transmitted. Please ensure the MD5 checksum and " +"The firmware image has been transmitted. Please ensure the SHA-256 checksum and " "image size are correct and click \"continue\"." msgstr "" @@ -80,9 +104,6 @@ msgstr "" msgid "Upgrade firmware" msgstr "" -msgid "Upgrading firmware" -msgstr "" - msgid "Upload image" msgstr "" diff --git a/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/index.lua b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/index.lua new file mode 100644 index 00000000..99025c95 --- /dev/null +++ b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/index.lua @@ -0,0 +1,12 @@ +package 'gluon-web-admin' + + +local root = node() +if not root.target then + root.target = alias("admin") +end + +entry({"admin"}, alias("admin", "info"), _("Advanced settings"), 10) + +entry({"admin", "info"}, template("admin/info"), _("Information"), 1) +entry({"admin", "remote"}, model("admin/remote"), _("Remote access"), 10) diff --git a/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/upgrade.lua b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/upgrade.lua new file mode 100644 index 00000000..42f5be48 --- /dev/null +++ b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/controller/admin/upgrade.lua @@ -0,0 +1,139 @@ +--[[ +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +package 'gluon-web-admin' + + +local util = require 'gluon.util' +local fs = require 'nixio.fs' + +local tmpfile = "/tmp/firmware.img" + + +local function filehandler(meta, chunk, eof) + if not fs.access(tmpfile) and not file and chunk and #chunk > 0 then + file = io.open(tmpfile, "w") + end + if file and chunk then + file:write(chunk) + end + if file and eof then + file:close() + end +end + +local function action_upgrade(http, renderer) + local nixio = require 'nixio' + + local function fork_exec(...) + local pid = nixio.fork() + if pid > 0 then + return + elseif pid == 0 then + -- change to root dir + nixio.chdir("/") + + -- patch stdin, out, err to /dev/null + local null = nixio.open("/dev/null", "w+") + if null then + nixio.dup(null, nixio.stderr) + nixio.dup(null, nixio.stdout) + nixio.dup(null, nixio.stdin) + if null:fileno() > 2 then + null:close() + end + end + + -- Sleep a little so the browser can fetch everything required to + -- display the reboot page, then reboot the device. + nixio.nanosleep(1) + + -- replace with target command + nixio.exec(...) + end + end + + local function image_supported(tmpfile) + return (os.execute(string.format("exec /sbin/sysupgrade -T %q >/dev/null", tmpfile)) == 0) + end + + local function storage_size() + local size = 0 + if fs.access("/proc/mtd") then + for l in io.lines("/proc/mtd") do + local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"') + if n == "linux" then + size = tonumber(s, 16) + break + end + end + elseif fs.access("/proc/partitions") then + for l in io.lines("/proc/partitions") do + local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)') + if b and n and not n:match('[0-9]') then + size = tonumber(b) * 1024 + break + end + end + end + return size + end + + local function image_checksum(tmpfile) + return (util.exec(string.format("exec sha256sum %q", tmpfile)):match("^([^%s]+)")) + end + + + -- Determine state + local step = tonumber(http:getenv("REQUEST_METHOD") == "POST" and http:formvalue("step")) or 1 + + local has_image = fs.access(tmpfile) + local has_support = has_image and image_supported(tmpfile) + + -- Step 1: file upload, error on unsupported image format + if step == 1 or not has_support then + -- If there is an image but user has requested step 1 + -- or type is not supported, then remove it. + if has_image then + fs.unlink(tmpfile) + end + + renderer.render_layout('admin/upgrade', { + bad_image = has_image and not has_support, + }, 'gluon-web-admin') + + -- Step 2: present uploaded file, show checksum, confirmation + elseif step == 2 then + renderer.render_layout('admin/upgrade_confirm', { + checksum = image_checksum(tmpfile), + filesize = fs.stat(tmpfile).size, + flashsize = storage_size(), + keepconfig = (http:formvalue("keepcfg") == "1"), + }, 'gluon-web-admin') + + elseif step == 3 then + if http:formvalue("keepcfg") == "1" then + fork_exec("/sbin/sysupgrade", tmpfile) + else + fork_exec("/sbin/sysupgrade", "-n", tmpfile) + end + renderer.render_layout('admin/upgrade_reboot', nil, 'gluon-web-admin', { + hidenav = true, + }) + end +end + + +local has_platform = fs.access("/lib/upgrade/platform.sh") +if has_platform then + local upgrade = entry({"admin", "upgrade"}, call(action_upgrade), _("Upgrade firmware"), 90) + upgrade.filehandler = filehandler +end diff --git a/package/gluon-web-admin/luasrc/lib/gluon/config-mode/model/admin/remote.lua b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/model/admin/remote.lua new file mode 100644 index 00000000..52c29ab0 --- /dev/null +++ b/package/gluon-web-admin/luasrc/lib/gluon/config-mode/model/admin/remote.lua @@ -0,0 +1,127 @@ +--[[ +Copyright 2008 Steven Barth +Copyright 2011 Jo-Philipp Wich +Copyright 2013 Nils Schneider + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +local nixio = require "nixio" +local fs = require "nixio.fs" +local util = require "gluon.util" +local site = require "gluon.site" + +local f_keys = Form(translate("SSH keys"), translate("You can provide your SSH keys here (one per line):"), 'keys') +local s = f_keys:section(Section) +local keys = s:option(TextValue, "keys") +keys.wrap = "off" +keys.rows = 5 +keys.default = fs.readfile("/etc/dropbear/authorized_keys") or "" + +function keys:write(value) + value = util.trim(value:gsub("\r", "")) + if value ~= "" then + fs.writefile("/etc/dropbear/authorized_keys", value .. "\n") + else + fs.remove("/etc/dropbear/authorized_keys") + end +end + +local config = site.config_mode.remote_login +if not config.show_password_form(false) then + -- password login is disabled in site.conf + return f_keys +end + +local min_password_length = config.min_password_length(12) +local mintype = 'minlength(' .. min_password_length .. ')' +local length_hint + +if min_password_length > 1 then + length_hint = translatef("%u characters min.", min_password_length) +end + +local f_password = Form(translate("Password"), translate( + "Alternatively, you can set a password to access your node. Please choose a " + .. "secure password you don't use anywhere else.

If you set an empty " + .. "password, login via password will be disabled. This is the default." + ), 'password' +) +f_password.reset = false + +local s = f_password:section(Section) + +local pw1 = s:option(Value, "pw1", translate("Password")) +pw1.password = true +pw1.optional = true +pw1.datatype = mintype +function pw1.cfgvalue() + return '' +end + +local pw2 = s:option(Value, "pw2", translate("Confirmation"), length_hint) +pw2.password = true +pw2.optional = true +pw2.datatype = mintype +function pw2.cfgvalue() + return '' +end + +local function set_password(password) + local inr, inw = nixio.pipe() + local pid = nixio.fork() + + if pid < 0 then + return false + elseif pid == 0 then + inw:close() + + local null = nixio.open('/dev/null', 'w') + nixio.dup(null, nixio.stderr) + nixio.dup(null, nixio.stdout) + if null:fileno() > 2 then + null:close() + end + + nixio.dup(inr, nixio.stdin) + inr:close() + + nixio.execp('passwd') + os.exit(127) + end + + inr:close() + + inw:write(string.format('%s\n%s\n', password, password)) + inw:close() + + local wpid, status, code = nixio.waitpid(pid) + return wpid and status == 'exited' and code == 0 +end + +function f_password:write() + if pw1.data ~= pw2.data then + f_password.errmessage = translate("The password and the confirmation differ.") + return + end + + local pw = pw1.data + + if pw ~= nil and #pw > 0 then + if set_password(pw) then + f_password.message = translate("Password changed.") + else + f_password.errmessage = translate("Unable to change the password.") + end + else + -- We don't check the return code here as the error 'password for root is already locked' is normal... + os.execute('passwd -l root >/dev/null') + f_password.message = translate("Password removed.") + end +end + +return f_keys, f_password diff --git a/package/gluon-web-autoupdater/Makefile b/package/gluon-web-autoupdater/Makefile new file mode 100644 index 00000000..c50e731a --- /dev/null +++ b/package/gluon-web-autoupdater/Makefile @@ -0,0 +1,17 @@ +# Copyright (C) 2013 Nils Schneider +# This is free software, licensed under the Apache 2.0 license. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-autoupdater +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-autoupdater + TITLE:=gluon-web module for gluon-autoupdater + DEPENDS:=+gluon-web-admin +gluon-autoupdater +endef + +$(eval $(call BuildPackageGluon,gluon-web-autoupdater)) diff --git a/package/gluon-luci-autoupdater/i18n/de.po b/package/gluon-web-autoupdater/i18n/de.po similarity index 92% rename from package/gluon-luci-autoupdater/i18n/de.po rename to package/gluon-web-autoupdater/i18n/de.po index 9fd4cf53..9f1fbecf 100644 --- a/package/gluon-luci-autoupdater/i18n/de.po +++ b/package/gluon-web-autoupdater/i18n/de.po @@ -1,12 +1,12 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-05-04 01:55+0200\n" "Last-Translator: \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -15,3 +15,6 @@ msgstr "Automatische Updates" msgid "Branch" msgstr "Branch" + +msgid "Enable" +msgstr "Aktivieren" diff --git a/package/gluon-luci-autoupdater/i18n/fr.po b/package/gluon-web-autoupdater/i18n/fr.po similarity index 93% rename from package/gluon-luci-autoupdater/i18n/fr.po rename to package/gluon-web-autoupdater/i18n/fr.po index 28263806..fec24176 100644 --- a/package/gluon-luci-autoupdater/i18n/fr.po +++ b/package/gluon-web-autoupdater/i18n/fr.po @@ -1,12 +1,12 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-08-19 20:20+0100\n" "Last-Translator: Bernot Tobias \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -15,3 +15,6 @@ msgstr "Mise a jour automatique" msgid "Branch" msgstr "Branche" + +msgid "Enable" +msgstr "Activer" diff --git a/package/gluon-luci-autoupdater/i18n/gluon-luci-autoupdater.pot b/package/gluon-web-autoupdater/i18n/gluon-web-autoupdater.pot similarity index 82% rename from package/gluon-luci-autoupdater/i18n/gluon-luci-autoupdater.pot rename to package/gluon-web-autoupdater/i18n/gluon-web-autoupdater.pot index 678bdbaf..1cce85c3 100644 --- a/package/gluon-luci-autoupdater/i18n/gluon-luci-autoupdater.pot +++ b/package/gluon-web-autoupdater/i18n/gluon-web-autoupdater.pot @@ -6,3 +6,6 @@ msgstr "" msgid "Branch" msgstr "" + +msgid "Enable" +msgstr "" diff --git a/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/controller/admin/autoupdater.lua b/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/controller/admin/autoupdater.lua new file mode 100644 index 00000000..7071039d --- /dev/null +++ b/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/controller/admin/autoupdater.lua @@ -0,0 +1,3 @@ +package 'gluon-web-autoupdater' + +entry({"admin", "autoupdater"}, model("admin/autoupdater"), _("Automatic updates"), 80) diff --git a/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/model/admin/autoupdater.lua b/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/model/admin/autoupdater.lua new file mode 100644 index 00000000..adf7cbd6 --- /dev/null +++ b/package/gluon-web-autoupdater/luasrc/lib/gluon/config-mode/model/admin/autoupdater.lua @@ -0,0 +1,39 @@ +--[[ +Copyright 2013 Nils Schneider + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +local uci = require("simple-uci").cursor() +local autoupdater = uci:get_first("autoupdater", "autoupdater") + +local f = Form(translate("Automatic updates")) +local s = f:section(Section) +local o + +o = s:option(Flag, "enabled", translate("Enable")) +o.default = uci:get_bool("autoupdater", autoupdater, "enabled") +function o:write(data) + uci:set("autoupdater", autoupdater, "enabled", data) +end + +o = s:option(ListValue, "branch", translate("Branch")) +uci:foreach("autoupdater", "branch", + function (section) + o:value(section[".name"]) + end +) +o.default = uci:get("autoupdater", autoupdater, "branch") +function o:write(data) + uci:set("autoupdater", autoupdater, "branch", data) +end + +function f:write() + uci:commit("autoupdater") +end + +return f diff --git a/package/gluon-web-logging/Makefile b/package/gluon-web-logging/Makefile new file mode 100644 index 00000000..10d83740 --- /dev/null +++ b/package/gluon-web-logging/Makefile @@ -0,0 +1,14 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-logging +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-logging + DEPENDS:=+gluon-web-admin + TITLE:=UI for remote syslog configuration +endef + +$(eval $(call BuildPackageGluon,gluon-web-logging)) diff --git a/package/gluon-web-logging/i18n/de.po b/package/gluon-web-logging/i18n/de.po new file mode 100644 index 00000000..8e00574f --- /dev/null +++ b/package/gluon-web-logging/i18n/de.po @@ -0,0 +1,15 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "" +"If you want to use a remote syslog server, you can set it up here. " +"Please keep in mind that the data is not encrypted, which may cause " +"individual-related data to be transmitted unencrypted over the internet." +msgstr "" +"Wenn du einen Remote-Syslog-Server nutzen möchtest, dann kannst du ihn hier " +"eintragen. Bitte beachte, dass diese Daten nicht verschlüsselt werden. Dies " +"kann dazu führen, dass personenbezogene Daten unverschlüsselt über das Internet " +"übertragen werden." + +msgid "Logging" +msgstr "Logging" diff --git a/package/gluon-web-logging/i18n/gluon-web-logging.pot b/package/gluon-web-logging/i18n/gluon-web-logging.pot new file mode 100644 index 00000000..e35c537c --- /dev/null +++ b/package/gluon-web-logging/i18n/gluon-web-logging.pot @@ -0,0 +1,11 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "" +"If you want to use a remote syslog server, you can set it up here. " +"Please keep in mind that the data is not encrypted, which may cause " +"individual-related data to be transmitted unencrypted over the internet." +msgstr "" + +msgid "Logging" +msgstr "" diff --git a/package/gluon-web-logging/luasrc/lib/gluon/config-mode/controller/admin/logging.lua b/package/gluon-web-logging/luasrc/lib/gluon/config-mode/controller/admin/logging.lua new file mode 100644 index 00000000..5704cdac --- /dev/null +++ b/package/gluon-web-logging/luasrc/lib/gluon/config-mode/controller/admin/logging.lua @@ -0,0 +1,3 @@ +package 'gluon-web-logging' + +entry({"admin", "logging"}, model("admin/logging"), _("Logging"), 85) diff --git a/package/gluon-web-logging/luasrc/lib/gluon/config-mode/model/admin/logging.lua b/package/gluon-web-logging/luasrc/lib/gluon/config-mode/model/admin/logging.lua new file mode 100644 index 00000000..8c707c83 --- /dev/null +++ b/package/gluon-web-logging/luasrc/lib/gluon/config-mode/model/admin/logging.lua @@ -0,0 +1,41 @@ +local uci = require('simple-uci').cursor() +local system = uci:get_first('system', 'system') + +local f = Form(translate('Logging'), translate( + "If you want to use a remote syslog server, you can set it up here. " + .. "Please keep in mind that the data is not encrypted, which may cause " + .. "individual-related data to be transmitted unencrypted over the internet." +)) +local s = f:section(Section) + +local enable = s:option(Flag, 'log_remote', translate('Enable')) +enable.default = uci:get_bool('system', system, 'log_remote') +function enable:write(data) + uci:set('system', system, 'log_remote', data) +end + +local ip = s:option(Value, 'log_ip', translate('IP')) +ip.default = uci:get('system', system, 'log_ip') +ip:depends(enable, true) +ip.optional = false +ip.placeholder = '0.0.0.0' +ip.datatype = 'ipaddr' +function ip:write(data) + uci:set('system', system, 'log_ip', data) +end + +local port = s:option(Value, 'log_port', translate('Port')) +port.default = uci:get('system', system, 'log_port') +port:depends(enable, true) +port.optional = true +port.placeholder = 514 +port.datatype = 'irange(1, 65535)' +function port:write(data) + uci:set('system', system, 'log_port', data) +end + +function f:write() + uci:commit('system') +end + +return f diff --git a/package/gluon-web-mesh-vpn-fastd/Makefile b/package/gluon-web-mesh-vpn-fastd/Makefile new file mode 100644 index 00000000..46dfd181 --- /dev/null +++ b/package/gluon-web-mesh-vpn-fastd/Makefile @@ -0,0 +1,14 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-mesh-vpn-fastd +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-mesh-vpn-fastd + TITLE:=gluon-web module to enable and disable encryption for the mesh VPN + DEPENDS:=+gluon-web-admin +gluon-mesh-vpn-fastd +endef + +$(eval $(call BuildPackageGluon,gluon-web-mesh-vpn-fastd)) diff --git a/package/gluon-web-mesh-vpn-fastd/check_site.lua b/package/gluon-web-mesh-vpn-fastd/check_site.lua new file mode 100644 index 00000000..ff64043b --- /dev/null +++ b/package/gluon-web-mesh-vpn-fastd/check_site.lua @@ -0,0 +1 @@ +need_value(in_site({'mesh_vpn', 'fastd', 'configurable'}), true) diff --git a/package/gluon-web-mesh-vpn-fastd/files/lib/gluon/config-mode/view/mesh-vpn-fastd.html b/package/gluon-web-mesh-vpn-fastd/files/lib/gluon/config-mode/view/mesh-vpn-fastd.html new file mode 100644 index 00000000..ed527c8e --- /dev/null +++ b/package/gluon-web-mesh-vpn-fastd/files/lib/gluon/config-mode/view/mesh-vpn-fastd.html @@ -0,0 +1,34 @@ +
+
+ /> + > +
+
+ class="gluon-value-title"><%:Security mode%> +
+ <%| translate( + 'In security mode, the mesh VPN uses an encrypted tunnel to connect to the VPN servers. ' .. + 'The encryption ensures that it is impossible for your internet access provider to see what ' .. + 'data is exchanged over your node.' + ) %> +
+
+
+
+ +
+
+ /> + > +
+
+ class="gluon-value-title"><%:Performance mode%> +
+ <%| translate( + 'In performance mode, no encryption is used. This usually allows for higher throughput, but the data exchanged over your node is not ' .. + 'protected against eavesdropping.' + ) %> +
+
+
+
diff --git a/package/gluon-luci-mesh-vpn-fastd/i18n/de.po b/package/gluon-web-mesh-vpn-fastd/i18n/de.po similarity index 89% rename from package/gluon-luci-mesh-vpn-fastd/i18n/de.po rename to package/gluon-web-mesh-vpn-fastd/i18n/de.po index 12e48439..eb2b751c 100644 --- a/package/gluon-luci-mesh-vpn-fastd/i18n/de.po +++ b/package/gluon-web-mesh-vpn-fastd/i18n/de.po @@ -15,7 +15,7 @@ msgid "" "throughput, but the data exchanged over your node is not protected against " "eavesdropping." msgstr "" -"Im Modus „Hohe Geschwindigkeit“ wird auf Verschlüsselung " +"Im Modus „Hohe Geschwindigkeit“ wird auf Verschlüsselung " "verzichtet. Dies erlaubt häufig eine höhere Bandbreite als mit " "Verschlüsselung, aber die Verbindung ist nicht gegen Abhören geschützt." @@ -24,7 +24,7 @@ msgid "" "VPN servers. The encryption ensures that it is impossible for your internet " "access provider to see what data is exchanged over your node." msgstr "" -"Im Modus „Hohe Sicherheit“ wird ein verschlüsselter Tunnel " +"Im Modus „Hohe Sicherheit“ wird ein verschlüsselter Tunnel " "verwendet. Dies schließt aus, dass dein Internetzugangsprovider herausfinden " "kann, was für Daten über deinen Knoten übertragen werden." diff --git a/package/gluon-luci-mesh-vpn-fastd/i18n/fr.po b/package/gluon-web-mesh-vpn-fastd/i18n/fr.po similarity index 100% rename from package/gluon-luci-mesh-vpn-fastd/i18n/fr.po rename to package/gluon-web-mesh-vpn-fastd/i18n/fr.po diff --git a/package/gluon-luci-mesh-vpn-fastd/i18n/gluon-luci-mesh-vpn-fastd.pot b/package/gluon-web-mesh-vpn-fastd/i18n/gluon-web-mesh-vpn-fastd.pot similarity index 100% rename from package/gluon-luci-mesh-vpn-fastd/i18n/gluon-luci-mesh-vpn-fastd.pot rename to package/gluon-web-mesh-vpn-fastd/i18n/gluon-web-mesh-vpn-fastd.pot diff --git a/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/controller/admin/mesh_vpn_fastd.lua b/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/controller/admin/mesh_vpn_fastd.lua new file mode 100644 index 00000000..1b365956 --- /dev/null +++ b/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/controller/admin/mesh_vpn_fastd.lua @@ -0,0 +1,3 @@ +package 'gluon-web-mesh-vpn-fastd' + +entry({"admin", "mesh_vpn_fastd"}, model("admin/mesh_vpn_fastd"), _("Mesh VPN"), 50) diff --git a/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/model/admin/mesh_vpn_fastd.lua b/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/model/admin/mesh_vpn_fastd.lua new file mode 100644 index 00000000..a41f291e --- /dev/null +++ b/package/gluon-web-mesh-vpn-fastd/luasrc/lib/gluon/config-mode/model/admin/mesh_vpn_fastd.lua @@ -0,0 +1,39 @@ +local uci = require("simple-uci").cursor() +local util = gluon.util + +local f = Form(translate('Mesh VPN')) + +local s = f:section(Section) + +local mode = s:option(Value, 'mode') +mode.package = "gluon-web-mesh-vpn-fastd" +mode.template = "mesh-vpn-fastd" + +local methods = uci:get('fastd', 'mesh_vpn', 'method') +if util.contains(methods, 'null') then + mode.default = 'performance' +else + mode.default = 'security' +end + +function mode:write(data) + local site = require 'gluon.site' + + local methods = {} + if data == 'performance' then + table.insert(methods, 'null') + end + + for _, method in ipairs(site.mesh_vpn.fastd.methods()) do + if method ~= 'null' then + table.insert(methods, method) + end + end + + uci:set('fastd', 'mesh_vpn', 'method', methods) + + uci:save('fastd') + uci:commit('fastd') +end + +return f diff --git a/package/gluon-web-model/Makefile b/package/gluon-web-model/Makefile new file mode 100644 index 00000000..d767f562 --- /dev/null +++ b/package/gluon-web-model/Makefile @@ -0,0 +1,13 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-model +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-web-model + TITLE:=Minimal Lua web framework derived from LuCI (model support) + DEPENDS:=+gluon-web +endef + +$(eval $(call BuildPackageGluon,gluon-web-model)) diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/dynlist.html b/package/gluon-web-model/files/lib/gluon/web/view/model/dynlist.html new file mode 100644 index 00000000..512a194b --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/dynlist.html @@ -0,0 +1,20 @@ +> +<% + for i, val in ipairs(self:cfgvalue()) do +%> + />
+<% end %> +
diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/form.html b/package/gluon-web-model/files/lib/gluon/web/view/model/form.html new file mode 100644 index 00000000..1b642b0d --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/form.html @@ -0,0 +1,28 @@ +
+ + + +
+ <% if self.title and #self.title > 0 then %>

<%|self.title%>

<% end %> + <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> + <% self:render_children(renderer) %> +
+<%- if self.message then %> +
<%|self.message%>
+<%- end %> +<%- if self.errmessage then %> +
<%|self.errmessage%>
+<%- end %> +
+ <%- if self.submit ~= false then %> + + <% end %> + <%- if self.reset ~= false then %> + + <% end %> +
+
diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/fvalue.html b/package/gluon-web-model/files/lib/gluon/web/view/model/fvalue.html new file mode 100644 index 00000000..60741e32 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/fvalue.html @@ -0,0 +1,5 @@ + /> +> diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/lvalue.html b/package/gluon-web-model/files/lib/gluon/web/view/model/lvalue.html new file mode 100644 index 00000000..47a2ffd1 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/lvalue.html @@ -0,0 +1,43 @@ +<% + local br = self.orientation == "horizontal" and '   ' or '
' + local entries = self:entries() +%> + +<% if self.widget == "select" then %> + +<% elseif self.widget == "radio" then %> +
+ <% for i, entry in pairs(entries) do %> + > + /> + > + <%|entry.value%> + + <% if i ~= #entries then write(br) end %> + <% end %> +
+<% end %> diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/section.html b/package/gluon-web-model/files/lib/gluon/web/view/model/section.html new file mode 100644 index 00000000..de4d7a5c --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/section.html @@ -0,0 +1,28 @@ +
+ <% if self.title and #self.title > 0 then -%> + <%|self.title%> + <%- end %> + <% if self.description and #self.description > 0 then -%> +
<%=self.description%>
+ <%- end %> +
+
+ <% self:render_children(renderer, scope) %> +
+ <% if self.error and self.error[1] then -%> +
+
    <% for _, e in ipairs(self.error[1]) do -%> +
  • + <%- if e == "invalid" then -%> + <%:One or more fields contain invalid values!%> + <%- elseif e == "missing" then -%> + <%:One or more required fields have no value!%> + <%- else -%> + <%|e%> + <%- end -%> +
  • + <%- end %>
+
+ <%- end %> +
+
diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/tvalue.html b/package/gluon-web-model/files/lib/gluon/web/view/model/tvalue.html new file mode 100644 index 00000000..cfc5e4b0 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/tvalue.html @@ -0,0 +1,3 @@ + diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/value.html b/package/gluon-web-model/files/lib/gluon/web/view/model/value.html new file mode 100644 index 00000000..f14c122e --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/value.html @@ -0,0 +1,12 @@ + /> diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/valuewrapper.html b/package/gluon-web-model/files/lib/gluon/web/view/model/valuewrapper.html new file mode 100644 index 00000000..1a1a63d1 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/valuewrapper.html @@ -0,0 +1,18 @@ +
> + <%- if self.title and #self.title > 0 then -%> + +
+ <%- end -%> + <% if self.subtemplate then include(self.subtemplate) end %> + <% if self.description and #self.description > 0 then -%> +
+
+ <%=self.description%> +
+ <%- end %> + <%- if self.title and #self.title > 0 then -%> +
+ <%- end -%> +
diff --git a/package/gluon-web-model/files/lib/gluon/web/view/model/wrapper.html b/package/gluon-web-model/files/lib/gluon/web/view/model/wrapper.html new file mode 100644 index 00000000..a49fe938 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/view/model/wrapper.html @@ -0,0 +1,6 @@ +<% + for _, map in ipairs(maps) do + map:render(renderer) + end +%> + diff --git a/package/gluon-web-model/files/lib/gluon/web/www/static/gluon-web-model.js b/package/gluon-web-model/files/lib/gluon/web/www/static/gluon-web-model.js new file mode 100644 index 00000000..d71e1d77 --- /dev/null +++ b/package/gluon-web-model/files/lib/gluon/web/www/static/gluon-web-model.js @@ -0,0 +1 @@ +!function(){var e={};function t(e){return/^-?\d+$/.test(e)?+e:NaN}function n(e){return/^-?\d*\.?\d+?$/.test(e)?+e:NaN}var a={integer:function(){return!isNaN(t(this))},uinteger:function(){return t(this)>=0},float:function(){return!isNaN(n(this))},ufloat:function(){return n(this)>=0},ipaddr:function(){return a.ip4addr.apply(this)||a.ip6addr.apply(this)},ip4addr:function(){var e;return!!(e=this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))&&(e[1]>=0&&e[1]<=255&&e[2]>=0&&e[2]<=255&&e[3]>=0&&e[3]<=255&&e[4]>=0&&e[4]<=255)},ip6addr:function(){return this.indexOf("::")<0?null!=this.match(/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i):!(this.indexOf(":::")>=0||this.match(/::.+::/)||this.match(/^:[^:]/)||this.match(/[^:]:$/))&&(!!this.match(/^(?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}$/i)||(!!this.match(/^(?:[a-f0-9]{1,4}:){7}:$/i)||!!this.match(/^:(?::[a-f0-9]{1,4}){7}$/i)))},wpakey:function(){var e=this;return 64==e.length?null!=e.match(/^[a-f0-9]{64}$/i):e.length>=8&&e.length<=63},range:function(e,t){var a=n(this);return a>=+e&&a<=+t},min:function(e){return n(this)>=+e},max:function(e){return n(this)<=+e},irange:function(e,n){var a=t(this);return a>=+e&&a<=+n},imin:function(e){return t(this)>=+e},imax:function(e){return t(this)<=+e},minlength:function(e){return(""+this).length>=+e},maxlength:function(e){return(""+this).length<=+e}};function r(e){for(var t=0;ta.index);u=u.nextSibling);u?d.insertBefore(a.node,u):d.appendChild(a.node),t=!0}d&&d.parentNode&&d.getAttribute("data-optionals")&&(d.parentNode.style.display=d.options.length<=1?"none":"")}t&&i()}function o(e,t,n,a){return e.addEventListener?e.addEventListener(t,n,!!a):e.attachEvent("on"+t,function(){var e=window.event;return!e.target&&e.srcElement&&(e.target=e.srcElement),!!n(e)}),e}function d(e,t){var n=t.prefix;function a(a,l,s){for(var c=[];e.firstChild;){var p=e.firstChild;(f=+p.index)!=s&&("input"==p.nodeName.toLowerCase()?c.push(p.value||""):"select"==p.nodeName.toLowerCase()&&(c[c.length-1]=p.options[p.selectedIndex].value)),e.removeChild(p)}l>=0?(a=l+1,c.splice(l,0,"")):t.optional||0!=c.length||c.push("");for(var f=1;f<=c.length;f++){var v=document.createElement("input");if(v.id=n+"."+f,v.name=n,v.value=c[f-1],v.type="text",v.index=f,v.className="gluon-input-text",t.size&&(v.size=t.size),t.placeholder&&(v.placeholder=t.placeholder),e.appendChild(v),t.type&&u(v,!1,t.type),o(v,"keydown",i),o(v,"keypress",r),f==a)v.focus();else if(-f==a){v.focus();var h=v.value;v.value=" ",v.value=h}if(t.optional||c.length>1)(m=document.createElement("span")).className="gluon-remove",e.appendChild(m),o(m,"click",d(!1)),e.appendChild(document.createElement("br"))}var m;(m=document.createElement("span")).className="gluon-add",e.appendChild(m),o(m,"click",d(!0))}function r(e){var t=(e=e||window.event).target?e.target:e.srcElement;switch(3==t.nodeType&&(t=t.parentNode),e.keyCode){case 8:case 46:return 0!=t.value.length||(e.preventDefault&&e.preventDefault(),!1);case 13:case 38:case 40:return e.preventDefault&&e.preventDefault(),!1}return!0}function i(e){var t,r,i=(e=e||window.event).target?e.target:e.srcElement,o=0;if(i){for(3==i.nodeType&&(i=i.parentNode),o=i.index,t=i.previousSibling;t&&t.name!=n;)t=t.previousSibling;for(r=i.nextSibling;r&&r.name!=n;)r=r.nextSibling}switch(e.keyCode){case 8:case 46:if("select"==i.nodeName.toLowerCase()||0==i.value.length){e.preventDefault&&e.preventDefault();var d=i.index;return 8==e.keyCode&&(d=1-d),a(d,-1,o),!1}break;case 13:a(-1,o,-1);break;case 38:t&&t.focus();break;case 40:r&&r.focus()}return!0}function d(e){return function(t){for(var a=((t=t||window.event).target?t.target:t.srcElement).previousSibling;a&&a.name!=n;)a=a.previousSibling;return e?i({target:a,keyCode:13}):(a.value="",i({target:a,keyCode:8})),!1}}a(NaN,-1,-1)}function u(e,t,n){var r,i,d,u=(d=(r=n).match(/^([^\(]+)\(([^,]+),([^\)]+)\)$/))&&void 0!==(i=a[d[1]])?function(){return i.apply(this,[d[2],d[3]])}:(d=r.match(/^([^\(]+)\(([^,\)]+)\)$/))&&void 0!==(i=a[d[1]])?function(){return i.apply(this,[d[2]])}:a[r];if(u){var l=function(){if(e.form){e.className=e.className.replace(/ gluon-input-invalid/g,"");var n=e.options&&e.options.selectedIndex>-1?e.options[e.options.selectedIndex].value:e.value;0==n.length&&t||u.apply(n)||(e.className+=" gluon-input-invalid")}};o(e,"blur",l),o(e,"keyup",l),"select"==e.nodeName.toLowerCase()&&(o(e,"change",l),o(e,"click",l)),l()}}!function(){var t,n,a,r,l;t=document.querySelectorAll("[data-depends]");for(var s=0;void 0!==(g=t[s]);s++){var c=parseInt(g.getAttribute("data-index"),10),p=JSON.parse(g.getAttribute("data-depends"));if(!isNaN(c)&&p.length>0)for(var f=0;f\n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "One or more fields contain invalid values!" +msgstr "Ein oder mehrere Felder enthalten ungültige Werte!" + +msgid "One or more required fields have no value!" +msgstr "Ein oder mehr benötigte Felder sind nicht ausgefüllt!" + +msgid "Reset" +msgstr "Zurücksetzen" + +msgid "Save" +msgstr "Speichern" diff --git a/package/gluon-web-model/i18n/fr.po b/package/gluon-web-model/i18n/fr.po new file mode 100644 index 00000000..61c59d88 --- /dev/null +++ b/package/gluon-web-model/i18n/fr.po @@ -0,0 +1,23 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2013-12-22 17:11+0200\n" +"Last-Translator: goofy \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "One or more fields contain invalid values!" +msgstr "Un ou plusieurs champs contiennent des valeurs incorrectes !" + +msgid "One or more required fields have no value!" +msgstr "Un ou plusieurs champs n'ont pas de valeur !" + +msgid "Reset" +msgstr "Remise à zéro" + +msgid "Save" +msgstr "Soumettre" diff --git a/package/gluon-web-model/i18n/gluon-web-model.pot b/package/gluon-web-model/i18n/gluon-web-model.pot new file mode 100644 index 00000000..3fd79546 --- /dev/null +++ b/package/gluon-web-model/i18n/gluon-web-model.pot @@ -0,0 +1,14 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "One or more fields contain invalid values!" +msgstr "" + +msgid "One or more required fields have no value!" +msgstr "" + +msgid "Reset" +msgstr "" + +msgid "Save" +msgstr "" diff --git a/package/gluon-web-model/javascript/gluon-web-model.js b/package/gluon-web-model/javascript/gluon-web-model.js new file mode 100644 index 00000000..c05a171e --- /dev/null +++ b/package/gluon-web-model/javascript/gluon-web-model.js @@ -0,0 +1,534 @@ +/* + Copyright 2008 Steven Barth + Copyright 2008-2012 Jo-Philipp Wich + Copyright 2017 Matthias Schiffer + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 +*/ + +/* + Build using: + + uglifyjs javascript/gluon-web-model.js -o files/lib/gluon/web/www/static/gluon-web-model.js -c -m --support-ie8 +*/ + + + +(function() { + var dep_entries = {}; + + function Int(x) { + return (/^-?\d+$/.test(x) ? +x : NaN); + } + + function Dec(x) { + return (/^-?\d*\.?\d+?$/.test(x) ? +x : NaN); + } + + var validators = { + + 'integer': function() { + return !isNaN(Int(this)); + }, + + 'uinteger': function() { + return (Int(this) >= 0); + }, + + 'float': function() { + return !isNaN(Dec(this)); + }, + + 'ufloat': function() { + return (Dec(this) >= 0); + }, + + 'ipaddr': function() { + return validators.ip4addr.apply(this) || + validators.ip6addr.apply(this); + }, + + 'ip4addr': function() { + var match; + if ((match = this.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/))) { + return (match[1] >= 0) && (match[1] <= 255) && + (match[2] >= 0) && (match[2] <= 255) && + (match[3] >= 0) && (match[3] <= 255) && + (match[4] >= 0) && (match[4] <= 255); + } + + return false; + }, + + 'ip6addr': function() { + if (this.indexOf('::') < 0) + return (this.match(/^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i) != null); + + if ( + (this.indexOf(':::') >= 0) || this.match(/::.+::/) || + this.match(/^:[^:]/) || this.match(/[^:]:$/) + ) + return false; + + if (this.match(/^(?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}$/i)) + return true; + if (this.match(/^(?:[a-f0-9]{1,4}:){7}:$/i)) + return true; + if (this.match(/^:(?::[a-f0-9]{1,4}){7}$/i)) + return true; + + return false; + }, + + 'wpakey': function() { + var v = this; + + if (v.length == 64) + return (v.match(/^[a-f0-9]{64}$/i) != null); + else + return (v.length >= 8) && (v.length <= 63); + }, + + 'range': function(min, max) { + var val = Dec(this); + return (val >= +min && val <= +max); + }, + + 'min': function(min) { + return (Dec(this) >= +min); + }, + + 'max': function(max) { + return (Dec(this) <= +max); + }, + + 'irange': function(min, max) { + var val = Int(this); + return (val >= +min && val <= +max); + }, + + 'imin': function(min) { + return (Int(this) >= +min); + }, + + 'imax': function(max) { + return (Int(this) <= +max); + }, + + 'minlength': function(min) { + return ((''+this).length >= +min); + }, + + 'maxlength': function(max) { + return ((''+this).length <= +max); + }, + }; + + function compile(type) { + var v, match; + if ((match = type.match(/^([^\(]+)\(([^,]+),([^\)]+)\)$/)) && (v = validators[match[1]]) !== undefined) { + return function() { + return v.apply(this, [match[2], match[3]]); + } + } else if ((match = type.match(/^([^\(]+)\(([^,\)]+)\)$/)) && (v = validators[match[1]]) !== undefined) { + return function() { + return v.apply(this, [match[2]]); + } + } else { + return validators[type]; + } + } + + function checkvalue(target, ref) { + var t = document.getElementById(target); + var value; + + if (t) { + if (t.type == "checkbox") { + value = t.checked; + } else if (t.value) { + value = t.value; + } else { + value = ""; + } + + return (value == ref); + } else { + t = document.getElementById(target + '.' + ref); + if (t) + return (t.type == "radio" && t.checked); + } + + return false; + + } + + function check(deps) { + for (var i=0; i < deps.length; i++) { + var stat = true; + + for (var j in deps[i]) { + stat = (stat && checkvalue(j, deps[i][j])); + } + + if (stat) + return true; + } + + return false; + } + + function update() { + var state = false; + for (var id in dep_entries) { + var entry = dep_entries[id]; + var node = document.getElementById(id); + var parent = document.getElementById(entry.parent); + + if (node && node.parentNode && !check(entry.deps)) { + node.parentNode.removeChild(node); + state = true; + } else if (parent && (!node || !node.parentNode) && check(entry.deps)) { + var next = undefined; + + for (next = parent.firstChild; next; next = next.nextSibling) { + if (next.getAttribute && parseInt(next.getAttribute('data-index'), 10) > entry.index) { + break; + } + } + + if (!next) { + parent.appendChild(entry.node); + } else { + parent.insertBefore(entry.node, next); + } + + state = true; + } + + // hide optionals widget if no choices remaining + if (parent && parent.parentNode && parent.getAttribute('data-optionals')) + parent.parentNode.style.display = (parent.options.length <= 1) ? 'none' : ''; + } + + if (state) { + update(); + } + } + + function bind(obj, type, callback, mode) { + if (!obj.addEventListener) { + obj.attachEvent('on' + type, + function() { + var e = window.event; + + if (!e.target && e.srcElement) + e.target = e.srcElement; + + return !!callback(e); + } + ); + } else { + obj.addEventListener(type, callback, !!mode); + } + return obj; + } + + function init_dynlist(parent, attr) { + var prefix = attr.prefix; + + function dynlist_redraw(focus, add, del) { + var values = []; + + while (parent.firstChild) { + var n = parent.firstChild; + var i = +n.index; + + if (i != del) { + if (n.nodeName.toLowerCase() == 'input') + values.push(n.value || ''); + else if (n.nodeName.toLowerCase() == 'select') + values[values.length-1] = n.options[n.selectedIndex].value; + } + + parent.removeChild(n); + } + + if (add >= 0) { + focus = add + 1; + values.splice(add, 0, ''); + } else if (!attr.optional && values.length == 0) { + values.push(''); + } + + for (var i = 1; i <= values.length; i++) { + var t = document.createElement('input'); + t.id = prefix + '.' + i; + t.name = prefix; + t.value = values[i-1]; + t.type = 'text'; + t.index = i; + t.className = 'gluon-input-text'; + + if (attr.size) + t.size = attr.size; + if (attr.placeholder) + t.placeholder = attr.placeholder; + + parent.appendChild(t); + + if (attr.type) + validate_field(t, false, attr.type); + + bind(t, 'keydown', dynlist_keydown); + bind(t, 'keypress', dynlist_keypress); + + if (i == focus) { + t.focus(); + } else if (-i == focus) { + t.focus(); + + /* force cursor to end */ + var v = t.value; + t.value = ' ' + t.value = v; + } + + if (attr.optional || values.length > 1) { + var b = document.createElement('span'); + b.className = 'gluon-remove'; + + parent.appendChild(b); + + bind(b, 'click', dynlist_btnclick(false)); + + parent.appendChild(document.createElement('br')); + } + } + + var b = document.createElement('span'); + b.className = 'gluon-add'; + + parent.appendChild(b); + + bind(b, 'click', dynlist_btnclick(true)); + } + + function dynlist_keypress(ev) { + ev = ev ? ev : window.event; + + var se = ev.target ? ev.target : ev.srcElement; + + if (se.nodeType == 3) + se = se.parentNode; + + switch (ev.keyCode) { + /* backspace, delete */ + case 8: + case 46: + if (se.value.length == 0) { + if (ev.preventDefault) + ev.preventDefault(); + + return false; + } + + return true; + + /* enter, arrow up, arrow down */ + case 13: + case 38: + case 40: + if (ev.preventDefault) + ev.preventDefault(); + + return false; + } + + return true; + } + + function dynlist_keydown(ev) { + ev = ev ? ev : window.event; + + var se = ev.target ? ev.target : ev.srcElement; + + var index = 0; + var prev, next; + + if (se) { + if (se.nodeType == 3) + se = se.parentNode; + + index = se.index; + + prev = se.previousSibling; + while (prev && prev.name != prefix) + prev = prev.previousSibling; + + next = se.nextSibling; + while (next && next.name != prefix) + next = next.nextSibling; + } + + switch (ev.keyCode) { + /* backspace, delete */ + case 8: + case 46: + var del = (se.nodeName.toLowerCase() == 'select') + ? true : (se.value.length == 0); + + if (del) { + if (ev.preventDefault) + ev.preventDefault(); + + var focus = se.index; + if (ev.keyCode == 8) + focus = -focus+1; + + dynlist_redraw(focus, -1, index); + + return false; + } + + break; + + /* enter */ + case 13: + dynlist_redraw(-1, index, -1); + break; + + /* arrow up */ + case 38: + if (prev) + prev.focus(); + + break; + + /* arrow down */ + case 40: + if (next) + next.focus(); + + break; + } + + return true; + } + + function dynlist_btnclick(add) { + return function(ev) { + ev = ev ? ev : window.event; + + var se = ev.target ? ev.target : ev.srcElement; + var input = se.previousSibling; + while (input && input.name != prefix) { + input = input.previousSibling; + } + + if (add) { + dynlist_keydown({ + target: input, + keyCode: 13 + }); + } else { + input.value = ''; + + dynlist_keydown({ + target: input, + keyCode: 8 + }); + } + + return false; + } + } + + dynlist_redraw(NaN, -1, -1); + } + + function validate_field(field, optional, type) { + var check = compile(type); + if (!check) + return; + + var validator = function() { + if (!field.form) + return; + + field.className = field.className.replace(/ gluon-input-invalid/g, ''); + + var value = (field.options && field.options.selectedIndex > -1) + ? field.options[field.options.selectedIndex].value : field.value; + + if (!(((value.length == 0) && optional) || check.apply(value))) + field.className += ' gluon-input-invalid'; + }; + + bind(field, "blur", validator); + bind(field, "keyup", validator); + + if (field.nodeName.toLowerCase() == 'select') { + bind(field, "change", validator); + bind(field, "click", validator); + } + + validator(); + } + + function add(obj, dep, index) { + var entry = dep_entries[obj.id]; + if (!entry) { + entry = { + "node": obj, + "parent": obj.parentNode.id, + "deps": [], + "index": index + }; + dep_entries[obj.id] = entry; + } + entry.deps.push(dep) + } + + (function() { + var nodes; + + nodes = document.querySelectorAll('[data-depends]'); + for (var i = 0, node; (node = nodes[i]) !== undefined; i++) { + var index = parseInt(node.getAttribute('data-index'), 10); + var depends = JSON.parse(node.getAttribute('data-depends')); + if (!isNaN(index) && depends.length > 0) { + for (var alt = 0; alt < depends.length; alt++) { + add(node, depends[alt], index); + } + } + } + + nodes = document.querySelectorAll('[data-update]'); + for (var i = 0, node; (node = nodes[i]) !== undefined; i++) { + var events = node.getAttribute('data-update').split(' '); + for (var j = 0, event; (event = events[j]) !== undefined; j++) { + bind(node, event, update); + } + } + + nodes = document.querySelectorAll('[data-type]'); + for (var i = 0, node; (node = nodes[i]) !== undefined; i++) { + validate_field(node, node.getAttribute('data-optional') === 'true', + node.getAttribute('data-type')); + } + + nodes = document.querySelectorAll('[data-dynlist]'); + for (var i = 0, node; (node = nodes[i]) !== undefined; i++) { + var attr = JSON.parse(node.getAttribute('data-dynlist')); + + init_dynlist(node, attr); + } + + update(); + })(); +})(); diff --git a/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model.lua b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model.lua new file mode 100644 index 00000000..8c968dfe --- /dev/null +++ b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model.lua @@ -0,0 +1,66 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017-2018 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +module('gluon.web.model', package.seeall) + +local fs = require 'nixio.fs' +local classes = require 'gluon.web.model.classes' + +local util = require 'gluon.web.util' +local instanceof = util.instanceof + +-- Loads a model from given file, creating an environment and returns it +local function load(filename, i18n) + local func = assert(loadfile(filename)) + + setfenv(func, setmetatable({}, {__index = + function(tbl, key) + return classes[key] or i18n[key] or _G[key] + end + })) + + local models = { func() } + + for k, model in ipairs(models) do + if not instanceof(model, classes.Node) then + error("model definition returned an invalid model object") + end + model.index = k + end + + return models +end + +return function(config, http, renderer, name, pkg) + local hidenav = false + + local modeldir = config.base_path .. '/model/' + local filename = modeldir..name..'.lua' + + if not fs.access(filename) then + error("Model '" .. name .. "' not found!") + end + + local i18n = setmetatable({ + i18n = renderer.i18n + }, { + __index = renderer.i18n(pkg) + }) + + local maps = load(filename, i18n) + + for _, map in ipairs(maps) do + map:parse(http) + end + for _, map in ipairs(maps) do + map:handle() + hidenav = hidenav or map.hidenav + end + + renderer.render_layout('model/wrapper', { + maps = maps, + }, nil, { + hidenav = hidenav, + }) +end diff --git a/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/classes.lua b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/classes.lua new file mode 100644 index 00000000..ac769692 --- /dev/null +++ b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/classes.lua @@ -0,0 +1,460 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017-2018 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +module("gluon.web.model.classes", package.seeall) + +local util = require "gluon.web.util" + +local datatypes = require "gluon.web.model.datatypes" +local class = util.class +local instanceof = util.instanceof + +FORM_NODATA = 0 +FORM_VALID = 1 +FORM_INVALID = -1 + + +local function parse_datatype(code) + local match, arg, arg2 + + match, arg, arg2 = code:match('^([^%(]+)%(([^,]+),([^%)]+)%)$') + if match then + return datatypes[match], {arg, arg2} + end + + match, arg = code:match('^([^%(]+)%(([^%)]+)%)$') + if match then + return datatypes[match], {arg} + end + + return datatypes[code], {} +end + +local function verify_datatype(dt, value) + if dt then + local c, args = parse_datatype(dt) + assert(c, "Invalid datatype") + return c(value, unpack(args)) + end + return true +end + + +Node = class() + +function Node:__init__(title, description, name) + self.children = {} + self.title = title or "" + self.description = description or "" + self.name = name + self.index = nil + self.parent = nil + self.package = 'gluon-web-model' +end + +function Node:append(obj) + table.insert(self.children, obj) + obj.index = #self.children + obj.parent = self +end + +function Node:id_suffix() + return self.name or (self.index and tostring(self.index)) or '_' +end + +function Node:id() + local prefix = self.parent and self.parent:id() or "id" + + return prefix.."."..self:id_suffix() +end + +function Node:parse(http) + for _, child in ipairs(self.children) do + child:parse(http) + end +end + +function Node:render(renderer, scope) + if self.template then + local env = setmetatable({ + self = self, + id = self:id(), + scope = scope, + }, {__index = scope}) + renderer.render(self.template, env, self.package) + end +end + +function Node:render_children(renderer, scope) + for _, node in ipairs(self.children) do + node:render(renderer, scope) + end +end + +function Node:resolve_depends() + local updated = false + for _, node in ipairs(self.children) do + update = updated or node:resolve_depends() + end + return updated +end + +function Node:handle() + for _, node in ipairs(self.children) do + node:handle() + end +end + + +Template = class(Node) + +function Template:__init__(template) + Node.__init__(self) + self.template = template +end + + +Form = class(Node) + +function Form:__init__(...) + Node.__init__(self, ...) + self.template = "model/form" +end + +function Form:submitstate(http) + return http:getenv("REQUEST_METHOD") == "POST" and http:formvalue(self:id()) ~= nil +end + +function Form:parse(http) + if not self:submitstate(http) then + self.state = FORM_NODATA + return + end + + Node.parse(self, http) + + while self:resolve_depends() do end + + for _, s in ipairs(self.children) do + for _, v in ipairs(s.children) do + if v.state == FORM_INVALID then + self.state = FORM_INVALID + return + end + end + end + + self.state = FORM_VALID +end + +function Form:handle() + if self.state == FORM_VALID then + Node.handle(self) + self:write() + end +end + +function Form:write() +end + +function Form:section(t, ...) + assert(instanceof(t, Section), "class must be a descendent of Section") + + local obj = t(...) + self:append(obj) + return obj +end + + +Section = class(Node) + +function Section:__init__(...) + Node.__init__(self, ...) + self.fields = {} + self.template = "model/section" +end + +function Section:option(t, option, title, description, ...) + assert(instanceof(t, AbstractValue), "class must be a descendant of AbstractValue") + + local obj = t(title, description, option, ...) + self:append(obj) + self.fields[option] = obj + return obj +end + + +AbstractValue = class(Node) + +function AbstractValue:__init__(option, ...) + Node.__init__(self, option, ...) + self.deps = {} + + self.default = nil + self.size = nil + self.optional = false + + self.template = "model/valuewrapper" + + self.state = FORM_NODATA +end + +function AbstractValue:depends(field, value) + local deps + if instanceof(field, Node) then + deps = { [field] = value } + else + deps = field + end + + table.insert(self.deps, deps) +end + +function AbstractValue:deplist(section, deplist) + local deps = {} + + for _, d in ipairs(deplist or self.deps) do + local a = {} + for k, v in pairs(d) do + a[k:id()] = v + end + table.insert(deps, a) + end + + if next(deps) then + return deps + end +end + +function AbstractValue:defaultvalue() + return self.default +end + +function AbstractValue:formvalue(http) + return http:formvalue(self:id()) +end + +function AbstractValue:cfgvalue() + if self.state == FORM_NODATA then + return self:defaultvalue() + else + return self.data + end +end + +function AbstractValue:add_error(type, msg) + self.error = msg or type + + if type == "invalid" then + self.tag_invalid = true + elseif type == "missing" then + self.tag_missing = true + end + + self.state = FORM_INVALID +end + +function AbstractValue:reset() + self.error = nil + self.tag_invalid = nil + self.tag_missing = nil + self.data = nil + self.state = FORM_NODATA + +end + +function AbstractValue:parse(http) + self.data = self:formvalue(http) + + local ok, err = self:validate() + if not ok then + if type(self.data) ~= "string" or #self.data > 0 then + self:add_error("invalid", err) + else + self:add_error("missing", err) + end + return + end + + self.state = FORM_VALID +end + +function AbstractValue:resolve_depends() + if self.state == FORM_NODATA or #self.deps == 0 then + return false + end + + for _, d in ipairs(self.deps) do + local valid = true + for k, v in pairs(d) do + if k.state ~= FORM_VALID or k.data ~= v then + valid = false + break + end + end + if valid then return false end + end + + self:reset() + return true +end + +function AbstractValue:validate() + if self.data and verify_datatype(self.datatype, self.data) then + return true + end + + if type(self.data) == "string" and #self.data == 0 then + self.data = nil + end + + if self.data == nil then + return self.optional + end + + return false + +end + +function AbstractValue:handle() + if self.state == FORM_VALID then + self:write(self.data) + end +end + +function AbstractValue:write(value) +end + + +Value = class(AbstractValue) + +function Value:__init__(...) + AbstractValue.__init__(self, ...) + self.subtemplate = "model/value" +end + + +Flag = class(AbstractValue) + +function Flag:__init__(...) + AbstractValue.__init__(self, ...) + self.subtemplate = "model/fvalue" + + self.default = false +end + +function Flag:formvalue(http) + return http:formvalue(self:id()) ~= nil +end + +function Flag:validate() + return true +end + + +ListValue = class(AbstractValue) + +function ListValue:__init__(...) + AbstractValue.__init__(self, ...) + self.subtemplate = "model/lvalue" + + self.size = 1 + self.widget = "select" + + self.keys = {} + self.entry_list = {} +end + +function ListValue:value(key, val, ...) + key = tostring(key) + + if self.keys[key] then + return + end + self.keys[key] = true + + val = val or key + table.insert(self.entry_list, { + key = key, + value = tostring(val), + deps = {...}, + }) +end + +function ListValue:entries() + local ret = {unpack(self.entry_list)} + + if self:cfgvalue() == nil or self.optional then + table.insert(ret, 1, { + key = '', + value = '', + deps = {}, + }) + end + + return ret +end + +function ListValue:validate() + if self.keys[self.data] then + return true + end + + if type(self.data) == "string" and #self.data == 0 then + self.data = nil + end + + if self.data == nil then + return self.optional + end + + return false +end + + +DynamicList = class(AbstractValue) + +function DynamicList:__init__(...) + AbstractValue.__init__(self, ...) + self.subtemplate = "model/dynlist" +end + +function DynamicList:defaultvalue() + local value = self.default + + if type(value) == "table" then + return value + else + return { value } + end +end + +function DynamicList:formvalue(http) + return http:formvaluetable(self:id()) +end + +function DynamicList:validate() + if self.data == nil then + self.data = {} + end + + if #self.data == 0 then + return self.optional + end + + for _, v in ipairs(self.data) do + if not verify_datatype(self.datatype, v) then + return false + end + end + return true +end + + +TextValue = class(AbstractValue) + +function TextValue:__init__(...) + AbstractValue.__init__(self, ...) + self.subtemplate = "model/tvalue" +end diff --git a/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/datatypes.lua b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/datatypes.lua new file mode 100644 index 00000000..49f55c70 --- /dev/null +++ b/package/gluon-web-model/luasrc/usr/lib/lua/gluon/web/model/datatypes.lua @@ -0,0 +1,167 @@ +-- Copyright 2010 Jo-Philipp Wich +-- Copyright 2017 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local tonumber = tonumber + + +module "gluon.web.model.datatypes" + + +function bool(val) + if val == "1" or val == "yes" or val == "on" or val == "true" then + return true + elseif val == "0" or val == "no" or val == "off" or val == "false" then + return true + elseif val == "" or val == nil then + return true + end + + return false +end + +local function dec(val) + if val:match('^%-?%d*%.?%d+$') then + return tonumber(val) + end +end + +local function int(val) + if val:match('^%-?%d+$') then + return tonumber(val) + end +end + +function uinteger(val) + local n = int(val) + return (n ~= nil and n >= 0) +end + +function integer(val) + return (int(val) ~= nil) +end + +function ufloat(val) + local n = dec(val) + return (n ~= nil and n >= 0) +end + +function float(val) + return (dec(val) ~= nil) +end + +function ipaddr(val) + return ip4addr(val) or ip6addr(val) +end + +function ip4addr(val) + local g = '(%d%d?%d?)' + local v1, v2, v3, v4 = val:match('^'..((g..'%.'):rep(3))..g..'$') + local n1, n2, n3, n4 = tonumber(v1), tonumber(v2), tonumber(v3), tonumber(v4) + + if not (n1 and n2 and n3 and n4) then return false end + + return ( + (n1 >= 0) and (n1 <= 255) and + (n2 >= 0) and (n2 <= 255) and + (n3 >= 0) and (n3 <= 255) and + (n4 >= 0) and (n4 <= 255) + ) +end + +function ip6addr(val) + local g1 = '%x%x?%x?%x?' + + if not val:match('::') then + return val:match('^'..((g1..':'):rep(7))..g1..'$') ~= nil + end + + if + val:match(':::') or val:match('::.+::') or + val:match('^:[^:]') or val:match('[^:]:$') + then + return false + end + + local g0 = '%x?%x?%x?%x?' + for i = 2, 7 do + if val:match('^'..((g0..':'):rep(i))..g0..'$') then + return true + end + end + + if val:match('^'..((g1..':'):rep(7))..':$') then + return true + end + if val:match('^:'..((':'..g1):rep(7))..'$') then + return true + end + + return false +end + +function wpakey(val) + if #val == 64 then + return (val:match("^%x+$") ~= nil) + else + return (#val >= 8) and (#val <= 63) + end +end + +function range(val, vmin, vmax) + return min(val, vmin) and max(val, vmax) +end + +function min(val, min) + val = dec(val) + min = tonumber(min) + + if val ~= nil and min ~= nil then + return (val >= min) + end + + return false +end + +function max(val, max) + val = dec(val) + max = tonumber(max) + + if val ~= nil and max ~= nil then + return (val <= max) + end + + return false +end + +function irange(val, vmin, vmax) + return integer(val) and range(val, vmin, vmax) +end + +function imin(val, vmin) + return integer(val) and min(val, vmin) +end + +function imax(val, vmax) + return integer(val) and max(val, vmax) +end + +function minlength(val, min) + min = tonumber(min) + + if min ~= nil then + return (#val >= min) + end + + return false +end + +function maxlength(val, max) + max = tonumber(max) + + if max ~= nil then + return (#val <= max) + end + + return false +end diff --git a/package/gluon-web-network/Makefile b/package/gluon-web-network/Makefile new file mode 100644 index 00000000..42620fe5 --- /dev/null +++ b/package/gluon-web-network/Makefile @@ -0,0 +1,17 @@ +# Copyright (C) 2013 Nils Schneider +# This is free software, licensed under the Apache 2.0 license. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-network +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-network + TITLE:=gluon-web module for network port configuration + DEPENDS:=+gluon-web-admin +gluon-client-bridge +endef + +$(eval $(call BuildPackageGluon,gluon-web-network)) diff --git a/package/gluon-luci-portconfig/i18n/de.po b/package/gluon-web-network/i18n/de.po similarity index 66% rename from package/gluon-luci-portconfig/i18n/de.po rename to package/gluon-web-network/i18n/de.po index 2197fdbe..1170cbb0 100644 --- a/package/gluon-luci-portconfig/i18n/de.po +++ b/package/gluon-web-network/i18n/de.po @@ -1,12 +1,12 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-05-04 02:08+0200\n" "Last-Translator: \n" "Language-Team: German\n" "Language: de\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" @@ -16,12 +16,39 @@ msgstr "Automatisch (DHCP)" msgid "Automatic (RA/DHCPv6)" msgstr "Automatisch (RA/DHCPv6)" -msgid "Enable meshing on the WAN interface" -msgstr "Mesh auf dem WAN-Port aktivieren" +msgid "Disabled" +msgstr "Deaktiviert" + +msgid "Enable PoE Passthrough" +msgstr "PoE-Passthrough aktivieren" + +msgid "Enable PoE Power Port %s" +msgstr "PoE-Ausgabe auf Port %s aktivieren" msgid "Enable meshing on the LAN interface" msgstr "Mesh auf dem LAN-Port aktivieren" +msgid "Enable meshing on the WAN interface" +msgstr "Mesh auf dem WAN-Port aktivieren" + +msgid "Gateway" +msgstr "Gateway" + +msgid "IP address" +msgstr "IP-Adresse" + +msgid "IPv4" +msgstr "IPv4" + +msgid "IPv6" +msgstr "IPv6" + +msgid "Netmask" +msgstr "Netzmaske" + +msgid "Network" +msgstr "Netzwerk" + msgid "Static" msgstr "Statisch" diff --git a/package/gluon-luci-portconfig/i18n/fr.po b/package/gluon-web-network/i18n/fr.po similarity index 70% rename from package/gluon-luci-portconfig/i18n/fr.po rename to package/gluon-web-network/i18n/fr.po index b5f7405d..c67531d8 100644 --- a/package/gluon-luci-portconfig/i18n/fr.po +++ b/package/gluon-web-network/i18n/fr.po @@ -1,28 +1,54 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: PACKAGE VERSION\n" "PO-Revision-Date: 2015-08-19 23:30+0100\n" "Last-Translator:Tobias Bernot \n" "Language-Team: French\n" "Language: fr\n" "MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" - msgid "Automatic (DHCP)" msgstr "Automatique (DHCP)" msgid "Automatic (RA/DHCPv6)" msgstr "Automatique (RA/DHCPv6)" -msgid "Enable meshing on the WAN interface" -msgstr "Activer le réseau MESH sur les ports WAN" +msgid "Disabled" +msgstr "Désactivé" + +msgid "Enable PoE Passthrough" +msgstr "" + +msgid "Enable PoE Power Port %s" +msgstr "" msgid "Enable meshing on the LAN interface" msgstr "Activer le réseau MESH sur le port LAN" +msgid "Enable meshing on the WAN interface" +msgstr "Activer le réseau MESH sur les ports WAN" + +msgid "Gateway" +msgstr "Passerelle" + +msgid "IP address" +msgstr "Adresse IP" + +msgid "IPv4" +msgstr "IPv4" + +msgid "IPv6" +msgstr "IPv6" + +msgid "Netmask" +msgstr "Masque de réseau" + +msgid "Network" +msgstr "Réseau" + msgid "Static" msgstr "Statique" diff --git a/package/gluon-luci-portconfig/i18n/gluon-luci-portconfig.pot b/package/gluon-web-network/i18n/gluon-web-network.pot similarity index 55% rename from package/gluon-luci-portconfig/i18n/gluon-luci-portconfig.pot rename to package/gluon-web-network/i18n/gluon-web-network.pot index 31ac71d3..75f625da 100644 --- a/package/gluon-luci-portconfig/i18n/gluon-luci-portconfig.pot +++ b/package/gluon-web-network/i18n/gluon-web-network.pot @@ -7,12 +7,39 @@ msgstr "" msgid "Automatic (RA/DHCPv6)" msgstr "" -msgid "Enable meshing on the WAN interface" +msgid "Disabled" +msgstr "" + +msgid "Enable PoE Passthrough" +msgstr "" + +msgid "Enable PoE Power Port %s" msgstr "" msgid "Enable meshing on the LAN interface" msgstr "" +msgid "Enable meshing on the WAN interface" +msgstr "" + +msgid "Gateway" +msgstr "" + +msgid "IP address" +msgstr "" + +msgid "IPv4" +msgstr "" + +msgid "IPv6" +msgstr "" + +msgid "Netmask" +msgstr "" + +msgid "Network" +msgstr "" + msgid "Static" msgstr "" diff --git a/package/gluon-web-network/luasrc/lib/gluon/config-mode/controller/admin/network.lua b/package/gluon-web-network/luasrc/lib/gluon/config-mode/controller/admin/network.lua new file mode 100644 index 00000000..6d14dc7a --- /dev/null +++ b/package/gluon-web-network/luasrc/lib/gluon/config-mode/controller/admin/network.lua @@ -0,0 +1,3 @@ +package 'gluon-web-network' + +entry({"admin", "network"}, model("admin/network"), _("Network"), 40) diff --git a/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua b/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua new file mode 100644 index 00000000..7f723ee5 --- /dev/null +++ b/package/gluon-web-network/luasrc/lib/gluon/config-mode/model/admin/network.lua @@ -0,0 +1,158 @@ +--[[ +Copyright 2014 Nils Schneider + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 +]]-- + +local uci = require("simple-uci").cursor() +local sysconfig = require 'gluon.sysconfig' +local util = require 'gluon.util' + +local wan = uci:get_all("network", "wan") +local wan6 = uci:get_all("network", "wan6") +local dns_static = uci:get_first("gluon-wan-dnsmasq", "static") + +local f = Form(translate("WAN connection")) + +local s = f:section(Section) + +local ipv4 = s:option(ListValue, "ipv4", translate("IPv4")) +ipv4:value("dhcp", translate("Automatic (DHCP)")) +ipv4:value("static", translate("Static")) +ipv4:value("none", translate("Disabled")) +ipv4.default = wan.proto + +local ipv4_addr = s:option(Value, "ipv4_addr", translate("IP address")) +ipv4_addr:depends(ipv4, "static") +ipv4_addr.default = wan.ipaddr +ipv4_addr.datatype = "ip4addr" + +local ipv4_netmask = s:option(Value, "ipv4_netmask", translate("Netmask")) +ipv4_netmask:depends(ipv4, "static") +ipv4_netmask.default = wan.netmask or "255.255.255.0" +ipv4_netmask.datatype = "ip4addr" + +local ipv4_gateway = s:option(Value, "ipv4_gateway", translate("Gateway")) +ipv4_gateway:depends(ipv4, "static") +ipv4_gateway.default = wan.gateway +ipv4_gateway.datatype = "ip4addr" + + +local s = f:section(Section) + +local ipv6 = s:option(ListValue, "ipv6", translate("IPv6")) +ipv6:value("dhcpv6", translate("Automatic (RA/DHCPv6)")) +ipv6:value("static", translate("Static")) +ipv6:value("none", translate("Disabled")) +ipv6.default = wan6.proto + +local ipv6_addr = s:option(Value, "ipv6_addr", translate("IP address")) +ipv6_addr:depends(ipv6, "static") +ipv6_addr.default = wan6.ip6addr +ipv6_addr.datatype = "ip6addr" + +local ipv6_gateway = s:option(Value, "ipv6_gateway", translate("Gateway")) +ipv6_gateway:depends(ipv6, "static") +ipv6_gateway.default = wan6.ip6gw +ipv6_gateway.datatype = "ip6addr" + +if dns_static then + local s = f:section(Section) + + local dns = s:option(DynamicList, "dns", translate("Static DNS servers")) + dns.default = uci:get_list("gluon-wan-dnsmasq", dns_static, "server") + dns.datatype = "ipaddr" + dns.optional = true + + function dns:write(data) + uci:set_list("gluon-wan-dnsmasq", dns_static, "server", data) + uci:commit("gluon-wan-dnsmasq") + end +end + +local s = f:section(Section) + +local mesh_wan = s:option(Flag, "mesh_wan", translate("Enable meshing on the WAN interface")) +mesh_wan.default = not uci:get_bool("network", "mesh_wan", "disabled") + +function mesh_wan:write(data) + uci:set("network", "mesh_wan", "disabled", not data) +end + +if sysconfig.lan_ifname then + local s = f:section(Section) + + local mesh_lan = s:option(Flag, "mesh_lan", translate("Enable meshing on the LAN interface")) + mesh_lan.default = not uci:get_bool("network", "mesh_lan", "disabled") + + function mesh_lan:write(data) + uci:set("network", "mesh_lan", "disabled", not data) + + local interfaces = uci:get_list("network", "client", "ifname") + + for lanif in sysconfig.lan_ifname:gmatch('%S+') do + if data then + util.remove_from_set(interfaces, lanif) + else + util.add_to_set(interfaces, lanif) + end + end + + uci:set_list("network", "client", "ifname", interfaces) + end +end + +local section +uci:foreach("system", "gpio_switch", function(s) + if s[".name"]:match("poe") then + if not section then + section = f:section(Section) + end + + local port = s.name:match("^PoE Power Port(%d*)$") + local name + if port then + name = translatef("Enable PoE Power Port %s", port) + else + name = translate("Enable " .. s.name) + end + local poe = section:option(Flag, s[".name"], name) + poe.default = uci:get_bool("system", s[".name"], "value") + + function poe:write(data) + uci:set("system", s[".name"], "value", data) + end + end +end) + +function f:write() + uci:set("network", "wan", "proto", ipv4.data) + if ipv4.data == "static" then + uci:set("network", "wan", "ipaddr", ipv4_addr.data) + uci:set("network", "wan", "netmask", ipv4_netmask.data) + uci:set("network", "wan", "gateway", ipv4_gateway.data) + else + uci:delete("network", "wan", "ipaddr") + uci:delete("network", "wan", "netmask") + uci:delete("network", "wan", "gateway") + end + + uci:set("network", "wan6", "proto", ipv6.data) + if ipv6.data == "static" then + uci:set("network", "wan6", "ip6addr", ipv6_addr.data) + uci:set("network", "wan6", "ip6gw", ipv6_gateway.data) + else + uci:delete("network", "wan6", "ip6addr") + uci:delete("network", "wan6", "ip6gw") + end + + + uci:commit("network") + uci:commit('system') +end + +return f diff --git a/package/gluon-web-node-role/Makefile b/package/gluon-web-node-role/Makefile new file mode 100644 index 00000000..81283761 --- /dev/null +++ b/package/gluon-web-node-role/Makefile @@ -0,0 +1,13 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-node-role +PKG_VERSION:=1 + +include ../gluon.mk + +define Package/gluon-web-node-role + DEPENDS:=+gluon-web-admin +gluon-node-info + TITLE:=UI for specifying node role +endef + +$(eval $(call BuildPackageGluon,gluon-web-node-role)) diff --git a/package/gluon-web-node-role/check_site.lua b/package/gluon-web-node-role/check_site.lua new file mode 100644 index 00000000..9bc5e25d --- /dev/null +++ b/package/gluon-web-node-role/check_site.lua @@ -0,0 +1,2 @@ +need_string(in_site({'roles', 'default'})) +need_string_array(in_site({'roles', 'list'})) diff --git a/package/gluon-luci-node-role/i18n/de.po b/package/gluon-web-node-role/i18n/de.po similarity index 54% rename from package/gluon-luci-node-role/i18n/de.po rename to package/gluon-web-node-role/i18n/de.po index e3037b26..969ca1cf 100644 --- a/package/gluon-luci-node-role/i18n/de.po +++ b/package/gluon-web-node-role/i18n/de.po @@ -17,11 +17,11 @@ msgid "Role" msgstr "Rolle" msgid "" -"If this node has a special role within the freifunk network you can specify " -"this role here. Please find out about the available roles and their impact " -"first. Only change the role if you know what you are doing." +"If this node has a special role within the mesh network you can specify this " +"role here. Please find out about the available roles and their impact first. " +"Only change the role if you know what you are doing." msgstr "" -"Wenn dein Freifunk-Knoten eine besondere Rolle im Freifunk Netz einnimmt, " +"Wenn dein Knoten eine besondere Rolle im Mesh-Netzwerk einnimmt, " "kannst du diese hier angeben. Bringe bitte zuvor in Erfahrung, welche " -"Auswirkungen die zur Verfügung stehenden Rollen im Freifunk-Netz haben. " -"Setze die Rolle nur, wenn du weißt was du machst." +"Bedeutung die zur Verfügung stehenden Rollen haben. " +"Setze die Rolle nur, wenn du weißt, was du tust." diff --git a/package/gluon-web-node-role/i18n/fr.po b/package/gluon-web-node-role/i18n/fr.po new file mode 100644 index 00000000..bebaa294 --- /dev/null +++ b/package/gluon-web-node-role/i18n/fr.po @@ -0,0 +1,27 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2015-08-19 23:30+0100\n" +"Last-Translator:Tobias Bernot \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Node role" +msgstr "Rôle du nœud" + +msgid "Role" +msgstr "Rôle" + +msgid "" +"If this node has a special role within the mesh network you can specify this " +"role here. Please find out about the available roles and their impact first. " +"Only change the role if you know what you are doing." +msgstr "" +"Si votre nœud a un rôle spécial dans le réseau MESH, vous pouvez " +"spécifier ce rôle ici. Avant de changer, informez vous sur les rôles " +"disponibles et sur leur impacts. Changez de rôle uniquement si vous " +"comprenez ce que vous faites." diff --git a/package/gluon-luci-node-role/i18n/gluon-luci-node-role.pot b/package/gluon-web-node-role/i18n/gluon-web-node-role.pot similarity index 72% rename from package/gluon-luci-node-role/i18n/gluon-luci-node-role.pot rename to package/gluon-web-node-role/i18n/gluon-web-node-role.pot index acf6dd79..027ae2e6 100644 --- a/package/gluon-luci-node-role/i18n/gluon-luci-node-role.pot +++ b/package/gluon-web-node-role/i18n/gluon-web-node-role.pot @@ -8,7 +8,7 @@ msgid "Role" msgstr "" msgid "" -"If this node has a special role within the freifunk network you can specify this role here. " +"If this node has a special role within the mesh network you can specify this role here. " "Please find out about the available roles and their impact first. " "Only change the role if you know what you are doing." msgstr "" diff --git a/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/controller/admin/noderole.lua b/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/controller/admin/noderole.lua new file mode 100644 index 00000000..b11dc50f --- /dev/null +++ b/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/controller/admin/noderole.lua @@ -0,0 +1,3 @@ +package 'gluon-web-node-role' + +entry({"admin", "noderole"}, model("admin/noderole"), "Node role", 60) diff --git a/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/model/admin/noderole.lua b/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/model/admin/noderole.lua new file mode 100644 index 00000000..5fe33459 --- /dev/null +++ b/package/gluon-web-node-role/luasrc/lib/gluon/config-mode/model/admin/noderole.lua @@ -0,0 +1,28 @@ +local f, s, o +local site = require 'gluon.site' +local uci = require("simple-uci").cursor() +local config = 'gluon-node-info' + +-- where to read the configuration from +local role = uci:get(config, uci:get_first(config, "system"), "role") + +f = Form(translate("Node role")) + +s = f:section(Section, nil, translate( + "If this node has a special role within the freifunk network you can specify this role here. " + .. "Please find out about the available roles and their impact first. " + .. "Only change the role if you know what you are doing." +)) + +o = s:option(ListValue, "role", translate("Role")) +o.default = role +for _, role in ipairs(site.roles.list()) do + o:value(role, translate('gluon-web-node-role:role:' .. role)) +end + +function o:write(data) + uci:set(config, uci:get_first(config, "system"), "role", data) + uci:commit(config) +end + +return f diff --git a/package/gluon-web-private-wifi/Makefile b/package/gluon-web-private-wifi/Makefile new file mode 100644 index 00000000..cff13fcb --- /dev/null +++ b/package/gluon-web-private-wifi/Makefile @@ -0,0 +1,14 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-private-wifi +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-private-wifi + DEPENDS:=+gluon-web-admin + TITLE:=UI for activating a private WLAN +endef + +$(eval $(call BuildPackageGluon,gluon-web-private-wifi)) diff --git a/package/gluon-luci-private-wifi/i18n/de.po b/package/gluon-web-private-wifi/i18n/de.po similarity index 94% rename from package/gluon-luci-private-wifi/i18n/de.po rename to package/gluon-web-private-wifi/i18n/de.po index 5b2ac19d..09ba09c2 100644 --- a/package/gluon-luci-private-wifi/i18n/de.po +++ b/package/gluon-web-private-wifi/i18n/de.po @@ -13,6 +13,12 @@ msgstr "" msgid "8-63 characters" msgstr "8-63 Zeichen" +msgid "Enabled" +msgstr "Aktiviert" + +msgid "Key" +msgstr "Schlüssel" + msgid "Name (SSID)" msgstr "Name (SSID)" diff --git a/package/gluon-luci-private-wifi/i18n/fr.po b/package/gluon-web-private-wifi/i18n/fr.po similarity index 77% rename from package/gluon-luci-private-wifi/i18n/fr.po rename to package/gluon-web-private-wifi/i18n/fr.po index c95ecd0a..5ea89c07 100644 --- a/package/gluon-luci-private-wifi/i18n/fr.po +++ b/package/gluon-web-private-wifi/i18n/fr.po @@ -13,11 +13,17 @@ msgstr "" msgid "8-63 characters" msgstr "8-63 charactères" +msgid "Enabled" +msgstr "Activé" + +msgid "Key" +msgstr "Clé" + msgid "Name (SSID)" msgstr "Nom (SSID)" msgid "Private WLAN" -msgstr "WLAN privé" +msgstr "Wi-Fi privé" msgid "" "Your node can additionally extend your private network by bridging the WAN " @@ -26,6 +32,6 @@ msgid "" "WAN interface should not be enabled at the same time." msgstr "" "Votre nœud peut étendre votre réseau privé en interfaçant le WAN avec un " -"WLAN séparé. Cette fonction est complètement indépendante de les fonctions " -"de MESH. Il ne faut pas activer la fonction de MESH et de WLAN privé en même " +"Wi-Fi séparé. Cette fonction est complètement indépendante de les fonctions " +"de MESH. Il ne faut pas activer la fonction de MESH et de Wi-Fi privé en même " "temps." diff --git a/package/gluon-luci-private-wifi/i18n/gluon-luci-private-wifi.pot b/package/gluon-web-private-wifi/i18n/gluon-web-private-wifi.pot similarity index 90% rename from package/gluon-luci-private-wifi/i18n/gluon-luci-private-wifi.pot rename to package/gluon-web-private-wifi/i18n/gluon-web-private-wifi.pot index 98d41bf8..0919ddb3 100644 --- a/package/gluon-luci-private-wifi/i18n/gluon-luci-private-wifi.pot +++ b/package/gluon-web-private-wifi/i18n/gluon-web-private-wifi.pot @@ -4,6 +4,12 @@ msgstr "Content-Type: text/plain; charset=UTF-8" msgid "8-63 characters" msgstr "" +msgid "Enabled" +msgstr "" + +msgid "Key" +msgstr "" + msgid "Name (SSID)" msgstr "" diff --git a/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/controller/admin/privatewifi.lua b/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/controller/admin/privatewifi.lua new file mode 100644 index 00000000..febfb4e4 --- /dev/null +++ b/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/controller/admin/privatewifi.lua @@ -0,0 +1,3 @@ +package 'gluon-web-private-wifi' + +entry({"admin", "privatewifi"}, model("admin/privatewifi"), _("Private WLAN"), 30) diff --git a/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/model/admin/privatewifi.lua b/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/model/admin/privatewifi.lua new file mode 100644 index 00000000..9f25bd12 --- /dev/null +++ b/package/gluon-web-private-wifi/luasrc/lib/gluon/config-mode/model/admin/privatewifi.lua @@ -0,0 +1,55 @@ +local uci = require("simple-uci").cursor() +local util = require 'gluon.util' + +-- where to read the configuration from +local primary_iface = 'wan_radio0' + +local f = Form(translate("Private WLAN")) + +local s = f:section(Section, nil, translate( + 'Your node can additionally extend your private network by bridging the WAN interface ' + .. 'with a separate WLAN. This feature is completely independent of the mesh functionality. ' + .. 'Please note that the private WLAN and meshing on the WAN interface should not be enabled ' + .. 'at the same time.' +)) + +local enabled = s:option(Flag, "enabled", translate("Enabled")) +enabled.default = uci:get('wireless', primary_iface) and not uci:get_bool('wireless', primary_iface, "disabled") + +local ssid = s:option(Value, "ssid", translate("Name (SSID)")) +ssid:depends(enabled, true) +ssid.datatype = "maxlength(32)" +ssid.default = uci:get('wireless', primary_iface, "ssid") + +local key = s:option(Value, "key", translate("Key"), translate("8-63 characters")) +key:depends(enabled, true) +key.datatype = "wpakey" +key.default = uci:get('wireless', primary_iface, "key") + +function f:write() + util.foreach_radio(uci, function(radio, index) + local radio_name = radio['.name'] + local name = "wan_" .. radio_name + + if enabled.data then + local macaddr = util.get_wlan_mac(uci, radio, index, 4) + + uci:section('wireless', "wifi-iface", name, { + device = radio_name, + network = "wan", + mode = 'ap', + encryption = 'psk2', + ssid = ssid.data, + key = key.data, + macaddr = macaddr, + disabled = false, + }) + else + uci:set('wireless', name, "disabled", true) + end + end) + + uci:commit('wireless') +end + +return f diff --git a/package/gluon-web-wifi-config/Makefile b/package/gluon-web-wifi-config/Makefile new file mode 100644 index 00000000..7827491e --- /dev/null +++ b/package/gluon-web-wifi-config/Makefile @@ -0,0 +1,14 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web-wifi-config +PKG_VERSION:=1 +PKG_RELEASE:=1 + +include ../gluon.mk + +define Package/gluon-web-wifi-config + DEPENDS:=+gluon-web-admin +libiwinfo-lua + TITLE:=UI for Wifi Settings +endef + +$(eval $(call BuildPackageGluon,gluon-web-wifi-config)) diff --git a/package/gluon-luci-wifi-config/i18n/de.po b/package/gluon-web-wifi-config/i18n/de.po similarity index 100% rename from package/gluon-luci-wifi-config/i18n/de.po rename to package/gluon-web-wifi-config/i18n/de.po diff --git a/package/gluon-luci-wifi-config/i18n/fr.po b/package/gluon-web-wifi-config/i18n/fr.po similarity index 95% rename from package/gluon-luci-wifi-config/i18n/fr.po rename to package/gluon-web-wifi-config/i18n/fr.po index 451772e7..b019e2fe 100644 --- a/package/gluon-luci-wifi-config/i18n/fr.po +++ b/package/gluon-web-wifi-config/i18n/fr.po @@ -13,10 +13,10 @@ msgid "(default)" msgstr "(défaut)" msgid "2.4GHz WLAN" -msgstr "2,4GHz-WLAN" +msgstr "2,4GHz Wi-Fi" msgid "5GHz WLAN" -msgstr "5GHz-WLAN" +msgstr "5GHz Wi-Fi" msgid "Enable client network (access point)" msgstr "Activer le réseau client (Access Point)" @@ -31,7 +31,7 @@ msgid "Transmission power" msgstr "Puissance d'émission" msgid "WLAN" -msgstr "WLAN" +msgstr "Wi-Fi" msgid "" "You can enable or disable your node's client and mesh network SSIDs here. " @@ -43,6 +43,6 @@ msgid "" msgstr "" "Ici vous pouvez activer ou désactiver la SSID du client ou MESH. " "Pensez a laisser la SSID du MESH activée pour que les autres nœuds puissent se connecter. " -"

Ici vous pouvez aussi configurer la puissance d'émmission se votre WLAN. " +"

Ici vous pouvez aussi configurer la puissance d'émmission se votre Wi-Fi. " "Prenez note que les valeurs fournies pour la puissance de transmission prennent " "en compte les gains fournis par l'antenne, et que ces valeurs ne sont pas toujours disponibles ou exactes." diff --git a/package/gluon-luci-wifi-config/i18n/gluon-luci-wifi-config.pot b/package/gluon-web-wifi-config/i18n/gluon-web-wifi-config.pot similarity index 100% rename from package/gluon-luci-wifi-config/i18n/gluon-luci-wifi-config.pot rename to package/gluon-web-wifi-config/i18n/gluon-web-wifi-config.pot diff --git a/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/controller/admin/wifi-config.lua b/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/controller/admin/wifi-config.lua new file mode 100644 index 00000000..4a0b5256 --- /dev/null +++ b/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/controller/admin/wifi-config.lua @@ -0,0 +1,3 @@ +package 'gluon-web-wifi-config' + +entry({"admin", "wifi-config"}, model("admin/wifi-config"), _("WLAN"), 20) diff --git a/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/model/admin/wifi-config.lua b/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/model/admin/wifi-config.lua new file mode 100644 index 00000000..0eaf4afa --- /dev/null +++ b/package/gluon-web-wifi-config/luasrc/lib/gluon/config-mode/model/admin/wifi-config.lua @@ -0,0 +1,105 @@ +local fs = require 'nixio.fs' +local iwinfo = require 'iwinfo' +local uci = require("simple-uci").cursor() +local util = require 'gluon.util' + + +local function txpower_list(phy) + local list = iwinfo.nl80211.txpwrlist(phy) or { } + local off = tonumber(iwinfo.nl80211.txpower_offset(phy)) or 0 + local new = { } + local prev = -1 + local _, val + for _, val in ipairs(list) do + local dbm = val.dbm + off + local mw = math.floor(10 ^ (dbm / 10)) + if mw ~= prev then + prev = mw + table.insert(new, { + display_dbm = dbm, + display_mw = mw, + driver_dbm = val.dbm, + }) + end + end + return new +end + + +local f = Form(translate("WLAN")) + +f:section(Section, nil, translate( + "You can enable or disable your node's client and mesh network " + .. "SSIDs here. Please don't disable the mesh network without " + .. "a good reason, so other nodes can mesh with yours.

" + .. "It is also possible to configure the WLAN adapters transmission power " + .. "here. Please note that the transmission power values include the antenna gain " + .. "where available, but there are many devices for which the gain is unavailable or inaccurate." +)) + + +uci:foreach('wireless', 'wifi-device', function(config) + local radio = config['.name'] + + local title + if config.hwmode == '11g' or config.hwmode == '11ng' then + title = translate("2.4GHz WLAN") + elseif config.hwmode == '11a' or config.hwmode == '11na' then + title = translate("5GHz WLAN") + else + return + end + + local p = f:section(Section, title) + + local function vif_option(t, msg) + if not uci:get('wireless', t .. '_' .. radio) then + return + end + + local o = p:option(Flag, radio .. '_' .. t .. '_enabled', msg) + o.default = not uci:get_bool('wireless', t .. '_' .. radio, 'disabled') + + function o:write(data) + uci:set('wireless', t .. '_' .. radio, 'disabled', not data) + end + end + + vif_option('client', translate('Enable client network (access point)')) + vif_option('mesh', translate("Enable mesh network (802.11s)")) + vif_option('ibss', translate("Enable mesh network (IBSS)")) + + local phy = util.find_phy(config) + if not phy then + return + end + + local txpowers = txpower_list(phy) + if #txpowers <= 1 then + return + end + + local tp = p:option(ListValue, radio .. '_txpower', translate("Transmission power")) + tp.default = uci:get('wireless', radio, 'txpower') or 'default' + + tp:value('default', translate("(default)")) + + table.sort(txpowers, function(a, b) return a.driver_dbm > b.driver_dbm end) + + for _, entry in ipairs(txpowers) do + tp:value(entry.driver_dbm, string.format("%i dBm (%i mW)", entry.display_dbm, entry.display_mw)) + end + + function tp:write(data) + if data == 'default' then + data = nil + end + uci:set('wireless', radio, 'txpower', data) + end +end) + +function f:write() + uci:commit('wireless') +end + +return f diff --git a/package/gluon-web/Makefile b/package/gluon-web/Makefile new file mode 100644 index 00000000..1ecca59e --- /dev/null +++ b/package/gluon-web/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-web +PKG_VERSION:=1 + +PKG_INSTALL:=1 + +include ../gluon.mk + +define Package/gluon-web + TITLE:=Minimal Lua web framework derived from LuCI + DEPENDS:=+lua-jsonc +luci-lib-nixio +endef + +define lang-config + +config GLUON_WEB_LANG_$(1) + bool "$(GLUON_LANG_$(1)) language support for gluon-web" + depends on PACKAGE_gluon-web + +endef + +define Package/gluon-web/config +$(foreach lang,$(GLUON_SUPPORTED_LANGS),$(call lang-config,$(lang))) +endef + +$(eval $(call BuildPackageGluon,gluon-web)) diff --git a/package/gluon-web/files/lib/gluon/web/view/error/404.html b/package/gluon-web/files/lib/gluon/web/view/error/404.html new file mode 100644 index 00000000..b2db7d0f --- /dev/null +++ b/package/gluon-web/files/lib/gluon/web/view/error/404.html @@ -0,0 +1,9 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +

404 <%:Not Found%>

+

<%:Sorry, the object you requested was not found.%>

+<%|message%> diff --git a/package/gluon-web/files/lib/gluon/web/view/error/500.html b/package/gluon-web/files/lib/gluon/web/view/error/500.html new file mode 100644 index 00000000..8f1532be --- /dev/null +++ b/package/gluon-web/files/lib/gluon/web/view/error/500.html @@ -0,0 +1,9 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +

500 <%:Internal Server Error%>

+

<%:Sorry, the server encountered an unexpected error.%>

+
<%|message%>
diff --git a/package/gluon-web/i18n/de.po b/package/gluon-web/i18n/de.po new file mode 100644 index 00000000..9481f60f --- /dev/null +++ b/package/gluon-web/i18n/de.po @@ -0,0 +1,24 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2013-03-29 12:13+0200\n" +"Last-Translator: Matthias Schiffer \n" +"Language-Team: German\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Internal Server Error" +msgstr "Interner Serverfehler" + +msgid "Not Found" +msgstr "Nicht Gefunden" + +msgid "Sorry, the object you requested was not found." +msgstr "Entschuldigung, das anfgeforderte Objekt wurde nicht gefunden." + +msgid "Sorry, the server encountered an unexpected error." +msgstr "" +"Entschuldigung, auf dem Server ist ein unerwarteter Fehler aufgetreten." diff --git a/package/gluon-web/i18n/fr.po b/package/gluon-web/i18n/fr.po new file mode 100644 index 00000000..631a80cb --- /dev/null +++ b/package/gluon-web/i18n/fr.po @@ -0,0 +1,23 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2013-12-22 17:11+0200\n" +"Last-Translator: goofy \n" +"Language-Team: French\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Internal Server Error" +msgstr "Erreur Serveur Interne" + +msgid "Not Found" +msgstr "Pas trouvé" + +msgid "Sorry, the object you requested was not found." +msgstr "Désolé, l'objet que vous avez demandé n'as pas été trouvé." + +msgid "Sorry, the server encountered an unexpected error." +msgstr "Désolé, le serveur à rencontré une erreur inattendue." diff --git a/package/gluon-web/i18n/gluon-web.pot b/package/gluon-web/i18n/gluon-web.pot new file mode 100644 index 00000000..d3b60ac0 --- /dev/null +++ b/package/gluon-web/i18n/gluon-web.pot @@ -0,0 +1,14 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +msgid "Internal Server Error" +msgstr "" + +msgid "Not Found" +msgstr "" + +msgid "Sorry, the object you requested was not found." +msgstr "" + +msgid "Sorry, the server encountered an unexpected error." +msgstr "" diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/cgi.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/cgi.lua new file mode 100644 index 00000000..8d8c648a --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/cgi.lua @@ -0,0 +1,35 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local nixio = require 'nixio' +local http = require 'gluon.web.http' +local dispatcher = require 'gluon.web.dispatcher' + +-- Limited source to avoid endless blocking +local function limitsource(handle, limit) + limit = limit or 0 + local BLOCKSIZE = 2048 + + return function() + if limit < 1 then + handle:close() + return nil + else + local read = (limit > BLOCKSIZE) and BLOCKSIZE or limit + limit = limit - read + + local chunk = handle:read(read) + if not chunk then handle:close() end + return chunk + end + end +end + +return function(config) + dispatcher(config, http.Http( + nixio.getenv(), + limitsource(io.stdin, tonumber(nixio.getenv("CONTENT_LENGTH"))), + io.stdout + )) +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/dispatcher.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/dispatcher.lua new file mode 100644 index 00000000..64449cd0 --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/dispatcher.lua @@ -0,0 +1,212 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008-2015 Jo-Philipp Wich +-- Copyright 2017-2018 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local fs = require "nixio.fs" +local json = require "jsonc" +local tpl = require "gluon.web.template" +local util = require "gluon.web.util" +local proto = require "gluon.web.http.protocol" + + +local function build_url(http, path) + return (http:getenv("SCRIPT_NAME") or "") .. "/" .. table.concat(path, "/") +end + + +local function set_language(renderer, accept) + local langs = {} + local weights = {} + local star = 0 + + local function add(lang, q) + if not weights[lang] then + table.insert(langs, lang) + weights[lang] = q + end + end + + for match in accept:gmatch("[^,]+") do + local lang = match:match('^%s*([^%s;_-]+)') + local q = tonumber(match:match(';q=(%S+)%s*$') or 1) + + if lang == '*' then + star = q + elseif lang and q > 0 then + add(lang, q) + end + end + + add('en', star) + + table.sort(langs, function(a, b) + return (weights[a] or 0) > (weights[b] or 0) + end) + + renderer.set_language(langs) +end + +local function dispatch(config, http, request) + local tree = {nodes={}} + local nodes = {[''] = tree} + + local function _node(path, create) + local name = table.concat(path, ".") + local c = nodes[name] + + if not c and create then + local last = table.remove(path) + local parent = _node(path, true) + + c = {nodes={}} + parent.nodes[last] = c + nodes[name] = c + end + return c + end + + -- Init template engine + local function attr(key, val) + if not val then + return '' + end + + if type(val) == "table" then + val = json.stringify(val) + end + + return string.format(' %s="%s"', key, util.pcdata(tostring(val))) + end + + local renderer = tpl(config, setmetatable({ + http = http, + request = request, + node = function(path) return _node({path}) end, + write = function(...) return http:write(...) end, + pcdata = util.pcdata, + urlencode = proto.urlencode, + attr = attr, + url = function(path) return build_url(http, path) end, + }, { __index = _G })) + + + local function createtree() + local base = config.base_path .. "/controller/" + + local function load_ctl(path) + local ctl = assert(loadfile(path)) + + local _pkg + + local subdisp = setmetatable({ + package = function(name) + _pkg = name + end, + + node = function(...) + return _node({...}) + end, + + entry = function(path, target, title, order) + local c = _node(path, true) + + c.target = target + c.title = title + c.order = order + c.pkg = _pkg + + return c + end, + + alias = function(...) + local req = {...} + return function() + http:redirect(build_url(http, req)) + end + end, + + call = function(func, ...) + local args = {...} + return function() + func(http, renderer, unpack(args)) + end + end, + + template = function(view, scope) + local pkg = _pkg + return function() + renderer.render_layout(view, scope, pkg) + end + end, + + model = function(name) + local pkg = _pkg + return function() + require('gluon.web.model')(config, http, renderer, name, pkg) + end + end, + + _ = function(text) + return text + end, + }, { __index = _G }) + + local env = setmetatable({}, { __index = subdisp }) + setfenv(ctl, env) + + ctl() + end + + for path in (fs.glob(base .. "*.lua") or function() end) do + load_ctl(path) + end + for path in (fs.glob(base .. "*/*.lua") or function() end) do + load_ctl(path) + end + end + + set_language(renderer, http:getenv("HTTP_ACCEPT_LANGUAGE") or "") + + createtree() + + + local node = _node(request) + + if not node or not node.target then + http:status(404, "Not Found") + renderer.render_layout("error/404", { + message = + "No page is registered at '/" .. table.concat(request, "/") .. "'.\n" .. + "If this URL belongs to an extension, make sure it is properly installed.\n", + }, 'gluon-web') + return + end + + http:parse_input(node.filehandler) + + local ok, err = pcall(node.target) + if not ok then + http:status(500, "Internal Server Error") + renderer.render_layout("error/500", { + message = + "Failed to execute dispatcher target for entry '/" .. table.concat(request, "/") .. "'.\n" .. + "The called action terminated with an exception:\n" .. tostring(err or "(unknown)"), + }, 'gluon-web') + end +end + +return function(config, http) + local request = {} + local pathinfo = proto.urldecode(http:getenv("PATH_INFO") or "", true) + for node in pathinfo:gmatch("[^/]+") do + table.insert(request, node) + end + + ok, err = pcall(dispatch, config, http, request) + if not ok then + http:status(500, "Internal Server Error") + http:prepare_content("text/plain") + http:write(err) + end +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http.lua new file mode 100644 index 00000000..2cf83de0 --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http.lua @@ -0,0 +1,123 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local string = string +local table = table +local nixio = require "nixio" +local protocol = require "gluon.web.http.protocol" +local util = require "gluon.web.util" + +local ipairs, pairs, tostring = ipairs, pairs, tostring + +module "gluon.web.http" + + +Http = util.class() +function Http:__init__(env, input, output) + self.input = input + self.output = output + + self.request = { + env = env, + headers = {}, + params = protocol.urldecode_params(env.QUERY_STRING or ""), + } + self.headers = {} +end + +local function push_headers(self) + if self.eoh then return end + + for _, header in pairs(self.headers) do + self.output:write(string.format("%s: %s\r\n", header[1], header[2])) + end + self.output:write("\r\n") + + self.eoh = true +end + +function Http:parse_input(filehandler) + protocol.parse_message_body( + self.input, + self.request, + filehandler + ) +end + +function Http:formvalue(name) + return self:formvaluetable(name)[1] +end + +function Http:formvaluetable(name) + return self.request.params[name] or {} +end + +function Http:getcookie(name) + local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") + local p = ";" .. name .. "=(.-);" + local i, j, value = c:find(p) + return value and urldecode(value) +end + +function Http:getenv(name) + return self.request.env[name] +end + +function Http:close() + if not self.output then return end + + push_headers(self) + + self.output:flush() + self.output:close() + self.output = nil +end + +function Http:header(key, value) + self.headers[key:lower()] = {key, value} +end + +function Http:prepare_content(mime) + if self.headers["content-type"] then return end + + if mime == "application/xhtml+xml" then + local accept = self:getenv("HTTP_ACCEPT") + if not accept or not accept:find("application/xhtml+xml", nil, true) then + mime = "text/html; charset=UTF-8" + end + self:header("Vary", "Accept") + end + self:header("Content-Type", mime) +end + +function Http:status(code, request) + if not self.output or self.code then return end + + code = code or 200 + request = request or "OK" + self.code = code + self.output:write(string.format("Status: %i %s\r\n", code, request)) +end + +function Http:write(content) + if not self.output then return end + + self:status() + + self:prepare_content("text/html; charset=utf-8") + + if not self.headers["cache-control"] then + self:header("Cache-Control", "no-cache") + self:header("Expires", "0") + end + + push_headers(self) + self.output:write(content) +end + +function Http:redirect(url) + self:status(302, "Found") + self:header("Location", url) + self:close() +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http/protocol.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http/protocol.lua new file mode 100644 index 00000000..b0a2ad1e --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/http/protocol.lua @@ -0,0 +1,268 @@ +-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich +-- Copyright 2017 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +-- This class contains several functions useful for http message- and content +-- decoding and to retrive form data from raw http messages. +module("gluon.web.http.protocol", package.seeall) + + +HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size + + +local function pump(src, snk) + while true do + local chunk, src_err = src() + local ret, snk_err = snk(chunk, src_err) + + if not (chunk and ret) then + local err = src_err or snk_err + if err then + return nil, err + else + return true + end + end + end +end + +function urlencode(s) + return (string.gsub(s, '[^a-zA-Z0-9%-_%.~]', + function(c) + local ret = '' + + for i = 1, string.len(c) do + ret = ret .. string.format('%%%02X', string.byte(c, i, i)) + end + + return ret + end + )) +end + +-- the "+" sign to " " - and return the decoded string. +function urldecode(str, no_plus) + + local function chrdec(hex) + return string.char(tonumber(hex, 16)) + end + + if type(str) == "string" then + if not no_plus then + str = str:gsub("+", " ") + end + + str = str:gsub("%%(%x%x)", chrdec) + end + + return str +end + +local function initval(tbl, key) + if not tbl[key] then + tbl[key] = {} + end + + table.insert(tbl[key], "") +end + +local function appendval(tbl, key, chunk) + local t = tbl[key] + t[#t] = t[#t] .. chunk +end + +-- from given url or string. Returns a table with urldecoded values. +-- Simple parameters are stored as string values associated with the parameter +-- name within the table. Parameters with multiple values are stored as array +-- containing the corresponding values. +function urldecode_params(url) + local params = {} + + if url:find("?") then + url = url:gsub("^.+%?([^?]+)", "%1") + end + + for pair in url:gmatch("[^&;]+") do + + -- find key and value + local key = urldecode(pair:match("^([^=]+)")) + local val = urldecode(pair:match("^[^=]+=(.+)$")) + + -- store + if key and key:len() > 0 then + initval(params, key) + if val then + appendval(params, key, val) + end + end + end + + return params +end + +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table withing the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- If an optional file callback function is given then it is feeded with the +-- file contents chunk by chunk and only the extracted file name is stored +-- within the params table. The callback function will be called subsequently +-- with three arguments: +-- o Table containing decoded (name, file) and raw (headers) mime header data +-- o String value containing a chunk of the file data +-- o Boolean which indicates wheather the current chunk is the last one (eof) +function mimedecode_message_body(src, msg, filecb) + + if msg and msg.env.CONTENT_TYPE then + msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$") + end + + if not msg.mime_boundary then + return nil, "Invalid Content-Type found" + end + + + local tlen = 0 + local inhdr = false + local field = nil + local store = nil + local lchunk = nil + + local function parse_headers(chunk, field) + local stat + repeat + chunk, stat = chunk:gsub( + "^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n", + function(k,v) + field.headers[k] = v + return "" + end + ) + until stat == 0 + + chunk, stat = chunk:gsub("^\r\n","") + + -- End of headers + if stat > 0 then + if field.headers["Content-Disposition"] then + if field.headers["Content-Disposition"]:match("^form%-data; ") then + field.name = field.headers["Content-Disposition"]:match('name="(.-)"') + field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$') + end + end + + if not field.headers["Content-Type"] then + field.headers["Content-Type"] = "text/plain" + end + + + if field.name then + initval(msg.params, field.name) + if field.file then + appendval(msg.params, field.name, field.file) + store = filecb + else + store = function(hdr, buf, eof) + appendval(msg.params, field.name, buf) + end + end + else + store = nil + end + + return chunk, true + end + + return chunk, false + end + + local function snk(chunk) + + tlen = tlen + (chunk and #chunk or 0) + + if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then + return nil, "Message body size exceeds Content-Length" + end + + if chunk and not lchunk then + lchunk = "\r\n" .. chunk + + elseif lchunk then + local data = lchunk .. (chunk or "") + local spos, epos, found + + repeat + spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "\r\n", 1, true) + + if not spos then + spos, epos = data:find("\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true) + end + + + if spos then + local predata = data:sub(1, spos - 1) + + if inhdr then + predata, eof = parse_headers(predata, field) + + if not eof then + return nil, "Invalid MIME section header" + elseif not field.name then + return nil, "Invalid Content-Disposition header" + end + end + + if store then + store(field, predata, true) + end + + + field = { headers = { } } + found = true + + data, eof = parse_headers(data:sub(epos + 1, #data), field) + inhdr = not eof + end + until not spos + + if found then + -- We found at least some boundary. Save + -- the unparsed remaining data for the + -- next chunk. + lchunk, data = data, nil + else + -- There was a complete chunk without a boundary. Parse it as headers or + -- append it as data, depending on our current state. + if inhdr then + lchunk, eof = parse_headers(data, field) + inhdr = not eof + else + -- We're inside data, so append the data. Note that we only append + -- lchunk, not all of data, since there is a chance that chunk + -- contains half a boundary. Assuming that each chunk is at least the + -- boundary in size, this should prevent problems + if store then + store(field, lchunk, false) + end + lchunk, chunk = chunk, nil + end + end + end + + return true + end + + return pump(src, snk) +end + +-- This function will examine the Content-Type within the given message object +-- to select the appropriate content decoder. +-- Currently only the multipart/form-data mime type is supported. +function parse_message_body(src, msg, filecb) + if not (msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE) then + return + end + + if msg.env.CONTENT_TYPE:match("^multipart/form%-data") then + return mimedecode_message_body(src, msg, filecb) + end +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/i18n.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/i18n.lua new file mode 100644 index 00000000..ad42c3a3 --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/i18n.lua @@ -0,0 +1,57 @@ +-- Copyright 2018 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local tparser = require "gluon.web.template.parser" +local fs = require "nixio.fs" + + +return function(config) + local i18ndir = config.base_path .. "/i18n" + + + local function i18n_file(lang, pkg) + return string.format('%s/%s.%s.lmo', i18ndir, pkg, lang) + end + + local function no_translation(key) + return nil + end + + local function load_catalog(lang, pkg) + if pkg then + local file = i18n_file(lang, pkg) + local cat = fs.access(file) and tparser.load_catalog(file) + + if cat then return cat end + end + + return no_translation + end + + + local i18n = {} + + function i18n.supported(lang) + return lang == 'en' or fs.access(i18n_file(lang, 'gluon-web')) + end + + function i18n.load(lang, pkg) + local _translate = load_catalog(lang, pkg) + + local function translate(key) + return _translate(key) or key + end + + local function translatef(key, ...) + return translate(key):format(...) + end + + return { + _translate = _translate, + translate = translate, + translatef = translatef, + } + end + + return i18n +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/template.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/template.lua new file mode 100644 index 00000000..84a9b5c1 --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/template.lua @@ -0,0 +1,108 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017-2018 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local tparser = require 'gluon.web.template.parser' + +local tostring, ipairs, setmetatable, setfenv = tostring, ipairs, setmetatable, setfenv +local pcall, assert = pcall, assert + + +return function(config, env) + local i18n = require('gluon.web.i18n')(config) + + local viewdir = config.base_path .. '/view/' + + local ctx = {} + + local language = 'en' + local catalogs = {} + + function ctx.set_language(langs) + for _, lang in ipairs(langs) do + if i18n.supported(lang) then + language = lang + catalogs = {} + return + end + end + end + + function ctx.i18n(pkg) + local cat = catalogs[pkg] or i18n.load(language, pkg) + if pkg then catalogs[pkg] = cat end + return cat + end + + local function render_template(name, template, scope, pkg) + scope = scope or {} + local t = ctx.i18n(pkg) + + local locals = { + renderer = ctx, + i18n = ctx.i18n, + translate = t.translate, + translatef = t.translatef, + _translate = t._translate, + include = function(name) + ctx.render(name, scope, pkg) + end, + } + + setfenv(template, setmetatable({}, { + __index = function(tbl, key) + return scope[key] or locals[key] or env[key] + end + })) + + -- Now finally render the thing + local stat, err = pcall(template) + assert(stat, "Failed to execute template '" .. name .. "'.\n" .. + "A runtime error occured: " .. tostring(err or "(nil)")) + end + + --- Render a certain template. + -- @param name Template name + -- @param scope Scope to assign to template (optional) + -- @param pkg i18n namespace package (optional) + function ctx.render(name, scope, pkg) + local sourcefile = viewdir .. name .. ".html" + local template, _, err = tparser.parse(sourcefile) + + assert(template, "Failed to load template '" .. name .. "'.\n" .. + "Error while parsing template '" .. sourcefile .. "':\n" .. + (err or "Unknown syntax error")) + + render_template(name, template, scope, pkg) + end + + --- Render a template from a string. + -- @param template Template string + -- @param scope Scope to assign to template (optional) + -- @param pkg i18n namespace package (optional) + function ctx.render_string(str, scope, pkg) + local template, _, err = tparser.parse_string(str) + + assert(template, "Error while parsing template:\n" .. + (err or "Unknown syntax error")) + + render_template('(local)', template, scope, pkg) + end + + --- Render a template, wrapped in the configured layout. + -- @param name Template name + -- @param scope Scope to assign to template (optional) + -- @param pkg i18n namespace package (optional) + -- @param layout_scope Additional variables to pass to the layout template + function ctx.render_layout(name, scope, pkg, layout_scope) + ctx.render(config.layout_template, setmetatable({ + content = name, + scope = scope, + pkg = pkg, + }, { + __index = layout_scope + }), config.layout_package) + end + + return ctx +end diff --git a/package/gluon-web/luasrc/usr/lib/lua/gluon/web/util.lua b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/util.lua new file mode 100644 index 00000000..045a16fb --- /dev/null +++ b/package/gluon-web/luasrc/usr/lib/lua/gluon/web/util.lua @@ -0,0 +1,61 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2017 Matthias Schiffer +-- Licensed to the public under the Apache License 2.0. + +local tparser = require "gluon.web.template.parser" + +local getmetatable, setmetatable = getmetatable, setmetatable +local tostring = tostring + +module "gluon.web.util" + +-- +-- Class helper routines +-- + +-- Instantiates a class +local function _instantiate(class, ...) + local inst = setmetatable({}, {__index = class}) + + if inst.__init__ then + inst:__init__(...) + end + + return inst +end + +-- The class object can be instantiated by calling itself. +-- Any class functions or shared parameters can be attached to this object. +-- Attaching a table to the class object makes this table shared between +-- all instances of this class. For object parameters use the __init__ function. +-- Classes can inherit member functions and values from a base class. +-- Class can be instantiated by calling them. All parameters will be passed +-- to the __init__ function of this class - if such a function exists. +-- The __init__ function must be used to set any object parameters that are not shared +-- with other objects of this class. Any return values will be ignored. +function class(base) + return setmetatable({}, { + __call = _instantiate, + __index = base + }) +end + +function instanceof(object, class) + while object do + if object == class then + return true + end + local mt = getmetatable(object) + object = mt and mt.__index + end + return false +end + + +-- +-- String and data manipulation routines +-- + +function pcdata(value) + return value and tparser.pcdata(tostring(value)) +end diff --git a/package/gluon-web/src/Makefile b/package/gluon-web/src/Makefile new file mode 100644 index 00000000..90b952f0 --- /dev/null +++ b/package/gluon-web/src/Makefile @@ -0,0 +1,16 @@ +all: compile + +%.o: %.c + $(CC) $(CPPFLAGS) $(CFLAGS) -D_GNU_SOURCE -std=c99 -Wall -Wextra -fPIC -fvisibility=hidden -c -o $@ $< + +clean: + rm -f parser.so *.o + +parser.so: template_parser.o template_utils.o template_lmo.o template_lualib.o + $(CC) $(LDFLAGS) -shared -o $@ $^ + +compile: parser.so + +install: compile + mkdir -p $(DESTDIR)/usr/lib/lua/gluon/web/template + cp parser.so $(DESTDIR)/usr/lib/lua/gluon/web/template/parser.so diff --git a/package/gluon-web/src/template_lmo.c b/package/gluon-web/src/template_lmo.c new file mode 100644 index 00000000..0a86bbc9 --- /dev/null +++ b/package/gluon-web/src/template_lmo.c @@ -0,0 +1,186 @@ +/* + * lmo - Lua Machine Objects - Base functions + * + * Copyright (C) 2009-2010 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "template_lmo.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +struct lmo_entry { + uint32_t key_id; + uint32_t val_id; + uint32_t offset; + uint32_t length; +} __attribute__((packed)); + + +static inline uint16_t get_le16(const void *data) { + const uint8_t *d = data; + return (((uint16_t)d[1]) << 8) | d[0]; +} + +static inline uint32_t get_be32(const void *data) { + const uint8_t *d = data; + return (((uint32_t)d[0]) << 24) + | (((uint32_t)d[1]) << 16) + | (((uint32_t)d[2]) << 8) + | d[3]; +} + +/* + * Hash function from http://www.azillionmonkeys.com/qed/hash.html + * Copyright (C) 2004-2008 by Paul Hsieh + */ +static uint32_t sfh_hash(const void *input, size_t len) +{ + const uint8_t *data = input; + uint32_t hash = len, tmp; + + /* Main loop */ + for (; len > 3; len -= 4) { + hash += get_le16(data); + tmp = (get_le16(data+2) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 4; + hash += hash >> 11; + } + + /* Handle end cases */ + switch (len) { + case 3: hash += get_le16(data); + hash ^= hash << 16; + hash ^= data[2] << 18; + hash += hash >> 11; + break; + case 2: hash += get_le16(data); + hash ^= hash << 11; + hash += hash >> 17; + break; + case 1: hash += *data; + hash ^= hash << 10; + hash += hash >> 1; + } + + /* Force "avalanching" of final 127 bits */ + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + + return hash; +} + +bool lmo_load(lmo_catalog_t *cat, const char *file) +{ + int fd = -1; + struct stat s; + + cat->data = MAP_FAILED; + + fd = open(file, O_RDONLY|O_CLOEXEC); + if (fd < 0) + goto err; + + if (fstat(fd, &s)) + goto err; + + cat->data = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); + + close(fd); + fd = -1; + + if (cat->data == MAP_FAILED) + goto err; + + cat->end = cat->data + s.st_size; + + uint32_t idx_offset = get_be32(cat->end - sizeof(uint32_t)); + cat->index = (const lmo_entry_t *)(cat->data + idx_offset); + + if ((const char *)cat->index > (cat->end - sizeof(uint32_t))) + goto err; + + cat->length = (cat->end - sizeof(uint32_t) - (const char *)cat->index) / sizeof(lmo_entry_t); + + return true; + +err: + if (fd >= 0) + close(fd); + + if (cat->data != MAP_FAILED) + munmap(cat->data, cat->end - cat->data); + + return false; +} + +void lmo_unload(lmo_catalog_t *cat) +{ + if (cat->data != MAP_FAILED) + munmap(cat->data, cat->end - cat->data); +} + + +static int lmo_compare_entry(const void *a, const void *b) +{ + const lmo_entry_t *ea = a, *eb = b; + uint32_t ka = ntohl(ea->key_id), kb = ntohl(eb->key_id); + + if (ka < kb) + return -1; + else if (ka > kb) + return 1; + else + return 0; +} + +static const lmo_entry_t * lmo_find_entry(const lmo_catalog_t *cat, uint32_t hash) +{ + lmo_entry_t key; + key.key_id = htonl(hash); + + return bsearch(&key, cat->index, cat->length, sizeof(lmo_entry_t), lmo_compare_entry); +} + +bool lmo_translate(const lmo_catalog_t *cat, const char *key, size_t keylen, const char **out, size_t *outlen) +{ + uint32_t hash = sfh_hash(key, keylen); + const lmo_entry_t *e = lmo_find_entry(cat, hash); + if (!e) + return false; + + *out = cat->data + ntohl(e->offset); + *outlen = ntohl(e->length); + + if (*out + *outlen > cat->end) + return false; + + return true; +} diff --git a/package/gluon-web/src/template_lmo.h b/package/gluon-web/src/template_lmo.h new file mode 100644 index 00000000..4af6cac1 --- /dev/null +++ b/package/gluon-web/src/template_lmo.h @@ -0,0 +1,44 @@ +/* + * lmo - Lua Machine Objects - General header + * + * Copyright (C) 2009-2012 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TEMPLATE_LMO_H_ +#define _TEMPLATE_LMO_H_ + +#include +#include + + +typedef struct lmo_entry lmo_entry_t; + + +struct lmo_catalog { + size_t length; + const lmo_entry_t *index; + char *data; + const char *end; +}; + +typedef struct lmo_catalog lmo_catalog_t; + + +bool lmo_load(lmo_catalog_t *cat, const char *file); +void lmo_unload(lmo_catalog_t *cat); +bool lmo_translate(const lmo_catalog_t *cat, const char *key, size_t keylen, const char **out, size_t *outlen); + +#endif diff --git a/package/gluon-web/src/template_lualib.c b/package/gluon-web/src/template_lualib.c new file mode 100644 index 00000000..308011f9 --- /dev/null +++ b/package/gluon-web/src/template_lualib.c @@ -0,0 +1,150 @@ +/* + * gluon-web Template - Lua binding + * + * Copyright (C) 2009 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "template_parser.h" +#include "template_utils.h" +#include "template_lmo.h" + +#include +#include + +#include +#include +#include + + +#define TEMPLATE_CATALOG "gluon.web.template.parser.catalog" + + +static int template_L_do_parse(lua_State *L, struct template_parser *parser, const char *chunkname) +{ + int lua_status, rv; + + if (!parser) + { + lua_pushnil(L); + lua_pushinteger(L, errno); + lua_pushstring(L, strerror(errno)); + return 3; + } + + lua_status = lua_load(L, template_reader, parser, chunkname); + + if (lua_status == 0) + rv = 1; + else + rv = template_error(L, parser); + + template_close(parser); + + return rv; +} + +static int template_L_parse(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + struct template_parser *parser = template_open(file); + + return template_L_do_parse(L, parser, file); +} + +static int template_L_parse_string(lua_State *L) +{ + size_t len; + const char *str = luaL_checklstring(L, 1, &len); + struct template_parser *parser = template_string(str, len); + + return template_L_do_parse(L, parser, "[string]"); +} + +static int template_L_pcdata(lua_State *L) +{ + size_t inlen, outlen; + char *out; + const char *in = luaL_checklstring(L, 1, &inlen); + if (!pcdata(in, inlen, &out, &outlen)) + return 0; + + lua_pushlstring(L, out, outlen); + free(out); + + return 1; +} + +static int template_L_load_catalog(lua_State *L) +{ + const char *file = luaL_checkstring(L, 1); + + lmo_catalog_t *cat = lua_newuserdata(L, sizeof(*cat)); + if (!lmo_load(cat, file)) { + lua_pop(L, 1); + return 0; + } + + luaL_getmetatable(L, TEMPLATE_CATALOG); + lua_setmetatable(L, -2); + + return 1; +} + +static int template_catalog_call(lua_State *L) +{ + size_t inlen, outlen; + lmo_catalog_t *cat = luaL_checkudata(L, 1, TEMPLATE_CATALOG); + const char *in = luaL_checklstring(L, 2, &inlen), *out; + if (!lmo_translate(cat, in, inlen, &out, &outlen)) + return 0; + + lua_pushlstring(L, out, outlen); + + return 1; +} + +static int template_catalog_gc(lua_State *L) +{ + lmo_catalog_t *cat = luaL_checkudata(L, 1, TEMPLATE_CATALOG); + lmo_unload(cat); + + return 0; +} + +static const luaL_reg R[] = { + { "parse", template_L_parse }, + { "parse_string", template_L_parse_string }, + { "pcdata", template_L_pcdata }, + { "load_catalog", template_L_load_catalog }, + {} +}; + +static const luaL_reg template_catalog_methods[] = { + { "__call", template_catalog_call }, + { "__gc", template_catalog_gc }, + {} +}; + +__attribute__ ((visibility("default"))) +LUALIB_API int luaopen_gluon_web_template_parser(lua_State *L) { + luaL_register(L, "gluon.web.template.parser", R); + + luaL_newmetatable(L, TEMPLATE_CATALOG); + luaL_register(L, NULL, template_catalog_methods); + lua_pop(L, 1); + + return 1; +} diff --git a/package/gluon-web/src/template_parser.c b/package/gluon-web/src/template_parser.c new file mode 100644 index 00000000..d71afe72 --- /dev/null +++ b/package/gluon-web/src/template_parser.c @@ -0,0 +1,424 @@ +/* + * gluon-web Template - Parser implementation + * + * Copyright (C) 2009-2012 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "template_parser.h" +#include "template_utils.h" +#include "template_lmo.h" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + + +typedef enum { + T_TYPE_INIT, + T_TYPE_TEXT, + T_TYPE_COMMENT, + T_TYPE_EXPR, + T_TYPE_EXPR_RAW, + T_TYPE_INCLUDE, + T_TYPE_I18N, + T_TYPE_I18N_RAW, + T_TYPE_CODE, + T_TYPE_EOF, +} t_type_t; + + +struct template_chunk { + const char *s; + const char *e; + t_type_t type; + int line; +}; + +/* parser state */ +struct template_parser { + size_t size; + char *data; + char *off; + char *lua_chunk; + int line; + int in_expr; + bool strip_before; + bool strip_after; + struct template_chunk prv_chunk; + struct template_chunk cur_chunk; + const char *file; +}; + + +/* leading and trailing code for different types */ +static const char *const gen_code[][2] = { + [T_TYPE_INIT] = {NULL, NULL}, + [T_TYPE_TEXT] = {"write('", "')"}, + [T_TYPE_COMMENT] = {NULL, NULL}, + [T_TYPE_EXPR] = {"write(pcdata(tostring(", " or '')))"}, + [T_TYPE_EXPR_RAW] = {"write(tostring(", " or ''))"}, + [T_TYPE_INCLUDE] = {"include('", "')"}, + [T_TYPE_I18N] = {"write(pcdata(translate('", "')))"}, + [T_TYPE_I18N_RAW] = {"write(translate('", "'))"}, + [T_TYPE_CODE] = {NULL, " "}, + [T_TYPE_EOF] = {NULL, NULL}, +}; + +static struct template_parser * template_init(struct template_parser *parser) +{ + parser->off = parser->data; + parser->cur_chunk.type = T_TYPE_INIT; + parser->cur_chunk.s = parser->data; + parser->cur_chunk.e = parser->data; + + return parser; +} + +struct template_parser * template_open(const char *file) +{ + int fd = -1; + struct stat s; + struct template_parser *parser; + + if (!(parser = calloc(1, sizeof(*parser)))) + goto err; + + parser->file = file; + + fd = open(file, O_RDONLY|O_CLOEXEC); + if (fd < 0) + goto err; + + if (fstat(fd, &s)) + goto err; + + parser->size = s.st_size; + parser->data = mmap(NULL, parser->size, PROT_READ, MAP_PRIVATE, + fd, 0); + + close(fd); + fd = -1; + + if (parser->data == MAP_FAILED) + goto err; + + return template_init(parser); + +err: + if (fd >= 0) + close(fd); + template_close(parser); + return NULL; +} + +struct template_parser * template_string(const char *str, size_t len) +{ + struct template_parser *parser; + + if (!(parser = calloc(1, sizeof(*parser)))) + goto err; + + parser->size = len; + parser->data = (char *)str; + + return template_init(parser); + +err: + template_close(parser); + return NULL; +} + +void template_close(struct template_parser *parser) +{ + if (!parser) + return; + + free(parser->lua_chunk); + + /* if file is not set, we were parsing a string */ + if (parser->file) { + if ((parser->data != NULL) && (parser->data != MAP_FAILED)) + munmap(parser->data, parser->size); + } + + free(parser); +} + +static void template_text(struct template_parser *parser, const char *e) +{ + const char *s = parser->off; + + if (s < (parser->data + parser->size)) { + if (parser->strip_after) { + while ((s < e) && isspace(s[0])) + s++; + } + + parser->cur_chunk.type = T_TYPE_TEXT; + } else { + parser->cur_chunk.type = T_TYPE_EOF; + } + + parser->cur_chunk.line = parser->line; + parser->cur_chunk.s = s; + parser->cur_chunk.e = e; +} + +static void template_code(struct template_parser *parser, const char *e) +{ + const char *s = parser->off; + + parser->strip_before = false; + parser->strip_after = false; + + if (s < e && s[0] == '-') { + parser->strip_before = true; + s++; + } + + if (s < e && e[-1] == '-') { + parser->strip_after = true; + e--; + } + + switch (*s) { + /* comment */ + case '#': + s++; + parser->cur_chunk.type = T_TYPE_COMMENT; + break; + + /* include */ + case '+': + s++; + parser->cur_chunk.type = T_TYPE_INCLUDE; + break; + + /* translate */ + case ':': + s++; + parser->cur_chunk.type = T_TYPE_I18N; + break; + + /* translate raw */ + case '_': + s++; + parser->cur_chunk.type = T_TYPE_I18N_RAW; + break; + + /* expr */ + case '|': + s++; + parser->cur_chunk.type = T_TYPE_EXPR; + break; + + /* expr raw */ + case '=': + s++; + parser->cur_chunk.type = T_TYPE_EXPR_RAW; + break; + + /* code */ + default: + parser->cur_chunk.type = T_TYPE_CODE; + } + + parser->cur_chunk.line = parser->line; + parser->cur_chunk.s = s; + parser->cur_chunk.e = e; +} + +static void luastr_escape(struct template_buffer *out, const char *s, const char *e) +{ + for (const char *ptr = s; ptr < e; ptr++) { + switch (*ptr) { + case '\\': + buf_append(out, "\\\\", 2); + break; + + case '\'': + buf_append(out, "\\\'", 2); + break; + + case '\n': + buf_append(out, "\\n", 2); + break; + + default: + buf_putchar(out, *ptr); + } + } +} + +static struct template_buffer * template_format_chunk(struct template_parser *parser) +{ + const char *p; + const char *head, *tail; + struct template_chunk *c = &parser->prv_chunk; + + if (parser->strip_before && c->type == T_TYPE_TEXT) { + while ((c->e > c->s) && isspace(c->e[-1])) + c->e--; + } + + /* empty chunk */ + if (c->type == T_TYPE_EOF) + return NULL; + + struct template_buffer *buf = buf_init(c->e - c->s); + if (!buf) + return NULL; + + if (c->e > c->s) { + if ((head = gen_code[c->type][0]) != NULL) + buf_append(buf, head, strlen(head)); + + switch (c->type) { + case T_TYPE_TEXT: + case T_TYPE_INCLUDE: + case T_TYPE_I18N: + case T_TYPE_I18N_RAW: + luastr_escape(buf, c->s, c->e); + break; + + case T_TYPE_EXPR: + case T_TYPE_EXPR_RAW: + buf_append(buf, c->s, c->e - c->s); + for (p = c->s; p < c->e; p++) + parser->line += (*p == '\n'); + break; + + case T_TYPE_CODE: + buf_append(buf, c->s, c->e - c->s); + for (p = c->s; p < c->e; p++) + parser->line += (*p == '\n'); + break; + + case T_TYPE_INIT: + case T_TYPE_COMMENT: + case T_TYPE_EOF: + break; + } + + if ((tail = gen_code[c->type][1]) != NULL) + buf_append(buf, tail, strlen(tail)); + } + + return buf; +} + +const char * template_reader(lua_State *L __attribute__((unused)), void *ud, size_t *sz) +{ + struct template_parser *parser = ud; + + /* free previous chunk */ + free(parser->lua_chunk); + parser->lua_chunk = NULL; + + while (true) { + int rem = parser->size - (parser->off - parser->data); + char *tag; + + parser->prv_chunk = parser->cur_chunk; + + /* before tag */ + if (!parser->in_expr) { + if ((tag = memmem(parser->off, rem, "<%", 2)) != NULL) { + template_text(parser, tag); + parser->off = tag + 2; + parser->in_expr = 1; + } else { + template_text(parser, parser->data + parser->size); + parser->off = parser->data + parser->size; + } + } + + /* inside tag */ + else { + if ((tag = memmem(parser->off, rem, "%>", 2)) != NULL) { + template_code(parser, tag); + parser->off = tag + 2; + parser->in_expr = 0; + } else { + /* unexpected EOF */ + template_code(parser, parser->data + parser->size); + + *sz = 1; + return "\033"; + } + } + + struct template_buffer *buf = template_format_chunk(parser); + if (!buf) + return NULL; + + *sz = buf_length(buf); + if (*sz) { + parser->lua_chunk = buf_destroy(buf); + return parser->lua_chunk; + } + } +} + +int template_error(lua_State *L, struct template_parser *parser) +{ + const char *err = luaL_checkstring(L, -1); + const char *off = parser->prv_chunk.s; + const char *ptr; + char msg[1024]; + int line = 0; + int chunkline = 0; + + if ((ptr = memmem(err, strlen(err), "]:", 2)) != NULL) { + chunkline = atoi(ptr + 2) - parser->prv_chunk.line; + + while (*ptr) { + if (*ptr++ == ' ') { + err = ptr; + break; + } + } + } + + if (memmem(err, strlen(err), "'char(27)'", 10) != NULL) { + off = parser->data + parser->size; + err = "'%>' expected before end of file"; + chunkline = 0; + } + + for (ptr = parser->data; ptr < off; ptr++) { + if (*ptr == '\n') + line++; + } + + snprintf(msg, sizeof(msg), "Syntax error in %s:%d: %s", + parser->file ?: "[string]", line + chunkline, err ?: "(unknown error)"); + + lua_pushnil(L); + lua_pushinteger(L, line + chunkline); + lua_pushstring(L, msg); + + return 3; +} diff --git a/package/gluon-web/src/template_parser.h b/package/gluon-web/src/template_parser.h new file mode 100644 index 00000000..4a04be75 --- /dev/null +++ b/package/gluon-web/src/template_parser.h @@ -0,0 +1,36 @@ +/* + * gluon-web Template - Parser header + * + * Copyright (C) 2009 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TEMPLATE_PARSER_H_ +#define _TEMPLATE_PARSER_H_ + +#include + + +struct template_parser; + + +struct template_parser * template_open(const char *file); +struct template_parser * template_string(const char *str, size_t len); +void template_close(struct template_parser *parser); + +const char *template_reader(lua_State *L, void *ud, size_t *sz); +int template_error(lua_State *L, struct template_parser *parser); + +#endif diff --git a/package/gluon-web/src/template_utils.c b/package/gluon-web/src/template_utils.c new file mode 100644 index 00000000..f8ea276f --- /dev/null +++ b/package/gluon-web/src/template_utils.c @@ -0,0 +1,310 @@ +/* + * gluon-web Template - Utility functions + * + * Copyright (C) 2010 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "template_utils.h" +#include "template_lmo.h" + +#include +#include +#include + +/* initialize a buffer object */ +struct template_buffer * buf_init(size_t size) +{ + struct template_buffer *buf = malloc(sizeof(*buf)); + + if (buf != NULL) { + buf->size = size; + buf->data = malloc(buf->size); + buf->dptr = buf->data; + + if (buf->data != NULL || size == 0) + return buf; + + free(buf); + } + + return NULL; +} + +/* grow buffer */ +static bool buf_grow(struct template_buffer *buf, size_t len) +{ + size_t off = buf->dptr - buf->data, left = buf->size - off; + if (len <= left) + return true; + + size_t diff = len - left; + if (diff < 1024) + diff = 1024; + + char *data = realloc(buf->data, buf->size + diff); + if (data == NULL) + return false; + + buf->data = data; + buf->dptr = data + off; + buf->size += diff; + + return true; +} + +/* put one char into buffer object */ +bool buf_putchar(struct template_buffer *buf, char c) +{ + if (!buf_grow(buf, 1)) + return false; + + *(buf->dptr++) = c; + + return true; +} + +/* append data to buffer */ +bool buf_append(struct template_buffer *buf, const char *s, size_t len) +{ + if (!buf_grow(buf, len)) + return false; + + memcpy(buf->dptr, s, len); + buf->dptr += len; + + return true; +} + +/* destroy buffer object and return pointer to data */ +char * buf_destroy(struct template_buffer *buf) +{ + char *data = buf->data; + + free(buf); + return data; +} + + +/* calculate the number of expected continuation chars */ +static inline size_t mb_num_chars(unsigned char c) +{ + if ((c & 0xE0) == 0xC0) + return 2; + else if ((c & 0xF0) == 0xE0) + return 3; + else if ((c & 0xF8) == 0xF0) + return 4; + else if ((c & 0xFC) == 0xF8) + return 5; + else if ((c & 0xFE) == 0xFC) + return 6; + + return 1; +} + +/* test whether the given byte is a valid continuation char */ +static inline bool mb_is_cont(unsigned char c) +{ + return ((c >= 0x80) && (c <= 0xBF)); +} + +/* test whether the byte sequence at the given pointer with the given + * length is the shortest possible representation of the code point */ +static inline bool mb_is_shortest(const unsigned char *s, size_t n) +{ + switch (n) + { + case 2: + /* 1100000x (10xxxxxx) */ + return !(((*s >> 1) == 0x60) && + ((*(s+1) >> 6) == 0x02)); + + case 3: + /* 11100000 100xxxxx (10xxxxxx) */ + return !((*s == 0xE0) && + ((*(s+1) >> 5) == 0x04) && + ((*(s+2) >> 6) == 0x02)); + + case 4: + /* 11110000 1000xxxx (10xxxxxx 10xxxxxx) */ + return !((*s == 0xF0) && + ((*(s+1) >> 4) == 0x08) && + ((*(s+2) >> 6) == 0x02) && + ((*(s+3) >> 6) == 0x02)); + + case 5: + /* 11111000 10000xxx (10xxxxxx 10xxxxxx 10xxxxxx) */ + return !((*s == 0xF8) && + ((*(s+1) >> 3) == 0x10) && + ((*(s+2) >> 6) == 0x02) && + ((*(s+3) >> 6) == 0x02) && + ((*(s+4) >> 6) == 0x02)); + + case 6: + /* 11111100 100000xx (10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx) */ + return !((*s == 0xF8) && + ((*(s+1) >> 2) == 0x20) && + ((*(s+2) >> 6) == 0x02) && + ((*(s+3) >> 6) == 0x02) && + ((*(s+4) >> 6) == 0x02) && + ((*(s+5) >> 6) == 0x02)); + } + + return true; +} + +/* test whether the byte sequence at the given pointer with the given + * length is an UTF-16 surrogate */ +static inline bool mb_is_surrogate(const unsigned char *s, size_t n) +{ + return ((n == 3) && (*s == 0xED) && (*(s+1) >= 0xA0) && (*(s+1) <= 0xBF)); +} + +/* test whether the byte sequence at the given pointer with the given + * length is an illegal UTF-8 code point */ +static inline bool mb_is_illegal(const unsigned char *s, size_t n) +{ + return ((n == 3) && (*s == 0xEF) && (*(s+1) == 0xBF) && + (*(s+2) >= 0xBE) && (*(s+2) <= 0xBF)); +} + + +/* scan given source string, validate UTF-8 sequence and store result + * in given buffer object */ +static size_t validate_utf8(const unsigned char **s, size_t l, struct template_buffer *buf) +{ + const unsigned char *ptr = *s; + size_t o = 0, v, n; + + /* ascii byte without null */ + if ((*(ptr+0) >= 0x01) && (*(ptr+0) <= 0x7F)) { + if (!buf_putchar(buf, *ptr++)) + return 0; + + o = 1; + } + + /* multi byte sequence */ + else if ((n = mb_num_chars(*ptr)) > 1) { + /* count valid chars */ + for (v = 1; (v <= n) && ((o+v) < l) && mb_is_cont(*(ptr+v)); v++); + + switch (n) + { + case 6: + case 5: + /* five and six byte sequences are always invalid */ + if (!buf_putchar(buf, '?')) + return 0; + + break; + + default: + /* if the number of valid continuation bytes matches the + * expected number and if the sequence is legal, copy + * the bytes to the destination buffer */ + if ((v == n) && mb_is_shortest(ptr, n) && + !mb_is_surrogate(ptr, n) && !mb_is_illegal(ptr, n)) + { + /* copy sequence */ + if (!buf_append(buf, (const char *)ptr, n)) + return 0; + } + + /* the found sequence is illegal, skip it */ + else + { + /* invalid sequence */ + if (!buf_putchar(buf, '?')) + return 0; + } + + break; + } + + /* advance beyound the last found valid continuation char */ + o = v; + ptr += v; + } + + /* invalid byte (0x00) */ + else { + if (!buf_putchar(buf, '?')) /* or 0xEF, 0xBF, 0xBD */ + return 0; + + o = 1; + ptr++; + } + + *s = ptr; + return o; +} + +/* Sanitize given string and strip all invalid XML bytes + * Validate UTF-8 sequences + * Escape XML control chars */ +bool pcdata(const char *s, size_t l, char **out, size_t *outl) +{ + struct template_buffer *buf = buf_init(l); + const unsigned char *ptr = (const unsigned char *)s; + size_t o, v; + char esq[8]; + int esl; + + if (!buf) + return false; + + for (o = 0; o < l; o++) { + /* Invalid XML bytes */ + if ((*ptr <= 0x08) || + ((*ptr >= 0x0B) && (*ptr <= 0x0C)) || + ((*ptr >= 0x0E) && (*ptr <= 0x1F)) || + (*ptr == 0x7F)) { + ptr++; + } + + /* Escapes */ + else if ((*ptr == '\'') || + (*ptr == '"') || + (*ptr == '&') || + (*ptr == '<') || + (*ptr == '>')) { + esl = snprintf(esq, sizeof(esq), "&#%i;", *ptr); + + if (!buf_append(buf, esq, esl)) + break; + + ptr++; + } + + /* ascii char */ + else if (*ptr <= 0x7F) { + buf_putchar(buf, (char)*ptr++); + } + + /* multi byte sequence */ + else { + if (!(v = validate_utf8(&ptr, l - o, buf))) + break; + + o += (v - 1); + } + } + + *outl = buf_length(buf); + *out = buf_destroy(buf); + return true; +} diff --git a/package/gluon-web/src/template_utils.h b/package/gluon-web/src/template_utils.h new file mode 100644 index 00000000..6dc18414 --- /dev/null +++ b/package/gluon-web/src/template_utils.h @@ -0,0 +1,47 @@ +/* + * gluon-web Template - Utility header + * + * Copyright (C) 2010-2012 Jo-Philipp Wich + * Copyright (C) 2018 Matthias Schiffer + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _TEMPLATE_UTILS_H_ +#define _TEMPLATE_UTILS_H_ + +#include +#include + + +/* buffer object */ +struct template_buffer { + char *data; + char *dptr; + size_t size; +}; + +struct template_buffer * buf_init(size_t size); +bool buf_putchar(struct template_buffer *buf, char c); +bool buf_append(struct template_buffer *buf, const char *s, size_t len); +char * buf_destroy(struct template_buffer *buf); + +/* read buffer length */ +static inline size_t buf_length(const struct template_buffer *buf) +{ + return buf->dptr - buf->data; +} + +bool pcdata(const char *s, size_t l, char **out, size_t *outl); + +#endif diff --git a/package/gluon.mk b/package/gluon.mk new file mode 100644 index 00000000..0b9787fc --- /dev/null +++ b/package/gluon.mk @@ -0,0 +1,119 @@ +GLUON_MK := $(abspath $(lastword $(MAKEFILE_LIST))) +PKG_FILE_DEPENDS += $(GLUON_MK) + +# Dependencies for LuaSrcDiet +PKG_BUILD_DEPENDS += luci-base/host + +ifneq ($(wildcard ./src/respondd.c),) + PKG_BUILD_DEPENDS += respondd +endif + +include $(INCLUDE_DIR)/package.mk + + +# Annoyingly, make's shell function replaces all newlines with spaces, so we have to do some escaping work. Yuck. +shell-escape = $(shell $(1) | sed -ne '1h; 1!H; $$ {g; s/@/@1/g; s/\n/@2/g; p}') +shell-unescape = $(subst @1,@,$(subst @2,$(newline),$(1))) +shell-verbatim = $(call shell-unescape,$(call shell-escape,$(1))) + + +define GluonCheckSite +[ -z "$$IPKG_INSTROOT" ] || "${TOPDIR}/staging_dir/hostpkg/bin/lua" "${TOPDIR}/../scripts/check_site.lua" <<'END__GLUON__CHECK__SITE' +$(call shell-verbatim,cat '$(1)') +END__GLUON__CHECK__SITE +endef + +GLUON_SUPPORTED_LANGS := de fr +GLUON_LANG_de := German +GLUON_LANG_fr := French + +GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_GLUON_WEB_LANG_$(lang)) +GLUON_ENABLED_LANGS := en $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_GLUON_WEB_LANG_$(lang)),$(lang))) + +ifneq ($(wildcard ./i18n/.),) + PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) +endif + + +define GluonBuildI18N + mkdir -p $$(PKG_BUILD_DIR)/i18n + for lang in $$(GLUON_ENABLED_LANGS); do \ + if [ -e $(1)/$$$$lang.po ]; then \ + rm -f $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \ + po2lmo $(1)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \ + fi; \ + done +endef + +define GluonInstallI18N + $$(INSTALL_DIR) $(1)/lib/gluon/web/i18n + for lang in $$(GLUON_ENABLED_LANGS); do \ + if [ -e $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo ]; then \ + $$(INSTALL_DATA) $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo $(1)/lib/gluon/web/i18n/$(PKG_NAME).$$$$lang.lmo; \ + fi; \ + done +endef + +define GluonSrcDiet + rm -rf $(2) + $(CP) $(1) $(2) + $(FIND) $(2) -type f | while read src; do \ + if LuaSrcDiet --noopt-binequiv -o "$$$$src.o" "$$$$src"; then \ + chmod $$$$(stat -c%a "$$$$src") "$$$$src.o"; \ + mv "$$$$src.o" "$$$$src"; \ + fi; \ + done +endef + + +define Gluon/Build/Compile + $(if $(wildcard ./src/Makefile ./src/CMakeLists.txt), + $(Build/Compile/Default) + ) + $(if $(wildcard ./luasrc/.), + $(call GluonSrcDiet,luasrc,$(PKG_BUILD_DIR)/luadest/) + ) + $(if $(wildcard ./i18n/.), + $(call GluonBuildI18N,i18n) + ) +endef + +define Gluon/Build/Install + $(if $(findstring $(PKG_INSTALL),1), + $(CP) $(PKG_INSTALL_DIR)/. $(1)/ + ) + $(if $(wildcard ./files/.), + $(CP) ./files/. $(1)/ + ) + $(if $(wildcard ./luasrc/.), + $(CP) $(PKG_BUILD_DIR)/luadest/. $(1)/ + ) + $(if $(wildcard ./src/respondd.c), + $(INSTALL_DIR) $(1)/usr/lib/respondd + $(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/usr/lib/respondd/$(PKG_NAME).so + ) + $(if $(wildcard ./i18n/.), + $(GluonInstallI18N) + ) +endef + +Build/Compile=$(call Gluon/Build/Compile) + +define BuildPackageGluon + define Package/$(1) := + SECTION:=gluon + CATEGORY:=Gluon + $$(Package/$(1)) + endef + + Package/$(1)/install ?= $$(Gluon/Build/Install) + + ifneq ($(wildcard check_site.lua),) + define Package/$(1)/postinst +#!/bin/sh +$$(call GluonCheckSite,check_site.lua) + endef + endif + + $$(eval $$(call BuildPackage,$(1))) +endef diff --git a/package/libbatadv/Makefile b/package/libbatadv/Makefile new file mode 100644 index 00000000..d2774769 --- /dev/null +++ b/package/libbatadv/Makefile @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: MIT +# +# batman-adv helpers functions library +# +# Copyright (c) 2017, Sven Eckelmann +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +include $(TOPDIR)/rules.mk + +PKG_NAME:=libbatadv +PKG_VERSION:=1 +PKG_LICENSE:=MIT + +PKG_INSTALL:=1 + +include $(INCLUDE_DIR)/package.mk + +define Package/libbatadv + SECTION:=libs + CATEGORY:=Libraries + TITLE:=batman-adv helpers functions + DEPENDS:=+libnl-tiny +endef + + +TARGET_CFLAGS += -flto -ffunction-sections -fdata-sections +TARGET_LDFLAGS += -fuse-linker-plugin -Wl,--gc-sections + +MAKE_VARS += \ + LIBNL_NAME="libnl-tiny" \ + LIBNL_GENL_NAME="libnl-tiny" + +MAKE_ARGS += \ + PREFIX=/usr + +MAKE_INSTALL_FLAGS += \ + PREFIX=/usr + +define Package/libbatadv/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/libbatadv.so $(1)/usr/lib/ +endef + +define Build/InstallDev + $(INSTALL_DIR) $(1) + $(CP) $(PKG_INSTALL_DIR)/* $(1)/ + $(INSTALL_DIR) $(1)/usr/lib/pkgconfig/ + $(CP) ./files/libbatadv.pc $(1)/usr/lib/pkgconfig/ +endef + +$(eval $(call BuildPackage,libbatadv)) diff --git a/package/libbatadv/files/libbatadv.pc b/package/libbatadv/files/libbatadv.pc new file mode 100644 index 00000000..44faa89c --- /dev/null +++ b/package/libbatadv/files/libbatadv.pc @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: MIT +# +# batman-adv helpers functions library +# +# Copyright (c) 2017, Sven Eckelmann +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +prefix=/usr +exec_prefix=/usr +libdir=${exec_prefix}/lib +includedir=${prefix}/include + +Name: libbatadv +Version: 1 +Description: batman-adv helpers functions +Requires.private: libnl-tiny +Libs: -lbatadv +Libs.private: +Cflags: diff --git a/package/libbatadv/src/Makefile b/package/libbatadv/src/Makefile new file mode 100644 index 00000000..fabfa82f --- /dev/null +++ b/package/libbatadv/src/Makefile @@ -0,0 +1,120 @@ +#!/usr/bin/make -f +# SPDX-License-Identifier: MIT +# +# batman-adv helpers functions library +# +# Copyright (c) 2017, Sven Eckelmann +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + + +# libbatadv build +BINARY_NAME = libbatadv.so +OBJ += batadv-genl.o + +# headers to install +HEADER += batadv-genl.h +HEADER += batman_adv.h + +# libbatadv flags and options +CFLAGS += -pedantic -Wall -W -MD -MP +CFLAGS += -fPIC -fvisibility=hidden +CPPFLAGS += -D_GNU_SOURCE +LDLIBS += +LDFLAGS += -shared -Wl,-export-dynamic + +# disable verbose output +ifneq ($(findstring $(MAKEFLAGS),s),s) +ifndef V + Q_CC = @echo ' ' CC $@; + Q_LD = @echo ' ' LD $@; + export Q_CC + export Q_LD +endif +endif + +ifeq ($(origin PKG_CONFIG), undefined) + PKG_CONFIG = pkg-config + ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),) + $(error $(PKG_CONFIG) not found) + endif +endif + +ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined) + LIBNL_NAME ?= libnl-3.0 + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),) + $(error No $(LIBNL_NAME) development libraries found!) + endif + LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME)) + LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME)) +endif +CFLAGS += $(LIBNL_CFLAGS) +LDLIBS += $(LIBNL_LDLIBS) + +ifeq ($(origin LIBNL_GENL_CFLAGS) $(origin LIBNL_GENL_LDLIBS), undefined undefined) + LIBNL_GENL_NAME ?= libnl-genl-3.0 + ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_GENL_NAME) 2>/dev/null),) + $(error No $(LIBNL_GENL_NAME) development libraries found!) + endif + LIBNL_GENL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_GENL_NAME)) + LIBNL_GENL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_GENL_NAME)) +endif +CFLAGS += $(LIBNL_GENL_CFLAGS) +LDLIBS += $(LIBNL_GENL_LDLIBS) + +# standard build tools +CC ?= gcc +RM ?= rm -f +INSTALL ?= install +MKDIR ?= mkdir -p +COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH) + +# standard install paths +PREFIX = /usr/local +INCLUDEDIR = $(PREFIX)/include +LIBDIR = $(PREFIX)/lib + +# default target +all: $(BINARY_NAME) + +# standard build rules +.SUFFIXES: .o .c +.c.o: + $(COMPILE.c) -o $@ $< + +$(BINARY_NAME): $(OBJ) + $(LINK.o) $^ $(LDLIBS) -o $@ + +clean: + $(RM) $(BINARY_NAME) $(OBJ) $(DEP) + +install: $(BINARY_NAME) + $(MKDIR) $(DESTDIR)$(LIBDIR) + $(MKDIR) $(DESTDIR)$(INCLUDEDIR) + $(INSTALL) -m 0755 $(BINARY_NAME) $(DESTDIR)$(LIBDIR) + $(INSTALL) -m 0644 $(HEADER) $(DESTDIR)$(INCLUDEDIR) + +# load dependencies +DEP = $(OBJ:.o=.d) +-include $(DEP) + +.PHONY: all clean install +.DELETE_ON_ERROR: +.DEFAULT_GOAL := all diff --git a/package/libbatadv/src/batadv-genl.c b/package/libbatadv/src/batadv-genl.c new file mode 100644 index 00000000..887019b8 --- /dev/null +++ b/package/libbatadv/src/batadv-genl.c @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: MIT +/* batman-adv helpers functions library + * + * Copyright (c) 2017, Sven Eckelmann + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "batadv-genl.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "batman_adv.h" + +__attribute__ ((visibility ("default"))) +struct nla_policy batadv_genl_policy[NUM_BATADV_ATTR] = { + [BATADV_ATTR_VERSION] = { .type = NLA_STRING }, + [BATADV_ATTR_ALGO_NAME] = { .type = NLA_STRING }, + [BATADV_ATTR_MESH_IFINDEX] = { .type = NLA_U32 }, + [BATADV_ATTR_MESH_IFNAME] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [BATADV_ATTR_MESH_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_HARD_IFINDEX] = { .type = NLA_U32 }, + [BATADV_ATTR_HARD_IFNAME] = { .type = NLA_STRING, + .maxlen = IFNAMSIZ }, + [BATADV_ATTR_HARD_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_ORIG_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_TPMETER_RESULT] = { .type = NLA_U8 }, + [BATADV_ATTR_TPMETER_TEST_TIME] = { .type = NLA_U32 }, + [BATADV_ATTR_TPMETER_BYTES] = { .type = NLA_U64 }, + [BATADV_ATTR_TPMETER_COOKIE] = { .type = NLA_U32 }, + [BATADV_ATTR_PAD] = { .type = NLA_UNSPEC }, + [BATADV_ATTR_ACTIVE] = { .type = NLA_FLAG }, + [BATADV_ATTR_TT_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_TT_TTVN] = { .type = NLA_U8 }, + [BATADV_ATTR_TT_LAST_TTVN] = { .type = NLA_U8 }, + [BATADV_ATTR_TT_CRC32] = { .type = NLA_U32 }, + [BATADV_ATTR_TT_VID] = { .type = NLA_U16 }, + [BATADV_ATTR_TT_FLAGS] = { .type = NLA_U32 }, + [BATADV_ATTR_FLAG_BEST] = { .type = NLA_FLAG }, + [BATADV_ATTR_LAST_SEEN_MSECS] = { .type = NLA_U32 }, + [BATADV_ATTR_NEIGH_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_TQ] = { .type = NLA_U8 }, + [BATADV_ATTR_THROUGHPUT] = { .type = NLA_U32 }, + [BATADV_ATTR_BANDWIDTH_UP] = { .type = NLA_U32 }, + [BATADV_ATTR_BANDWIDTH_DOWN] = { .type = NLA_U32 }, + [BATADV_ATTR_ROUTER] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_BLA_OWN] = { .type = NLA_FLAG }, + [BATADV_ATTR_BLA_ADDRESS] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_BLA_VID] = { .type = NLA_U16 }, + [BATADV_ATTR_BLA_BACKBONE] = { .type = NLA_UNSPEC, + .minlen = ETH_ALEN, + .maxlen = ETH_ALEN }, + [BATADV_ATTR_BLA_CRC] = { .type = NLA_U16 }, +}; + +/** + * nlquery_error_cb() - Store error value in &batadv_nlquery_opts->error and + * stop processing + * @nla: netlink address of the peer + * @nlerr: netlink error message being processed + * @arg: &struct batadv_nlquery_opts given to batadv_genl_query() + * + * Return: Always NL_STOP + */ +static int nlquery_error_cb(struct sockaddr_nl *nla __attribute__((unused)), + struct nlmsgerr *nlerr, void *arg) +{ + struct batadv_nlquery_opts *query_opts = arg; + + query_opts->err = nlerr->error; + + return NL_STOP; +} + +/** + * nlquery_stop_cb() - Store error value in &batadv_nlquery_opts->error and + * stop processing + * @msg: netlink message being processed + * @arg: &struct batadv_nlquery_opts given to batadv_genl_query() + * + * Return: Always NL_STOP + */ +static int nlquery_stop_cb(struct nl_msg *msg, void *arg) +{ + struct nlmsghdr *nlh = nlmsg_hdr(msg); + struct batadv_nlquery_opts *query_opts = arg; + int *error = nlmsg_data(nlh); + + if (*error) + query_opts->err = *error; + + return NL_STOP; +} + +/** + * batadv_genl_query() - Start a common batman-adv generic netlink query + * @mesh_iface: name of the batman-adv mesh interface + * @nl_cmd: &enum batadv_nl_commands which should be sent to kernel + * @callback: receive callback for valid messages + * @flags: additional netlink message header flags + * @query_opts: pointer to &struct batadv_nlquery_opts which is used to save + * the current processing state. This is given as arg to @callback + * + * Return: 0 on success or negative error value otherwise + */ +__attribute__ ((visibility ("default"))) +int batadv_genl_query(const char *mesh_iface, enum batadv_nl_commands nl_cmd, + nl_recvmsg_msg_cb_t callback, int flags, + struct batadv_nlquery_opts *query_opts) +{ + struct nl_sock *sock; + struct nl_msg *msg; + struct nl_cb *cb; + int ifindex; + int family; + int ret; + + query_opts->err = 0; + + sock = nl_socket_alloc(); + if (!sock) + return -ENOMEM; + + ret = genl_connect(sock); + if (ret < 0) { + query_opts->err = ret; + goto err_free_sock; + } + + family = genl_ctrl_resolve(sock, BATADV_NL_NAME); + if (family < 0) { + query_opts->err = -EOPNOTSUPP; + goto err_free_sock; + } + + ifindex = if_nametoindex(mesh_iface); + if (!ifindex) { + query_opts->err = -ENODEV; + goto err_free_sock; + } + + cb = nl_cb_alloc(NL_CB_DEFAULT); + if (!cb) { + query_opts->err = -ENOMEM; + goto err_free_sock; + } + + nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, query_opts); + nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nlquery_stop_cb, query_opts); + nl_cb_err(cb, NL_CB_CUSTOM, nlquery_error_cb, query_opts); + + msg = nlmsg_alloc(); + if (!msg) { + query_opts->err = -ENOMEM; + goto err_free_cb; + } + + genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags, + nl_cmd, 1); + + nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex); + nl_send_auto_complete(sock, msg); + nlmsg_free(msg); + + nl_recvmsgs(sock, cb); + +err_free_cb: + nl_cb_put(cb); +err_free_sock: + nl_socket_free(sock); + + return query_opts->err; +} diff --git a/package/libbatadv/src/batadv-genl.h b/package/libbatadv/src/batadv-genl.h new file mode 100644 index 00000000..1643d493 --- /dev/null +++ b/package/libbatadv/src/batadv-genl.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: MIT */ +/* batman-adv helpers functions library + * + * Copyright (c) 2017, Sven Eckelmann + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef _BATADV_GENL_H_ +#define _BATADV_GENL_H_ + +#include +#include +#include +#include +#include + +#include "batman_adv.h" + +/** + * struct batadv_nlquery_opts - internal state for batadv_genl_query() + * + * This structure should be used as member of a struct which tracks the state + * for the callback. The macro batadv_container_of can be used to convert the + * arg pointer from batadv_nlquery_opts to the member which contains this + * struct. + */ +struct batadv_nlquery_opts { + /** @err: current error */ + int err; +}; + +/** + * BATADV_ARRAY_SIZE() - Get number of items in static array + * @x: array with known length + * + * Return: number of items in array + */ +#ifndef BATADV_ARRAY_SIZE +#define BATADV_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) +#endif + +/** + * batadv_container_of() - Calculate address of object that contains address ptr + * @ptr: pointer to member variable + * @type: type of the structure containing ptr + * @member: name of the member variable in struct @type + * + * Return: @type pointer of object containing ptr + */ +#ifndef batadv_container_of +#define batadv_container_of(ptr, type, member) __extension__ ({ \ + const __typeof__(((type *)0)->member) *__pmember = (ptr); \ + (type *)((char *)__pmember - offsetof(type, member)); }) +#endif + +/** + * batadv_genl_missing_attrs() - Check whether @attrs is missing mandatory + * attribute + * @attrs: attributes which was parsed by nla_parse() + * @mandatory: list of required attributes + * @num: number of required attributes in @mandatory + * + * Return: Return true when a attribute is missing, false otherwise + */ +static inline bool +batadv_genl_missing_attrs(struct nlattr *attrs[], + const enum batadv_nl_attrs mandatory[], size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) { + if (!attrs[mandatory[i]]) + return true; + } + + return false; +} + +extern struct nla_policy batadv_genl_policy[]; + +int batadv_genl_query(const char *mesh_iface, enum batadv_nl_commands nl_cmd, + nl_recvmsg_msg_cb_t callback, int flags, + struct batadv_nlquery_opts *query_opts); + +#endif /* _BATADV_GENL_H_ */ diff --git a/package/libbatadv/src/batman_adv.h b/package/libbatadv/src/batman_adv.h new file mode 100644 index 00000000..ae00c99c --- /dev/null +++ b/package/libbatadv/src/batman_adv.h @@ -0,0 +1,426 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) 2016-2017 B.A.T.M.A.N. contributors: + * + * Matthias Schiffer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _UAPI_LINUX_BATMAN_ADV_H_ +#define _UAPI_LINUX_BATMAN_ADV_H_ + +#define BATADV_NL_NAME "batadv" + +#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" + +/** + * enum batadv_tt_client_flags - TT client specific flags + * + * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire. + * Bits from 8 to 15 are called _local flags_ because they are used for local + * computations only. + * + * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with + * the other nodes in the network. To achieve this goal these flags are included + * in the TT CRC computation. + */ +enum batadv_tt_client_flags { + /** + * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table + */ + BATADV_TT_CLIENT_DEL = (1 << 0), + + /** + * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and + * the new update telling its new real location has not been + * received/sent yet + */ + BATADV_TT_CLIENT_ROAM = (1 << 1), + + /** + * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi + * interface. This information is used by the "AP Isolation" feature + */ + BATADV_TT_CLIENT_WIFI = (1 << 4), + + /** + * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This + * information is used by the Extended Isolation feature + */ + BATADV_TT_CLIENT_ISOLA = (1 << 5), + + /** + * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from + * the table + */ + BATADV_TT_CLIENT_NOPURGE = (1 << 8), + + /** + * @BATADV_TT_CLIENT_NEW: this client has been added to the local table + * but has not been announced yet + */ + BATADV_TT_CLIENT_NEW = (1 << 9), + + /** + * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it + * is kept in the table for one more originator interval for consistency + * purposes + */ + BATADV_TT_CLIENT_PENDING = (1 << 10), + + /** + * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be + * part of the network but no nnode has already announced it + */ + BATADV_TT_CLIENT_TEMP = (1 << 11), +}; + +/** + * enum batadv_nl_attrs - batman-adv netlink attributes + */ +enum batadv_nl_attrs { + /** + * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors + */ + BATADV_ATTR_UNSPEC, + + /** + * @BATADV_ATTR_VERSION: batman-adv version string + */ + BATADV_ATTR_VERSION, + + /** + * @BATADV_ATTR_ALGO_NAME: name of routing algorithm + */ + BATADV_ATTR_ALGO_NAME, + + /** + * @BATADV_ATTR_MESH_IFINDEX: index of the batman-adv interface + */ + BATADV_ATTR_MESH_IFINDEX, + + /** + * @BATADV_ATTR_MESH_IFNAME: name of the batman-adv interface + */ + BATADV_ATTR_MESH_IFNAME, + + /** + * @BATADV_ATTR_MESH_ADDRESS: mac address of the batman-adv interface + */ + BATADV_ATTR_MESH_ADDRESS, + + /** + * @BATADV_ATTR_HARD_IFINDEX: index of the non-batman-adv interface + */ + BATADV_ATTR_HARD_IFINDEX, + + /** + * @BATADV_ATTR_HARD_IFNAME: name of the non-batman-adv interface + */ + BATADV_ATTR_HARD_IFNAME, + + /** + * @BATADV_ATTR_HARD_ADDRESS: mac address of the non-batman-adv + * interface + */ + BATADV_ATTR_HARD_ADDRESS, + + /** + * @BATADV_ATTR_ORIG_ADDRESS: originator mac address + */ + BATADV_ATTR_ORIG_ADDRESS, + + /** + * @BATADV_ATTR_TPMETER_RESULT: result of run (see + * batadv_tp_meter_status) + */ + BATADV_ATTR_TPMETER_RESULT, + + /** + * @BATADV_ATTR_TPMETER_TEST_TIME: time (msec) the run took + */ + BATADV_ATTR_TPMETER_TEST_TIME, + + /** + * @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run + */ + BATADV_ATTR_TPMETER_BYTES, + + /** + * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session + */ + BATADV_ATTR_TPMETER_COOKIE, + + /** + * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment + */ + BATADV_ATTR_PAD, + + /** + * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active + */ + BATADV_ATTR_ACTIVE, + + /** + * @BATADV_ATTR_TT_ADDRESS: Client MAC address + */ + BATADV_ATTR_TT_ADDRESS, + + /** + * @BATADV_ATTR_TT_TTVN: Translation table version + */ + BATADV_ATTR_TT_TTVN, + + /** + * @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version + */ + BATADV_ATTR_TT_LAST_TTVN, + + /** + * @BATADV_ATTR_TT_CRC32: CRC32 over translation table + */ + BATADV_ATTR_TT_CRC32, + + /** + * @BATADV_ATTR_TT_VID: VLAN ID + */ + BATADV_ATTR_TT_VID, + + /** + * @BATADV_ATTR_TT_FLAGS: Translation table client flags + */ + BATADV_ATTR_TT_FLAGS, + + /** + * @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best + */ + BATADV_ATTR_FLAG_BEST, + + /** + * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen + */ + BATADV_ATTR_LAST_SEEN_MSECS, + + /** + * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address + */ + BATADV_ATTR_NEIGH_ADDRESS, + + /** + * @BATADV_ATTR_TQ: TQ to neighbour + */ + BATADV_ATTR_TQ, + + /** + * @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour + */ + BATADV_ATTR_THROUGHPUT, + + /** + * @BATADV_ATTR_BANDWIDTH_UP: Reported uplink bandwidth + */ + BATADV_ATTR_BANDWIDTH_UP, + + /** + * @BATADV_ATTR_BANDWIDTH_DOWN: Reported downlink bandwidth + */ + BATADV_ATTR_BANDWIDTH_DOWN, + + /** + * @BATADV_ATTR_ROUTER: Gateway router MAC address + */ + BATADV_ATTR_ROUTER, + + /** + * @BATADV_ATTR_BLA_OWN: Flag indicating own originator + */ + BATADV_ATTR_BLA_OWN, + + /** + * @BATADV_ATTR_BLA_ADDRESS: Bridge loop avoidance claim MAC address + */ + BATADV_ATTR_BLA_ADDRESS, + + /** + * @BATADV_ATTR_BLA_VID: BLA VLAN ID + */ + BATADV_ATTR_BLA_VID, + + /** + * @BATADV_ATTR_BLA_BACKBONE: BLA gateway originator MAC address + */ + BATADV_ATTR_BLA_BACKBONE, + + /** + * @BATADV_ATTR_BLA_CRC: BLA CRC + */ + BATADV_ATTR_BLA_CRC, + + /* add attributes above here, update the policy in netlink.c */ + + /** + * @__BATADV_ATTR_AFTER_LAST: internal use + */ + __BATADV_ATTR_AFTER_LAST, + + /** + * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available + */ + NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST, + + /** + * @BATADV_ATTR_MAX: highest attribute number currently defined + */ + BATADV_ATTR_MAX = __BATADV_ATTR_AFTER_LAST - 1 +}; + +/** + * enum batadv_nl_commands - supported batman-adv netlink commands + */ +enum batadv_nl_commands { + /** + * @BATADV_CMD_UNSPEC: unspecified command to catch errors + */ + BATADV_CMD_UNSPEC, + + /** + * @BATADV_CMD_GET_MESH_INFO: Query basic information about batman-adv + * device + */ + BATADV_CMD_GET_MESH_INFO, + + /** + * @BATADV_CMD_TP_METER: Start a tp meter session + */ + BATADV_CMD_TP_METER, + + /** + * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session + */ + BATADV_CMD_TP_METER_CANCEL, + + /** + * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms. + */ + BATADV_CMD_GET_ROUTING_ALGOS, + + /** + * @BATADV_CMD_GET_HARDIFS: Query list of hard interfaces + */ + BATADV_CMD_GET_HARDIFS, + + /** + * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations + */ + BATADV_CMD_GET_TRANSTABLE_LOCAL, + + /** + * @BATADV_CMD_GET_TRANSTABLE_GLOBAL: Query list of global translations + */ + BATADV_CMD_GET_TRANSTABLE_GLOBAL, + + /** + * @BATADV_CMD_GET_ORIGINATORS: Query list of originators + */ + BATADV_CMD_GET_ORIGINATORS, + + /** + * @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours + */ + BATADV_CMD_GET_NEIGHBORS, + + /** + * @BATADV_CMD_GET_GATEWAYS: Query list of gateways + */ + BATADV_CMD_GET_GATEWAYS, + + /** + * @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims + */ + BATADV_CMD_GET_BLA_CLAIM, + + /** + * @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance + * backbones + */ + BATADV_CMD_GET_BLA_BACKBONE, + + /* add new commands above here */ + + /** + * @__BATADV_CMD_AFTER_LAST: internal use + */ + __BATADV_CMD_AFTER_LAST, + + /** + * @BATADV_CMD_MAX: highest used command number + */ + BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1 +}; + +/** + * enum batadv_tp_meter_reason - reason of a tp meter test run stop + */ +enum batadv_tp_meter_reason { + /** + * @BATADV_TP_REASON_COMPLETE: sender finished tp run + */ + BATADV_TP_REASON_COMPLETE = 3, + + /** + * @BATADV_TP_REASON_CANCEL: sender was stopped during run + */ + BATADV_TP_REASON_CANCEL = 4, + + /* error status >= 128 */ + + /** + * @BATADV_TP_REASON_DST_UNREACHABLE: receiver could not be reached or + * didn't answer + */ + BATADV_TP_REASON_DST_UNREACHABLE = 128, + + /** + * @BATADV_TP_REASON_RESEND_LIMIT: (unused) sender retry reached limit + */ + BATADV_TP_REASON_RESEND_LIMIT = 129, + + /** + * @BATADV_TP_REASON_ALREADY_ONGOING: test to or from the same node + * already ongoing + */ + BATADV_TP_REASON_ALREADY_ONGOING = 130, + + /** + * @BATADV_TP_REASON_MEMORY_ERROR: test was stopped due to low memory + */ + BATADV_TP_REASON_MEMORY_ERROR = 131, + + /** + * @BATADV_TP_REASON_CANT_SEND: failed to send via outgoing interface + */ + BATADV_TP_REASON_CANT_SEND = 132, + + /** + * @BATADV_TP_REASON_TOO_MANY: too many ongoing sessions + */ + BATADV_TP_REASON_TOO_MANY = 133, +}; + +#endif /* _UAPI_LINUX_BATMAN_ADV_H_ */ diff --git a/package/libgluonutil/Makefile b/package/libgluonutil/Makefile index 762c25f4..e9cc45cb 100644 --- a/package/libgluonutil/Makefile +++ b/package/libgluonutil/Makefile @@ -6,8 +6,6 @@ CMAKE_INSTALL:=1 PKG_LICENSE:=BSD-2-Clause -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/cmake.mk @@ -15,16 +13,7 @@ define Package/libgluonutil SECTION:=libs CATEGORY:=Libraries TITLE:=Gluon utility library - DEPENDS:=+libjson-c -endef - -CMAKE_OPTIONS += \ - -DCMAKE_BUILD_TYPE:String="MINSIZEREL" - - -define Build/Prepare - mkdir -p $(PKG_BUILD_DIR) - $(CP) ./src/* $(PKG_BUILD_DIR)/ + DEPENDS:=+libjson-c +libuci endef define Package/libgluonutil/install diff --git a/package/libgluonutil/src/CMakeLists.txt b/package/libgluonutil/src/CMakeLists.txt index ba92a3e1..41dd038a 100644 --- a/package/libgluonutil/src/CMakeLists.txt +++ b/package/libgluonutil/src/CMakeLists.txt @@ -1,24 +1,15 @@ cmake_minimum_required(VERSION 2.6) -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) - project(libgluonutil C) -set(LIBDIR "lib${LIB_SUFFIX}") - -find_package(JSON_C REQUIRED) - set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE) add_library(gluonutil SHARED libgluonutil.c) -set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99 ${JSON_C_CFLAGS_OTHER}") -set_property(TARGET gluonutil PROPERTY LINK_FLAGS "${JSON_C_LDFLAGS_OTHER}") -set_property(TARGET gluonutil APPEND PROPERTY INCLUDE_DIRECTORIES ${JSON_C_INCLUDE_DIR}) -target_link_libraries(gluonutil ${JSON_C_LIBRARIES}) +set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99") +target_link_libraries(gluonutil json-c uci) install(TARGETS gluonutil - ARCHIVE DESTINATION ${LIBDIR} - LIBRARY DESTINATION ${LIBDIR} + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib ) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libgluonutil.h DESTINATION include) diff --git a/package/libgluonutil/src/FindJSON_C.cmake b/package/libgluonutil/src/FindJSON_C.cmake deleted file mode 100644 index f6abee65..00000000 --- a/package/libgluonutil/src/FindJSON_C.cmake +++ /dev/null @@ -1,20 +0,0 @@ -# Defines the following variables: -# JSON_C_FOUND -# JSON_C_INCLUDE_DIR -# JSON_C_LIBRARIES -# JSON_C_CFLAGS_OTHER -# JSON_C_LDFLAGS_OTHER - - -find_package(PkgConfig REQUIRED QUIET) - -pkg_check_modules(_JSON_C json-c) - -find_path(JSON_C_INCLUDE_DIR NAMES json-c/json.h HINTS ${_JSON_C_INCLUDE_DIRS}) -find_library(JSON_C_LIBRARIES NAMES json-c HINTS ${_JSON_C_LIBRARY_DIRS}) - -set(JSON_C_CFLAGS_OTHER "${_JSON_C_CFLAGS_OTHER}" CACHE STRING "Additional compiler flags for json-c") -set(JSON_C_LDFLAGS_OTHER "${_JSON_C_LDFLAGS_OTHER}" CACHE STRING "Additional linker flags for json-c") - -find_package_handle_standard_args(JSON_C REQUIRED_VARS JSON_C_LIBRARIES JSON_C_INCLUDE_DIR) -mark_as_advanced(JSON_C_INCLUDE_DIR JSON_C_LIBRARIES JSON_C_CFLAGS_OTHER JSON_C_LDFLAGS_OTHER) diff --git a/package/libgluonutil/src/libgluonutil.c b/package/libgluonutil/src/libgluonutil.c index 5932c544..0f4bfe4a 100644 --- a/package/libgluonutil/src/libgluonutil.c +++ b/package/libgluonutil/src/libgluonutil.c @@ -27,11 +27,44 @@ #include "libgluonutil.h" #include - +#include +#include #include #include #include +#include +/** + * Merges two JSON objects + * + * Both objects are consumed. On conflicts, object b will be preferred. + */ +static struct json_object * merge_json(struct json_object *a, struct json_object *b) { + if (!json_object_is_type(a, json_type_object) || !json_object_is_type(b, json_type_object)) { + json_object_put(a); + return b; + } + + json_object *m = json_object_new_object(); + + json_object_object_foreach(a, key_a, val_a) + json_object_object_add(m, key_a, json_object_get(val_a)); + json_object_put(a); + + json_object_object_foreach(b, key_b, val_b) { + struct json_object *val_m; + + if (json_object_object_get_ex(m, key_b, &val_m)) + val_m = merge_json(json_object_get(val_m), json_object_get(val_b)); + else + val_m = json_object_get(val_b); + + json_object_object_add(m, key_b, val_m); + } + json_object_put(b); + + return m; +} char * gluonutil_read_line(const char *filename) { FILE *f = fopen(filename, "r"); @@ -109,6 +142,107 @@ struct json_object * gluonutil_wrap_and_free_string(char *str) { return ret; } -struct json_object * gluonutil_load_site_config(void) { - return json_object_from_file("/lib/gluon/site.json"); + +bool gluonutil_get_node_prefix6(struct in6_addr *prefix) { + struct json_object *site = gluonutil_load_site_config(); + if (!site) + return false; + + struct json_object *node_prefix = NULL; + if (!json_object_object_get_ex(site, "node_prefix6", &node_prefix)) { + json_object_put(site); + return false; + } + + const char *str_prefix = json_object_get_string(node_prefix); + if (!str_prefix) { + json_object_put(site); + return false; + } + + char *prefix_addr = strndup(str_prefix, strchrnul(str_prefix, '/')-str_prefix); + + int ret = inet_pton(AF_INET6, prefix_addr, prefix); + + free(prefix_addr); + json_object_put(site); + + if (ret != 1) + return false; + + return true; +} + + + +bool gluonutil_has_domains(void) { + return (access("/lib/gluon/domains/", F_OK) == 0); +} + +char * gluonutil_get_domain(void) { + if (!gluonutil_has_domains()) + return NULL; + + char *ret = NULL; + + struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + goto uci_fail; + + ctx->flags &= ~UCI_FLAG_STRICT; + + struct uci_package *p; + if (uci_load(ctx, "gluon", &p)) + goto uci_fail; + + struct uci_section *s = uci_lookup_section(ctx, p, "core"); + if (!s) + goto uci_fail; + + const char *domain_code = uci_lookup_option_string(ctx, s, "domain"); + if (!domain_code) + goto uci_fail; + + ret = strdup(domain_code); + +uci_fail: + if (ctx) + uci_free_context(ctx); + + return ret; +} + + +struct json_object * gluonutil_load_site_config(void) { + char *domain_code = NULL; + struct json_object *site = NULL, *domain = NULL; + + site = json_object_from_file("/lib/gluon/site.json"); + if (!site) + return NULL; + + if (!gluonutil_has_domains()) + return site; + + domain_code = gluonutil_get_domain(); + if (!domain_code) + goto err; + + { + const char *domain_path_fmt = "/lib/gluon/domains/%s.json"; + char domain_path[strlen(domain_path_fmt) + strlen(domain_code)]; + snprintf(domain_path, sizeof(domain_path), domain_path_fmt, domain_code); + free(domain_code); + + domain = json_object_from_file(domain_path); + } + if (!domain) + goto err; + + return merge_json(site, domain); + +err: + json_object_put(site); + free(domain_code); + return NULL; } diff --git a/package/libgluonutil/src/libgluonutil.h b/package/libgluonutil/src/libgluonutil.h index 96195281..39b253ba 100644 --- a/package/libgluonutil/src/libgluonutil.h +++ b/package/libgluonutil/src/libgluonutil.h @@ -27,14 +27,21 @@ #ifndef _LIBGLUON_LIBGLUON_H_ #define _LIBGLUON_LIBGLUON_H_ +#include +#include + + char * gluonutil_read_line(const char *filename); char * gluonutil_get_sysconfig(const char *key); char * gluonutil_get_node_id(void); char * gluonutil_get_interface_address(const char *ifname); +bool gluonutil_get_node_prefix6(struct in6_addr *prefix); struct json_object * gluonutil_wrap_string(const char *str); struct json_object * gluonutil_wrap_and_free_string(char *str); +bool gluonutil_has_domains(void); +char * gluonutil_get_domain(void); struct json_object * gluonutil_load_site_config(void); #endif /* _LIBGLUON_LIBGLUON_H_ */ diff --git a/patches/lede/0001-build-move-STAGING_DIR_HOSTPKG-and-BUILD_DIR_HOST-back-to-a-common-directory-for-all-targets.patch b/patches/lede/0001-build-move-STAGING_DIR_HOSTPKG-and-BUILD_DIR_HOST-back-to-a-common-directory-for-all-targets.patch new file mode 100644 index 00000000..4afacf54 --- /dev/null +++ b/patches/lede/0001-build-move-STAGING_DIR_HOSTPKG-and-BUILD_DIR_HOST-back-to-a-common-directory-for-all-targets.patch @@ -0,0 +1,111 @@ +From: Matthias Schiffer +Date: Sat, 14 Jan 2017 18:13:14 +0100 +Subject: build: move STAGING_DIR_HOSTPKG and BUILD_DIR_HOST back to a common directory for all targets + +$(STAGING_DIR)/host is kept in addition to $(STAGING_DIR_HOSTPKG) in most +places; it is still used as destination for host files in Build/InstallDev. + +Signed-off-by: Matthias Schiffer + +diff --git a/Makefile b/Makefile +index b220dfd3c56a11f3e27d70e3d6e58cc6448abd2f..c1a7285c83df310e987eaef8376500d2b614eafb 100644 +--- a/Makefile ++++ b/Makefile +@@ -55,7 +55,7 @@ clean: FORCE + rm -rf $(BUILD_DIR) $(STAGING_DIR) $(BIN_DIR) $(OUTPUT_DIR)/packages/$(ARCH_PACKAGES) $(BUILD_LOG_DIR) $(TOPDIR)/staging_dir/packages + + dirclean: clean +- rm -rf $(STAGING_DIR_HOST) $(TOOLCHAIN_DIR) $(BUILD_DIR_HOST) $(BUILD_DIR_TOOLCHAIN) ++ rm -rf $(STAGING_DIR_HOST) $(STAGING_DIR_HOSTPKG) $(TOOLCHAIN_DIR) $(BUILD_DIR_BASE)/host $(BUILD_DIR_BASE)/hostpkg $(BUILD_DIR_TOOLCHAIN) + rm -rf $(TMP_DIR) + + ifndef DUMP_TARGET_DB +diff --git a/include/autotools.mk b/include/autotools.mk +index c6aa47e0bef311697b4def7a7183d1ac59dcf599..7bd400ab36d052b39fcb76a66873c8673eb189a0 100644 +--- a/include/autotools.mk ++++ b/include/autotools.mk +@@ -75,7 +75,7 @@ define autoreconf_target + $(strip $(call autoreconf, \ + $(PKG_BUILD_DIR), $(PKG_REMOVE_FILES), \ + $(PKG_AUTOMAKE_PATHS), $(PKG_LIBTOOL_PATHS), \ +- $(STAGING_DIR)/host/share/aclocal $(STAGING_DIR)/usr/share/aclocal $(PKG_MACRO_PATHS))) ++ $(STAGING_DIR)/host/share/aclocal $(STAGING_DIR_HOSTPKG)/share/aclocal $(STAGING_DIR)/usr/share/aclocal $(PKG_MACRO_PATHS))) + endef + + define patch_libtool_target +diff --git a/include/cmake.mk b/include/cmake.mk +index 5a403cbf41e2bbd6bdb843492639a01aff8cf75b..900dae1d4afc6007f8ac04179dd7f0922a07d4fa 100644 +--- a/include/cmake.mk ++++ b/include/cmake.mk +@@ -34,7 +34,7 @@ CMAKE_NM:=$(call cmake_tool,$(TARGET_NM)) + CMAKE_RANLIB:=$(call cmake_tool,$(TARGET_RANLIB)) + + CMAKE_FIND_ROOT_PATH:=$(STAGING_DIR)/usr;$(TOOLCHAIN_DIR)$(if $(CONFIG_EXTERNAL_TOOLCHAIN),;$(CONFIG_TOOLCHAIN_ROOT)) +-CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOST) ++CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOSTPKG);$(STAGING_DIR_HOST) + CMAKE_SHARED_LDFLAGS:=-Wl,-Bsymbolic-functions + + define Build/Configure/Default +diff --git a/include/host-build.mk b/include/host-build.mk +index 5fcec7ebf48361100d29c5925beaae4f36d5ac7b..485f09a6b71b881692b5ee575927397259bbac24 100644 +--- a/include/host-build.mk ++++ b/include/host-build.mk +@@ -126,7 +126,7 @@ ifneq ($(if $(HOST_QUILT),,$(CONFIG_AUTOREBUILD)),) + endif + + define Host/Exports/Default +- $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR_HOST)/share/aclocal $$(STAGING_DIR_HOST)/share/aclocal-* $(if $(IS_PACKAGE_BUILD),$$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*)),-I $$(p)) ++ $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR_HOST)/share/aclocal $$(STAGING_DIR_HOST)/share/aclocal-* $(if $(IS_PACKAGE_BUILD),$$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR_HOSTPKG)/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*)),-I $$(p)) + $(1) : export STAGING_PREFIX=$$(HOST_BUILD_PREFIX) + $(1) : export PKG_CONFIG_PATH=$$(STAGING_DIR_HOST)/lib/pkgconfig:$$(HOST_BUILD_PREFIX)/lib/pkgconfig + $(1) : export PKG_CONFIG_LIBDIR=$$(HOST_BUILD_PREFIX)/lib/pkgconfig +diff --git a/include/package.mk b/include/package.mk +index e9989ab13ec81a8751ee7245639ee0b82b9a87b2..7f77c4e99b1e9b79503963c497c4c87d7af9d71a 100644 +--- a/include/package.mk ++++ b/include/package.mk +@@ -130,7 +130,7 @@ ifdef USE_SOURCE_DIR + endif + + define Build/Exports/Default +- $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR)/usr/share/aclocal $$(STAGING_DIR)/usr/share/aclocal-* $$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*),-I $$(p)) ++ $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR)/usr/share/aclocal $$(STAGING_DIR)/usr/share/aclocal-* $$(STAGING_DIR_HOSTPKG)/share/aclocal $$(STAGING_DIR_HOSTPKG)/share/aclocal-* $$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*),-I $$(p)) + $(1) : export STAGING_PREFIX=$$(STAGING_DIR)/usr + $(1) : export PATH=$$(TARGET_PATH_PKG) + $(1) : export CONFIG_SITE:=$$(CONFIG_SITE) +diff --git a/rules.mk b/rules.mk +index 5710a84fe7ad24e45acb2ef62ee29eab37e8de06..b678e9bea5bc146a3c515d93003415cd21882068 100644 +--- a/rules.mk ++++ b/rules.mk +@@ -147,9 +147,9 @@ STAGING_DIR_ROOT:=$(STAGING_DIR)/root-$(BOARD) + BUILD_LOG_DIR:=$(TOPDIR)/logs + PKG_INFO_DIR := $(STAGING_DIR)/pkginfo + +-BUILD_DIR_HOST:=$(if $(IS_PACKAGE_BUILD),$(BUILD_DIR)/host,$(BUILD_DIR_BASE)/host) ++BUILD_DIR_HOST:=$(if $(IS_PACKAGE_BUILD),$(BUILD_DIR_BASE)/hostpkg,$(BUILD_DIR_BASE)/host) + STAGING_DIR_HOST:=$(TOPDIR)/staging_dir/host +-STAGING_DIR_HOSTPKG:=$(STAGING_DIR)/host ++STAGING_DIR_HOSTPKG:=$(TOPDIR)/staging_dir/hostpkg + + TARGET_PATH:=$(subst $(space),:,$(filter-out .,$(filter-out ./,$(subst :,$(space),$(PATH))))) + TARGET_INIT_PATH:=$(call qstrip,$(CONFIG_TARGET_INIT_PATH)) +@@ -208,7 +208,7 @@ ifndef DUMP + endif + endif + endif +-TARGET_PATH_PKG:=$(STAGING_DIR)/host/bin:$(TARGET_PATH) ++TARGET_PATH_PKG:=$(STAGING_DIR)/host/bin:$(STAGING_DIR_HOSTPKG)/bin:$(TARGET_PATH) + + ifeq ($(CONFIG_SOFT_FLOAT),y) + SOFT_FLOAT_CONFIG_OPTION:=--with-float=soft +@@ -234,9 +234,9 @@ export PKG_CONFIG + + HOSTCC:=gcc + HOSTCXX:=g++ +-HOST_CPPFLAGS:=-I$(STAGING_DIR_HOST)/include -I$(STAGING_DIR_HOST)/usr/include $(if $(IS_PACKAGE_BUILD),-I$(STAGING_DIR)/host/include) ++HOST_CPPFLAGS:=-I$(STAGING_DIR_HOST)/include -I$(STAGING_DIR_HOST)/usr/include $(if $(IS_PACKAGE_BUILD),-I$(STAGING_DIR_HOSTPKG)/include -I$(STAGING_DIR)/host/include) + HOST_CFLAGS:=-O2 $(HOST_CPPFLAGS) +-HOST_LDFLAGS:=-L$(STAGING_DIR_HOST)/lib -L$(STAGING_DIR_HOST)/usr/lib $(if $(IS_PACKAGE_BUILD),-L$(STAGING_DIR)/host/lib) ++HOST_LDFLAGS:=-L$(STAGING_DIR_HOST)/lib -L$(STAGING_DIR_HOST)/usr/lib $(if $(IS_PACKAGE_BUILD),-L$(STAGING_DIR_HOSTPKG)/lib -L$(STAGING_DIR)/host/lib) + + ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),) + TARGET_AR:=$(TARGET_CROSS)gcc-ar diff --git a/patches/openwrt/0002-procd-add-support-for-alternative-rc.d-directories.patch b/patches/lede/0002-procd-add-support-for-alternative-rc.d-directories.patch similarity index 96% rename from patches/openwrt/0002-procd-add-support-for-alternative-rc.d-directories.patch rename to patches/lede/0002-procd-add-support-for-alternative-rc.d-directories.patch index ced85fed..db29794d 100644 --- a/patches/openwrt/0002-procd-add-support-for-alternative-rc.d-directories.patch +++ b/patches/lede/0002-procd-add-support-for-alternative-rc.d-directories.patch @@ -4,7 +4,7 @@ Subject: procd: add support for alternative rc.d directories diff --git a/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch b/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch new file mode 100644 -index 0000000..bc24342 +index 0000000000000000000000000000000000000000..bc2434200364b46f1db4c2eec22c4e8b973844d5 --- /dev/null +++ b/package/system/procd/patches/0001-Add-support-for-alternative-rc.d-directories.patch @@ -0,0 +1,97 @@ diff --git a/patches/lede/0003-base-files-disable-reset-button-handling.patch b/patches/lede/0003-base-files-disable-reset-button-handling.patch new file mode 100644 index 00000000..55d95fde --- /dev/null +++ b/patches/lede/0003-base-files-disable-reset-button-handling.patch @@ -0,0 +1,43 @@ +From: Matthias Schiffer +Date: Sat, 21 Mar 2015 16:40:52 +0100 +Subject: base-files: disable reset button handling + +This conflicts with our reset button usage. + +diff --git a/package/base-files/files/etc/rc.button/reset b/package/base-files/files/etc/rc.button/reset +deleted file mode 100755 +index 2403122ad21d1abd568337908c9d58060e87bf08..0000000000000000000000000000000000000000 +--- a/package/base-files/files/etc/rc.button/reset ++++ /dev/null +@@ -1,31 +0,0 @@ +-#!/bin/sh +- +-. /lib/functions.sh +- +-OVERLAY="$( grep ' /overlay ' /proc/mounts )" +- +-case "$ACTION" in +-pressed) +- [ -z "$OVERLAY" ] && return 0 +- +- return 5 +-;; +-timeout) +- . /etc/diag.sh +- set_state failsafe +-;; +-released) +- if [ "$SEEN" -lt 1 ] +- then +- echo "REBOOT" > /dev/console +- sync +- reboot +- elif [ "$SEEN" -ge 5 -a -n "$OVERLAY" ] +- then +- echo "FACTORY RESET" > /dev/console +- jffs2reset -y && reboot & +- fi +-;; +-esac +- +-return 0 diff --git a/patches/openwrt/0009-hostapd-prevent-channel-switch-for-5GHz.patch b/patches/lede/0004-hostapd-prevent-channel-switch-for-5GHz.patch similarity index 84% rename from patches/openwrt/0009-hostapd-prevent-channel-switch-for-5GHz.patch rename to patches/lede/0004-hostapd-prevent-channel-switch-for-5GHz.patch index 03a24967..3eda369d 100644 --- a/patches/openwrt/0009-hostapd-prevent-channel-switch-for-5GHz.patch +++ b/patches/lede/0004-hostapd-prevent-channel-switch-for-5GHz.patch @@ -8,15 +8,15 @@ adapter (they would lose their configuration). As a temporary fix, disable this channel switch function. -diff --git a/package/network/services/hostapd/patches/470-no_channel_switch.patch b/package/network/services/hostapd/patches/470-no_channel_switch.patch +diff --git a/package/network/services/hostapd/patches/900-no_channel_switch.patch b/package/network/services/hostapd/patches/900-no_channel_switch.patch new file mode 100644 -index 0000000..2eb1d7e +index 0000000000000000000000000000000000000000..c6145156928ffa5a5195ca145b0655bb88c92091 --- /dev/null -+++ b/package/network/services/hostapd/patches/470-no_channel_switch.patch ++++ b/package/network/services/hostapd/patches/900-no_channel_switch.patch @@ -0,0 +1,68 @@ +--- a/src/common/hw_features_common.c ++++ b/src/common/hw_features_common.c -+@@ -172,7 +172,6 @@ int check_40mhz_5g(struct hostapd_hw_mod ++@@ -171,7 +171,6 @@ int check_40mhz_5g(struct hostapd_hw_mod + struct wpa_scan_results *scan_res, int pri_chan, + int sec_chan) + { @@ -24,8 +24,8 @@ index 0000000..2eb1d7e + int bss_pri_chan, bss_sec_chan; + size_t i; + int match; -+@@ -183,57 +182,6 @@ int check_40mhz_5g(struct hostapd_hw_mod -+ if (pri_chan == sec_chan) ++@@ -180,57 +179,6 @@ int check_40mhz_5g(struct hostapd_hw_mod ++ pri_chan == sec_chan) + return 0; + +- pri_freq = hw_get_freq(mode, pri_chan); diff --git a/patches/openwrt/0080-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch b/patches/lede/0005-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch similarity index 97% rename from patches/openwrt/0080-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch rename to patches/lede/0005-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch index 690d3ebb..662d8960 100644 --- a/patches/openwrt/0080-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch +++ b/patches/lede/0005-libjson-c-Add-support-for-custom-format-strings-for-doubles.patch @@ -4,7 +4,7 @@ Subject: libjson-c: Add support for custom format strings for doubles diff --git a/package/libs/libjson-c/patches/002-custom-format-string.patch b/package/libs/libjson-c/patches/002-custom-format-string.patch new file mode 100644 -index 0000000..2f454c5 +index 0000000000000000000000000000000000000000..2f454c560ff78c1edd4654b9651f0e6299bd5e6f --- /dev/null +++ b/package/libs/libjson-c/patches/002-custom-format-string.patch @@ -0,0 +1,98 @@ diff --git a/patches/lede/0006-dropbear-add-a-failsafe-mode-that-will-always-allow-password-less-root-login.patch b/patches/lede/0006-dropbear-add-a-failsafe-mode-that-will-always-allow-password-less-root-login.patch new file mode 100644 index 00000000..a6e9213b --- /dev/null +++ b/patches/lede/0006-dropbear-add-a-failsafe-mode-that-will-always-allow-password-less-root-login.patch @@ -0,0 +1,69 @@ +From: Matthias Schiffer +Date: Tue, 27 Sep 2016 03:55:55 +0200 +Subject: dropbear: add a failsafe mode that will always allow password-less root login + +Signed-off-by: Matthias Schiffer + +diff --git a/package/network/services/dropbear/patches/700-failsafe-mode.patch b/package/network/services/dropbear/patches/700-failsafe-mode.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..d379da0d0a7890e0a25d87e227c2e065cd2750ee +--- /dev/null ++++ b/package/network/services/dropbear/patches/700-failsafe-mode.patch +@@ -0,0 +1,57 @@ ++--- a/runopts.h +++++ b/runopts.h ++@@ -98,6 +98,8 @@ typedef struct svr_runopts { ++ int allowblankpass; ++ unsigned int maxauthtries; ++ +++ int failsafe_mode; +++ ++ #ifdef ENABLE_SVR_REMOTETCPFWD ++ int noremotetcp; ++ #endif ++--- a/svr-auth.c +++++ b/svr-auth.c ++@@ -149,10 +149,11 @@ void recv_msg_userauth_request() { ++ AUTH_METHOD_NONE_LEN) == 0) { ++ TRACE(("recv_msg_userauth_request: 'none' request")) ++ if (valid_user ++- && (svr_opts.allowblankpass || !strcmp(ses.authstate.pw_name, "root")) ++- && !svr_opts.noauthpass ++- && !(svr_opts.norootpass && ses.authstate.pw_uid == 0) ++- && ses.authstate.pw_passwd[0] == '\0') +++ && ((svr_opts.failsafe_mode && !strcmp(ses.authstate.pw_name, "root")) +++ || ((svr_opts.allowblankpass || !strcmp(ses.authstate.pw_name, "root")) +++ && !svr_opts.noauthpass +++ && !(svr_opts.norootpass && ses.authstate.pw_uid == 0) +++ && ses.authstate.pw_passwd[0] == '\0'))) ++ { ++ dropbear_log(LOG_NOTICE, ++ "Auth succeeded with blank password for '%s' from %s", ++--- a/svr-runopts.c +++++ b/svr-runopts.c ++@@ -72,6 +72,7 @@ static void printhelp(const char * progn ++ "-s Disable password logins\n" ++ "-g Disable password logins for root\n" ++ "-B Allow blank password logins\n" +++ "-f Failsafe mode: always allow password-less root login\n" ++ #endif ++ "-T <1 to %d> Maximum authentication tries (default %d)\n" ++ #ifdef ENABLE_SVR_LOCALTCPFWD ++@@ -133,6 +134,7 @@ void svr_getopts(int argc, char ** argv) ++ svr_opts.noauthpass = 0; ++ svr_opts.norootpass = 0; ++ svr_opts.allowblankpass = 0; +++ svr_opts.failsafe_mode = 0; ++ svr_opts.maxauthtries = DEFAULT_AUTH_TRIES; ++ svr_opts.inetdmode = 0; ++ svr_opts.portcount = 0; ++@@ -251,6 +253,9 @@ void svr_getopts(int argc, char ** argv) ++ case 'B': ++ svr_opts.allowblankpass = 1; ++ break; +++ case 'f': +++ svr_opts.failsafe_mode = 1; +++ break; ++ #endif ++ case 'h': ++ printhelp(argv[0]); diff --git a/patches/lede/0007-rules.mk-export-STAGING_DIR_HOSTPKG.patch b/patches/lede/0007-rules.mk-export-STAGING_DIR_HOSTPKG.patch new file mode 100644 index 00000000..b6bedd95 --- /dev/null +++ b/patches/lede/0007-rules.mk-export-STAGING_DIR_HOSTPKG.patch @@ -0,0 +1,19 @@ +From: Matthias Schiffer +Date: Thu, 19 Jan 2017 00:03:32 +0100 +Subject: rules.mk: export STAGING_DIR_HOSTPKG + +Signed-off-by: Matthias Schiffer + +diff --git a/rules.mk b/rules.mk +index b678e9bea5bc146a3c515d93003415cd21882068..16cab67d5d1b8b130a0ffddc81789e798cda338e 100644 +--- a/rules.mk ++++ b/rules.mk +@@ -225,7 +225,7 @@ else + endif + + export PATH:=$(TARGET_PATH) +-export STAGING_DIR STAGING_DIR_HOST ++export STAGING_DIR STAGING_DIR_HOST STAGING_DIR_HOSTPKG + export SH_FUNC:=. $(INCLUDE_DIR)/shell.sh; + + PKG_CONFIG:=$(STAGING_DIR_HOST)/bin/pkg-config diff --git a/patches/lede/0008-gettext-full-fix-to-use-STAGING_DIR_HOSTPKG-instead-of-STAGING_DIR-host.patch b/patches/lede/0008-gettext-full-fix-to-use-STAGING_DIR_HOSTPKG-instead-of-STAGING_DIR-host.patch new file mode 100644 index 00000000..4aa04521 --- /dev/null +++ b/patches/lede/0008-gettext-full-fix-to-use-STAGING_DIR_HOSTPKG-instead-of-STAGING_DIR-host.patch @@ -0,0 +1,32 @@ +From: Matthias Schiffer +Date: Thu, 19 Jan 2017 00:04:09 +0100 +Subject: gettext-full: fix to use $STAGING_DIR_HOSTPKG instead of $STAGING_DIR/host + +Signed-off-by: Matthias Schiffer + +diff --git a/package/libs/gettext-full/patches/000-relocatable.patch b/package/libs/gettext-full/patches/000-relocatable.patch +index c14be728367b57c08024d848cf8ff847cfe865be..a95c268f5bc94ed8ec3784ae2044aa77e0322491 100644 +--- a/package/libs/gettext-full/patches/000-relocatable.patch ++++ b/package/libs/gettext-full/patches/000-relocatable.patch +@@ -5,8 +5,8 @@ + # Set variables + # - gettext_datadir directory where the data files are stored. + -prefix="@prefix@" +-+if [ -n "$STAGING_DIR" ]; then +-+ prefix="$STAGING_DIR/host" +++if [ -n "$STAGING_DIR_HOSTPKG" ]; then +++ prefix="$STAGING_DIR_HOSTPKG" + +else + + prefix="@prefix@" + +fi +@@ -20,8 +20,8 @@ + # Set variables + # - gettext_datadir directory where the data files are stored. + -prefix="@prefix@" +-+if [ -n "$STAGING_DIR" ]; then +-+ prefix="$STAGING_DIR/host" +++if [ -n "$STAGING_DIR_HOSTPKG" ]; then +++ prefix="$STAGING_DIR_HOSTPKG" + +else + + prefix="@prefix@" + +fi diff --git a/patches/lede/0009-netifd-update-to-git-HEAD-version.patch b/patches/lede/0009-netifd-update-to-git-HEAD-version.patch new file mode 100644 index 00000000..b03ee347 --- /dev/null +++ b/patches/lede/0009-netifd-update-to-git-HEAD-version.patch @@ -0,0 +1,28 @@ +From: Matthias Schiffer +Date: Fri, 10 Mar 2017 01:58:42 +0100 +Subject: netifd: update to git HEAD version + +91810ec system-linux: add VXLAN support +f107656 netifd: Add option to configure locktime for each device +cdc0e80 interface: add prefix assignment priority support +6397f5e device: add veth support +6228d0f wireless: fix _wireless_add_process +7cc2f10 treewide: fix white space errors + +diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile +index fb035864017df739a0d0b0c0451fe8488a40c77c..d6d91ba014c67f126176eba8acae5fd2c8b007ba 100644 +--- a/package/network/config/netifd/Makefile ++++ b/package/network/config/netifd/Makefile +@@ -5,9 +5,9 @@ PKG_RELEASE:=1 + + PKG_SOURCE_PROTO:=git + PKG_SOURCE_URL=$(LEDE_GIT)/project/netifd.git +-PKG_SOURCE_DATE:=2017-01-25 +-PKG_SOURCE_VERSION:=650758b16e5185505a3fbc1307949340af70b611 +-PKG_MIRROR_HASH:=d09c740bc1bf6269678bd75c9af52ecd4be3d1d59402a543ceb9d4459cecfa2b ++PKG_SOURCE_DATE:=2017-03-07 ++PKG_SOURCE_VERSION:=91810ecc13239f3b18c8299de265b4f3531c0017 ++PKG_MIRROR_HASH:=51d0a8866c6b004185f1fb83f37e7aed33fc94b72bd85954c773549a57c3c761 + PKG_MAINTAINER:=Felix Fietkau + + PKG_LICENSE:=GPL-2.0 diff --git a/patches/lede/0010-netifd-ubus-add-interface-method-to-trigger-renew-event.patch b/patches/lede/0010-netifd-ubus-add-interface-method-to-trigger-renew-event.patch new file mode 100644 index 00000000..18c432a3 --- /dev/null +++ b/patches/lede/0010-netifd-ubus-add-interface-method-to-trigger-renew-event.patch @@ -0,0 +1,83 @@ +From: Matthias Schiffer +Date: Wed, 12 Apr 2017 02:31:12 +0200 +Subject: netifd: ubus: add interface method to trigger renew event + +diff --git a/package/network/config/netifd/patches/0001-ubus-add-interface-method-to-trigger-renew-event.patch b/package/network/config/netifd/patches/0001-ubus-add-interface-method-to-trigger-renew-event.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..1f59498d421b7e1d3e76a1a38f604181d11c4649 +--- /dev/null ++++ b/package/network/config/netifd/patches/0001-ubus-add-interface-method-to-trigger-renew-event.patch +@@ -0,0 +1,73 @@ ++From 8b39c2fce4c1da3f3dcd4c6fd305c124714839e8 Mon Sep 17 00:00:00 2001 ++Message-Id: <8b39c2fce4c1da3f3dcd4c6fd305c124714839e8.1491956920.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Wed, 12 Apr 2017 02:25:33 +0200 ++Subject: [PATCH] ubus: add interface method to trigger renew event ++ ++proto-shell handlers may implement all kinds of renew handlers, there ++should be a way to explicitly trigger such a renew. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ interface.c | 8 ++++++++ ++ interface.h | 1 + ++ ubus.c | 14 ++++++++++++++ ++ 3 files changed, 23 insertions(+) ++ ++--- a/interface.c +++++ b/interface.c ++@@ -1076,6 +1076,14 @@ interface_set_down(struct interface *ifa ++ return 0; ++ } ++ +++int interface_renew(struct interface *iface) +++{ +++ if (iface->state == IFS_TEARDOWN || iface->state == IFS_DOWN) +++ return -1; +++ +++ return interface_proto_event(iface->proto, PROTO_CMD_RENEW, false); +++} +++ ++ void ++ interface_start_pending(void) ++ { ++--- a/interface.h +++++ b/interface.h ++@@ -184,6 +184,7 @@ void interface_set_available(struct inte ++ int interface_set_up(struct interface *iface); ++ int interface_set_down(struct interface *iface); ++ void __interface_set_down(struct interface *iface, bool force); +++int interface_renew(struct interface *iface); ++ ++ void interface_set_main_dev(struct interface *iface, struct device *dev); ++ void interface_set_l3_dev(struct interface *iface, struct device *dev); ++--- a/ubus.c +++++ b/ubus.c ++@@ -376,6 +376,19 @@ netifd_handle_down(struct ubus_context * ++ return 0; ++ } ++ +++static int +++netifd_handle_renew(struct ubus_context *ctx, struct ubus_object *obj, +++ struct ubus_request_data *req, const char *method, +++ struct blob_attr *msg) +++{ +++ struct interface *iface; +++ +++ iface = container_of(obj, struct interface, ubus); +++ interface_renew(iface); +++ +++ return 0; +++} +++ ++ static void ++ netifd_add_interface_errors(struct blob_buf *b, struct interface *iface) ++ { ++@@ -912,6 +925,7 @@ netifd_handle_set_data(struct ubus_conte ++ static struct ubus_method iface_object_methods[] = { ++ { .name = "up", .handler = netifd_handle_up }, ++ { .name = "down", .handler = netifd_handle_down }, +++ { .name = "renew", .handler = netifd_handle_renew }, ++ { .name = "status", .handler = netifd_handle_status }, ++ { .name = "prepare", .handler = netifd_handle_iface_prepare }, ++ { .name = "dump", .handler = netifd_handle_dump }, diff --git a/patches/lede/0011-procd-switch-to-latest-master.patch b/patches/lede/0011-procd-switch-to-latest-master.patch new file mode 100644 index 00000000..e16f6586 --- /dev/null +++ b/patches/lede/0011-procd-switch-to-latest-master.patch @@ -0,0 +1,21 @@ +From: Matthias Schiffer +Date: Thu, 13 Jul 2017 17:15:21 +0200 +Subject: procd: switch to latest master + +diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile +index b905cb25aa02c4c3f82cbc288ef15648dfd66444..5b92d79332f2ea400041586b92b570d8b633218a 100644 +--- a/package/system/procd/Makefile ++++ b/package/system/procd/Makefile +@@ -12,9 +12,9 @@ PKG_RELEASE:=1 + + PKG_SOURCE_PROTO:=git + PKG_SOURCE_URL=$(LEDE_GIT)/project/procd.git +-PKG_SOURCE_DATE:=2018-01-22 +-PKG_SOURCE_VERSION:=9a4036fb1b7412ab2ea4f360d2cc7e6a5e0fa6b5 +-PKG_MIRROR_HASH:=669f062e9c5228ef9d09cc9904d8ce4651f0b8506a6c2fff27b21e83b26f0abb ++PKG_SOURCE_DATE:=2018-01-23 ++PKG_SOURCE_VERSION:=653629f19e591a0827ab39de07b4526bb119a57a ++PKG_MIRROR_HASH:=2e0c3ae45521eea456a8411c8d9ef19ed9a5ed6c0ab38b9496555625fb4ba6a2 + CMAKE_INSTALL:=1 + + PKG_LICENSE:=GPL-2.0 diff --git a/patches/lede/0012-procd-clean-up-trailing-whitespace-in-nand.sh.patch b/patches/lede/0012-procd-clean-up-trailing-whitespace-in-nand.sh.patch new file mode 100644 index 00000000..671b879d --- /dev/null +++ b/patches/lede/0012-procd-clean-up-trailing-whitespace-in-nand.sh.patch @@ -0,0 +1,28 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 08:27:40 +0200 +Subject: procd: clean up trailing whitespace in nand.sh + +Signed-off-by: Matthias Schiffer + +diff --git a/package/system/procd/files/nand.sh b/package/system/procd/files/nand.sh +index ebaaf2aa16009cc1431dbb79ba9f689c8b636069..8a164ee08537014936a8608f5a60fe0e27dcabd6 100644 +--- a/package/system/procd/files/nand.sh ++++ b/package/system/procd/files/nand.sh +@@ -194,7 +194,7 @@ nand_upgrade_prepare_ubi() { + + nand_do_upgrade_success() { + local conf_tar="/tmp/sysupgrade.tgz" +- ++ + sync + [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" + echo "sysupgrade successful" +@@ -231,7 +231,7 @@ nand_upgrade_ubifs() { + local rootfs_length=`(cat $1 | wc -c) 2> /dev/null` + + nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0" +- ++ + local ubidev="$( nand_find_ubi "$CI_UBIPART" )" + local root_ubivol="$(nand_find_volume $ubidev rootfs)" + ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 diff --git a/patches/lede/0013-procd-prepare-NAND-sysupgrade-for-making-upgraded-dynamically-linked.patch b/patches/lede/0013-procd-prepare-NAND-sysupgrade-for-making-upgraded-dynamically-linked.patch new file mode 100644 index 00000000..3d3c5b4e --- /dev/null +++ b/patches/lede/0013-procd-prepare-NAND-sysupgrade-for-making-upgraded-dynamically-linked.patch @@ -0,0 +1,32 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 08:28:05 +0200 +Subject: procd: prepare NAND sysupgrade for making upgraded dynamically linked + +Use install_bin to copy upgraded with all dependencies. The old name +/tmp/upgraded is temporarily retained as a symlink to avoid breaking +things. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/system/procd/files/nand.sh b/package/system/procd/files/nand.sh +index 8a164ee08537014936a8608f5a60fe0e27dcabd6..6bd2005344c081df20e5a330a69e49e37225c39f 100644 +--- a/package/system/procd/files/nand.sh ++++ b/package/system/procd/files/nand.sh +@@ -333,7 +333,7 @@ nand_upgrade_stage1() { + [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] && + rm $CONF_TAR + +- ubus call system nandupgrade "{\"path\": \"$path\" }" ++ ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }" + exit 0 + } + } +@@ -370,6 +370,7 @@ nand_do_platform_check() { + # $(1): file to be used for upgrade + nand_do_upgrade() { + echo -n $1 > /tmp/sysupgrade-nand-path +- cp /sbin/upgraded /tmp/ ++ install_bin /sbin/upgraded ++ ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded + nand_upgrade_stage1 + } diff --git a/patches/lede/0014-procd-remove-procd-nand-package.patch b/patches/lede/0014-procd-remove-procd-nand-package.patch new file mode 100644 index 00000000..0a8ffb89 --- /dev/null +++ b/patches/lede/0014-procd-remove-procd-nand-package.patch @@ -0,0 +1,934 @@ +From: Matthias Schiffer +Date: Fri, 21 Apr 2017 20:37:58 +0200 +Subject: procd: remove procd-nand package + +We always want to support staged upgrades now, so it's better to include +upgraded into the main package. /lib/upgrade/nand.sh is moved to +base-files. + +The procd-nand-firstboot package is removed for now, it may return later +as a separate package. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/Makefile b/package/base-files/Makefile +index 1d034fdede7598f15b1f802c47e834990e5852d9..f473ef732106eb8fa05e7c5b59df176fef33e42d 100644 +--- a/package/base-files/Makefile ++++ b/package/base-files/Makefile +@@ -19,7 +19,9 @@ PKG_BUILD_DEPENDS:=usign/host + PKG_LICENSE:=GPL-2.0 + + # Extend depends from version.mk +-PKG_CONFIG_DEPENDS += CONFIG_SIGNED_PACKAGES CONFIG_TARGET_INIT_PATH CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE ++PKG_CONFIG_DEPENDS += \ ++ CONFIG_SIGNED_PACKAGES CONFIG_TARGET_INIT_PATH CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE \ ++ CONFIG_NAND_SUPPORT + + include $(INCLUDE_DIR)/package.mk + +@@ -31,7 +33,7 @@ endif + define Package/base-files + SECTION:=base + CATEGORY:=Base system +- DEPENDS:=+netifd +libc +procd +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:lede-keyring +fstools +fwtool ++ DEPENDS:=+netifd +libc +procd +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:lede-keyring +NAND_SUPPORT:ubi-utils +fstools +fwtool + TITLE:=Base filesystem for Lede + URL:=http://openwrt.org/ + VERSION:=$(PKG_RELEASE)-$(REVISION) +@@ -107,9 +109,16 @@ ifdef CONFIG_SIGNED_PACKAGES + endef + endif + ++ifeq ($(CONFIG_NAND_SUPPORT),) ++ define Package/base-files/nand-support ++ rm -f $(1)/lib/upgrade/nand.sh ++ endef ++endif ++ + define Package/base-files/install + $(CP) ./files/* $(1)/ + $(Package/base-files/install-key) ++ $(Package/base-files/nand-support) + if [ -d $(GENERIC_PLATFORM_DIR)/base-files/. ]; then \ + $(CP) $(GENERIC_PLATFORM_DIR)/base-files/* $(1)/; \ + fi +diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh +new file mode 100644 +index 0000000000000000000000000000000000000000..6bd2005344c081df20e5a330a69e49e37225c39f +--- /dev/null ++++ b/package/base-files/files/lib/upgrade/nand.sh +@@ -0,0 +1,376 @@ ++#!/bin/sh ++# Copyright (C) 2014 OpenWrt.org ++# ++ ++. /lib/functions.sh ++ ++# 'kernel' partition on NAND contains the kernel ++CI_KERNPART="kernel" ++ ++# 'ubi' partition on NAND contains UBI ++CI_UBIPART="ubi" ++ ++ubi_mknod() { ++ local dir="$1" ++ local dev="/dev/$(basename $dir)" ++ ++ [ -e "$dev" ] && return 0 ++ ++ local devid="$(cat $dir/dev)" ++ local major="${devid%%:*}" ++ local minor="${devid##*:}" ++ mknod "$dev" c $major $minor ++} ++ ++nand_find_volume() { ++ local ubidevdir ubivoldir ++ ubidevdir="/sys/devices/virtual/ubi/$1" ++ [ ! -d "$ubidevdir" ] && return 1 ++ for ubivoldir in $ubidevdir/${1}_*; do ++ [ ! -d "$ubivoldir" ] && continue ++ if [ "$( cat $ubivoldir/name )" = "$2" ]; then ++ basename $ubivoldir ++ ubi_mknod "$ubivoldir" ++ return 0 ++ fi ++ done ++} ++ ++nand_find_ubi() { ++ local ubidevdir ubidev mtdnum ++ mtdnum="$( find_mtd_index $1 )" ++ [ ! "$mtdnum" ] && return 1 ++ for ubidevdir in /sys/devices/virtual/ubi/ubi*; do ++ [ ! -d "$ubidevdir" ] && continue ++ cmtdnum="$( cat $ubidevdir/mtd_num )" ++ [ ! "$mtdnum" ] && continue ++ if [ "$mtdnum" = "$cmtdnum" ]; then ++ ubidev=$( basename $ubidevdir ) ++ ubi_mknod "$ubidevdir" ++ echo $ubidev ++ return 0 ++ fi ++ done ++} ++ ++nand_get_magic_long() { ++ dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ++} ++ ++get_magic_long_tar() { ++ ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null ++} ++ ++identify_magic() { ++ local magic=$1 ++ case "$magic" in ++ "55424923") ++ echo "ubi" ++ ;; ++ "31181006") ++ echo "ubifs" ++ ;; ++ "68737173") ++ echo "squashfs" ++ ;; ++ "d00dfeed") ++ echo "fit" ++ ;; ++ "4349"*) ++ echo "combined" ++ ;; ++ *) ++ echo "unknown $magic" ++ ;; ++ esac ++} ++ ++ ++identify() { ++ identify_magic $(nand_get_magic_long "$1" "${2:-0}") ++} ++ ++identify_tar() { ++ identify_magic $(get_magic_long_tar "$1" "$2") ++} ++ ++nand_restore_config() { ++ sync ++ local ubidev=$( nand_find_ubi $CI_UBIPART ) ++ local ubivol="$( nand_find_volume $ubidev rootfs_data )" ++ [ ! "$ubivol" ] && ++ ubivol="$( nand_find_volume $ubidev rootfs )" ++ mkdir /tmp/new_root ++ if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then ++ echo "mounting ubifs $ubivol failed" ++ rmdir /tmp/new_root ++ return 1 ++ fi ++ mv "$1" "/tmp/new_root/sysupgrade.tgz" ++ umount /tmp/new_root ++ sync ++ rmdir /tmp/new_root ++} ++ ++nand_upgrade_prepare_ubi() { ++ local rootfs_length="$1" ++ local rootfs_type="$2" ++ local has_kernel="${3:-0}" ++ local has_env="${4:-0}" ++ ++ local mtdnum="$( find_mtd_index "$CI_UBIPART" )" ++ if [ ! "$mtdnum" ]; then ++ echo "cannot find ubi mtd partition $CI_UBIPART" ++ return 1 ++ fi ++ ++ local ubidev="$( nand_find_ubi "$CI_UBIPART" )" ++ if [ ! "$ubidev" ]; then ++ ubiattach -m "$mtdnum" ++ sync ++ ubidev="$( nand_find_ubi "$CI_UBIPART" )" ++ fi ++ ++ if [ ! "$ubidev" ]; then ++ ubiformat /dev/mtd$mtdnum -y ++ ubiattach -m "$mtdnum" ++ sync ++ ubidev="$( nand_find_ubi "$CI_UBIPART" )" ++ [ "$has_env" -gt 0 ] && { ++ ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB ++ ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB ++ } ++ fi ++ ++ local kern_ubivol="$( nand_find_volume $ubidev kernel )" ++ local root_ubivol="$( nand_find_volume $ubidev rootfs )" ++ local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" ++ ++ # remove ubiblock device of rootfs ++ local root_ubiblk="ubiblock${root_ubivol:3}" ++ if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then ++ echo "removing $root_ubiblk" ++ if ! ubiblock -r /dev/$root_ubivol; then ++ echo "cannot remove $root_ubiblk" ++ return 1; ++ fi ++ fi ++ ++ # kill volumes ++ [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N kernel || true ++ [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs || true ++ [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true ++ ++ # update kernel ++ if [ "$has_kernel" = "1" ]; then ++ if ! ubimkvol /dev/$ubidev -N kernel -s $kernel_length; then ++ echo "cannot create kernel volume" ++ return 1; ++ fi ++ fi ++ ++ # update rootfs ++ local root_size_param ++ if [ "$rootfs_type" = "ubifs" ]; then ++ root_size_param="-m" ++ else ++ root_size_param="-s $rootfs_length" ++ fi ++ if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then ++ echo "cannot create rootfs volume" ++ return 1; ++ fi ++ ++ # create rootfs_data for non-ubifs rootfs ++ if [ "$rootfs_type" != "ubifs" ]; then ++ if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then ++ echo "cannot initialize rootfs_data volume" ++ return 1 ++ fi ++ fi ++ sync ++ return 0 ++} ++ ++nand_do_upgrade_success() { ++ local conf_tar="/tmp/sysupgrade.tgz" ++ ++ sync ++ [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" ++ echo "sysupgrade successful" ++ umount -a ++ reboot -f ++} ++ ++# Flash the UBI image to MTD partition ++nand_upgrade_ubinized() { ++ local ubi_file="$1" ++ local mtdnum="$(find_mtd_index "$CI_UBIPART")" ++ ++ [ ! "$mtdnum" ] && { ++ CI_UBIPART="rootfs" ++ mtdnum="$(find_mtd_index "$CI_UBIPART")" ++ } ++ ++ if [ ! "$mtdnum" ]; then ++ echo "cannot find mtd device $CI_UBIPART" ++ umount -a ++ reboot -f ++ fi ++ ++ local mtddev="/dev/mtd${mtdnum}" ++ ubidetach -p "${mtddev}" || true ++ sync ++ ubiformat "${mtddev}" -y -f "${ubi_file}" ++ ubiattach -p "${mtddev}" ++ nand_do_upgrade_success ++} ++ ++# Write the UBIFS image to UBI volume ++nand_upgrade_ubifs() { ++ local rootfs_length=`(cat $1 | wc -c) 2> /dev/null` ++ ++ nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0" ++ ++ local ubidev="$( nand_find_ubi "$CI_UBIPART" )" ++ local root_ubivol="$(nand_find_volume $ubidev rootfs)" ++ ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 ++ ++ nand_do_upgrade_success ++} ++ ++nand_board_name() { ++ if type 'platform_nand_board_name' >/dev/null 2>/dev/null; then ++ platform_nand_board_name ++ return ++ fi ++ ++ cat /tmp/sysinfo/board_name ++} ++ ++nand_upgrade_tar() { ++ local tar_file="$1" ++ local board_name="$(nand_board_name)" ++ local kernel_mtd="$(find_mtd_index $CI_KERNPART)" ++ ++ local kernel_length=`(tar xf $tar_file sysupgrade-$board_name/kernel -O | wc -c) 2> /dev/null` ++ local rootfs_length=`(tar xf $tar_file sysupgrade-$board_name/root -O | wc -c) 2> /dev/null` ++ ++ local rootfs_type="$(identify_tar "$tar_file" sysupgrade-$board_name/root)" ++ ++ local has_kernel=1 ++ local has_env=0 ++ ++ [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { ++ tar xf $tar_file sysupgrade-$board_name/kernel -O | mtd write - $CI_KERNPART ++ } ++ [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0 ++ ++ nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env" ++ ++ local ubidev="$( nand_find_ubi "$CI_UBIPART" )" ++ [ "$has_kernel" = "1" ] && { ++ local kern_ubivol="$(nand_find_volume $ubidev kernel)" ++ tar xf $tar_file sysupgrade-$board_name/kernel -O | \ ++ ubiupdatevol /dev/$kern_ubivol -s $kernel_length - ++ } ++ ++ local root_ubivol="$(nand_find_volume $ubidev rootfs)" ++ tar xf $tar_file sysupgrade-$board_name/root -O | \ ++ ubiupdatevol /dev/$root_ubivol -s $rootfs_length - ++ ++ nand_do_upgrade_success ++} ++ ++# Recognize type of passed file and start the upgrade process ++nand_do_upgrade_stage2() { ++ local file_type=$(identify $1) ++ ++ if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then ++ platform_nand_pre_upgrade "$1" ++ fi ++ ++ [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs" ++ ++ case "$file_type" in ++ "ubi") nand_upgrade_ubinized $1;; ++ "ubifs") nand_upgrade_ubifs $1;; ++ *) nand_upgrade_tar $1;; ++ esac ++} ++ ++nand_upgrade_stage2() { ++ [ $1 = "nand" ] && { ++ [ -f "$2" ] && { ++ touch /tmp/sysupgrade ++ ++ killall -9 telnetd ++ killall -9 dropbear ++ killall -9 ash ++ ++ kill_remaining TERM ++ sleep 3 ++ kill_remaining KILL ++ ++ sleep 1 ++ ++ if [ -n "$(rootfs_type)" ]; then ++ v "Switching to ramdisk..." ++ run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2" ++ else ++ nand_do_upgrade_stage2 $2 ++ fi ++ return 0 ++ } ++ echo "Nand upgrade failed" ++ exit 1 ++ } ++} ++ ++nand_upgrade_stage1() { ++ [ -f /tmp/sysupgrade-nand-path ] && { ++ path="$(cat /tmp/sysupgrade-nand-path)" ++ [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] && ++ rm $CONF_TAR ++ ++ ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }" ++ exit 0 ++ } ++} ++ ++# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts ++# 3 types of files: ++# 1) UBI - should contain an ubinized image, header is checked for the proper ++# MAGIC ++# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, ++# header is checked for the proper MAGIC ++# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty ++# "CONTROL" file (at this point its content isn't verified) ++# ++# You usually want to call this function in platform_check_image. ++# ++# $(1): board name, used in case of passing TAR file ++# $(2): file to be checked ++nand_do_platform_check() { ++ local board_name="$1" ++ local tar_file="$2" ++ local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null` ++ local file_type="$(identify $2)" ++ ++ [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && { ++ echo "Invalid sysupgrade file." ++ return 1 ++ } ++ ++ return 0 ++} ++ ++# Start NAND upgrade process ++# ++# $(1): file to be used for upgrade ++nand_do_upgrade() { ++ echo -n $1 > /tmp/sysupgrade-nand-path ++ install_bin /sbin/upgraded ++ ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded ++ nand_upgrade_stage1 ++} +diff --git a/package/system/procd/Makefile b/package/system/procd/Makefile +index 5b92d79332f2ea400041586b92b570d8b633218a..879f03f54b23603a360499078d7d53503875f55a 100644 +--- a/package/system/procd/Makefile ++++ b/package/system/procd/Makefile +@@ -22,11 +22,9 @@ PKG_LICENSE_FILES:= + + PKG_MAINTAINER:=John Crispin + +-PKG_FLAGS:=nonshared +- + PKG_CONFIG_DEPENDS:= \ + CONFIG_TARGET_INIT_PATH CONFIG_KERNEL_SECCOMP \ +- CONFIG_NAND_SUPPORT CONFIG_PROCD_SHOW_BOOT CONFIG_PROCD_ZRAM_TMPFS \ ++ CONFIG_PROCD_SHOW_BOOT CONFIG_PROCD_ZRAM_TMPFS \ + CONFIG_KERNEL_NAMESPACES CONFIG_PACKAGE_procd-ujail CONFIG_PACKAGE_procd-seccomp + + include $(INCLUDE_DIR)/package.mk +@@ -42,7 +40,7 @@ TARGET_LDFLAGS += $(if $(CONFIG_USE_GLIBC),-lrt) + define Package/procd + SECTION:=base + CATEGORY:=Base system +- DEPENDS:=+ubusd +ubus +libjson-script +ubox +USE_GLIBC:librt +libubox +libubus +NAND_SUPPORT:procd-nand ++ DEPENDS:=+ubusd +ubus +libjson-script +ubox +USE_GLIBC:librt +libubox +libubus + TITLE:=OpenWrt system process manager + endef + +@@ -60,20 +58,6 @@ define Package/procd-seccomp + TITLE:=OpenWrt process seccomp helper + utrace + endef + +-define Package/procd-nand +- SECTION:=utils +- CATEGORY:=Utilities +- DEPENDS:=@NAND_SUPPORT +ubi-utils +- TITLE:=OpenWrt sysupgrade nand helper +-endef +- +-define Package/procd-nand-firstboot +- SECTION:=utils +- CATEGORY:=Utilities +- DEPENDS:=procd-nand +- TITLE:=OpenWrt firstboot nand helper +-endef +- + define Package/procd/config + menu "Configuration" + depends on PACKAGE_procd +@@ -91,10 +75,6 @@ endmenu + endef + + +-ifeq ($(CONFIG_NAND_SUPPORT),y) +- CMAKE_OPTIONS += -DBUILD_UPGRADED=1 +-endif +- + ifeq ($(CONFIG_PROCD_SHOW_BOOT),y) + CMAKE_OPTIONS += -DSHOW_BOOT_ON_CONSOLE=1 + endif +@@ -113,7 +93,7 @@ CMAKE_OPTIONS += -DSECCOMP_SUPPORT=$(SECCOMP) -DUTRACE_SUPPORT=$(SECCOMP) + define Package/procd/install + $(INSTALL_DIR) $(1)/sbin $(1)/etc $(1)/lib/functions + +- $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{init,procd,askfirst,udevtrigger} $(1)/sbin/ ++ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{init,procd,askfirst,udevtrigger,upgraded} $(1)/sbin/ + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libsetlbf.so $(1)/lib + $(INSTALL_BIN) ./files/reload_config $(1)/sbin/ + $(INSTALL_DATA) ./files/hotplug*.json $(1)/etc/ +@@ -133,21 +113,6 @@ define Package/procd-seccomp/install + $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libpreload-trace.so $(1)/lib + endef + +-define Package/procd-nand/install +- $(INSTALL_DIR) $(1)/sbin $(1)/lib/upgrade +- +- $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/upgraded $(1)/sbin/ +- $(INSTALL_DATA) ./files/nand.sh $(1)/lib/upgrade/ +-endef +- +-define Package/procd-nand-firstboot/install +- $(INSTALL_DIR) $(1)/lib/preinit +- +- $(INSTALL_DATA) ./files/nand-preinit.sh $(1)/lib/preinit/60-nand-firstboot.sh +-endef +- + $(eval $(call BuildPackage,procd)) + $(eval $(call BuildPackage,procd-ujail)) + $(eval $(call BuildPackage,procd-seccomp)) +-$(eval $(call BuildPackage,procd-nand)) +-$(eval $(call BuildPackage,procd-nand-firstboot)) +diff --git a/package/system/procd/files/nand-preinit.sh b/package/system/procd/files/nand-preinit.sh +deleted file mode 100644 +index cf596246d1f2891cbeb7b5c7cac4bb6e002b13fb..0000000000000000000000000000000000000000 +--- a/package/system/procd/files/nand-preinit.sh ++++ /dev/null +@@ -1,21 +0,0 @@ +-#!/bin/sh +-# Copyright (C) 2014 OpenWrt.org +- +-nand_takeover() { +- . /lib/upgrade/nand.sh +- mtd=$(find_mtd_index "$CI_UBIPART") +- esize=$(cat /proc/mtd | grep mtd$mtd |cut -d" " -f 3) +- [ -z "$esize" ] && return 1 +- esize=$(printf "%d" 0x$esize) +- for a in `seq 0 64`; do +- mtd -o $((a * esize)) -l 400 dump /dev/mtd$mtd > /tmp/takeover.hdr +- MAGIC=$(dd if=/tmp/takeover.hdr bs=1 skip=261 count=5 2> /dev/null) +- SIZE=$(printf "%d" 0x$(dd if=/tmp/takeover.hdr bs=4 count=1 2> /dev/null | hexdump -v -n 4 -e '1/1 "%02x"')) +- [ "$MAGIC" = "ustar" ] && { +- mtd -o $((a * esize)) -l $((SIZE + 4)) dump /dev/mtd$mtd | dd bs=1 skip=4 of=/tmp/sysupgrade.tar +- nand_do_upgrade_stage2 /tmp/sysupgrade.tar +- } +- done +-} +- +-boot_hook_add initramfs nand_takeover +diff --git a/package/system/procd/files/nand.sh b/package/system/procd/files/nand.sh +deleted file mode 100644 +index 6bd2005344c081df20e5a330a69e49e37225c39f..0000000000000000000000000000000000000000 +--- a/package/system/procd/files/nand.sh ++++ /dev/null +@@ -1,376 +0,0 @@ +-#!/bin/sh +-# Copyright (C) 2014 OpenWrt.org +-# +- +-. /lib/functions.sh +- +-# 'kernel' partition on NAND contains the kernel +-CI_KERNPART="kernel" +- +-# 'ubi' partition on NAND contains UBI +-CI_UBIPART="ubi" +- +-ubi_mknod() { +- local dir="$1" +- local dev="/dev/$(basename $dir)" +- +- [ -e "$dev" ] && return 0 +- +- local devid="$(cat $dir/dev)" +- local major="${devid%%:*}" +- local minor="${devid##*:}" +- mknod "$dev" c $major $minor +-} +- +-nand_find_volume() { +- local ubidevdir ubivoldir +- ubidevdir="/sys/devices/virtual/ubi/$1" +- [ ! -d "$ubidevdir" ] && return 1 +- for ubivoldir in $ubidevdir/${1}_*; do +- [ ! -d "$ubivoldir" ] && continue +- if [ "$( cat $ubivoldir/name )" = "$2" ]; then +- basename $ubivoldir +- ubi_mknod "$ubivoldir" +- return 0 +- fi +- done +-} +- +-nand_find_ubi() { +- local ubidevdir ubidev mtdnum +- mtdnum="$( find_mtd_index $1 )" +- [ ! "$mtdnum" ] && return 1 +- for ubidevdir in /sys/devices/virtual/ubi/ubi*; do +- [ ! -d "$ubidevdir" ] && continue +- cmtdnum="$( cat $ubidevdir/mtd_num )" +- [ ! "$mtdnum" ] && continue +- if [ "$mtdnum" = "$cmtdnum" ]; then +- ubidev=$( basename $ubidevdir ) +- ubi_mknod "$ubidevdir" +- echo $ubidev +- return 0 +- fi +- done +-} +- +-nand_get_magic_long() { +- dd if="$1" skip=$2 bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' +-} +- +-get_magic_long_tar() { +- ( tar xf $1 $2 -O | dd bs=4 count=1 | hexdump -v -n 4 -e '1/1 "%02x"') 2> /dev/null +-} +- +-identify_magic() { +- local magic=$1 +- case "$magic" in +- "55424923") +- echo "ubi" +- ;; +- "31181006") +- echo "ubifs" +- ;; +- "68737173") +- echo "squashfs" +- ;; +- "d00dfeed") +- echo "fit" +- ;; +- "4349"*) +- echo "combined" +- ;; +- *) +- echo "unknown $magic" +- ;; +- esac +-} +- +- +-identify() { +- identify_magic $(nand_get_magic_long "$1" "${2:-0}") +-} +- +-identify_tar() { +- identify_magic $(get_magic_long_tar "$1" "$2") +-} +- +-nand_restore_config() { +- sync +- local ubidev=$( nand_find_ubi $CI_UBIPART ) +- local ubivol="$( nand_find_volume $ubidev rootfs_data )" +- [ ! "$ubivol" ] && +- ubivol="$( nand_find_volume $ubidev rootfs )" +- mkdir /tmp/new_root +- if ! mount -t ubifs /dev/$ubivol /tmp/new_root; then +- echo "mounting ubifs $ubivol failed" +- rmdir /tmp/new_root +- return 1 +- fi +- mv "$1" "/tmp/new_root/sysupgrade.tgz" +- umount /tmp/new_root +- sync +- rmdir /tmp/new_root +-} +- +-nand_upgrade_prepare_ubi() { +- local rootfs_length="$1" +- local rootfs_type="$2" +- local has_kernel="${3:-0}" +- local has_env="${4:-0}" +- +- local mtdnum="$( find_mtd_index "$CI_UBIPART" )" +- if [ ! "$mtdnum" ]; then +- echo "cannot find ubi mtd partition $CI_UBIPART" +- return 1 +- fi +- +- local ubidev="$( nand_find_ubi "$CI_UBIPART" )" +- if [ ! "$ubidev" ]; then +- ubiattach -m "$mtdnum" +- sync +- ubidev="$( nand_find_ubi "$CI_UBIPART" )" +- fi +- +- if [ ! "$ubidev" ]; then +- ubiformat /dev/mtd$mtdnum -y +- ubiattach -m "$mtdnum" +- sync +- ubidev="$( nand_find_ubi "$CI_UBIPART" )" +- [ "$has_env" -gt 0 ] && { +- ubimkvol /dev/$ubidev -n 0 -N ubootenv -s 1MiB +- ubimkvol /dev/$ubidev -n 1 -N ubootenv2 -s 1MiB +- } +- fi +- +- local kern_ubivol="$( nand_find_volume $ubidev kernel )" +- local root_ubivol="$( nand_find_volume $ubidev rootfs )" +- local data_ubivol="$( nand_find_volume $ubidev rootfs_data )" +- +- # remove ubiblock device of rootfs +- local root_ubiblk="ubiblock${root_ubivol:3}" +- if [ "$root_ubivol" -a -e "/dev/$root_ubiblk" ]; then +- echo "removing $root_ubiblk" +- if ! ubiblock -r /dev/$root_ubivol; then +- echo "cannot remove $root_ubiblk" +- return 1; +- fi +- fi +- +- # kill volumes +- [ "$kern_ubivol" ] && ubirmvol /dev/$ubidev -N kernel || true +- [ "$root_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs || true +- [ "$data_ubivol" ] && ubirmvol /dev/$ubidev -N rootfs_data || true +- +- # update kernel +- if [ "$has_kernel" = "1" ]; then +- if ! ubimkvol /dev/$ubidev -N kernel -s $kernel_length; then +- echo "cannot create kernel volume" +- return 1; +- fi +- fi +- +- # update rootfs +- local root_size_param +- if [ "$rootfs_type" = "ubifs" ]; then +- root_size_param="-m" +- else +- root_size_param="-s $rootfs_length" +- fi +- if ! ubimkvol /dev/$ubidev -N rootfs $root_size_param; then +- echo "cannot create rootfs volume" +- return 1; +- fi +- +- # create rootfs_data for non-ubifs rootfs +- if [ "$rootfs_type" != "ubifs" ]; then +- if ! ubimkvol /dev/$ubidev -N rootfs_data -m; then +- echo "cannot initialize rootfs_data volume" +- return 1 +- fi +- fi +- sync +- return 0 +-} +- +-nand_do_upgrade_success() { +- local conf_tar="/tmp/sysupgrade.tgz" +- +- sync +- [ -f "$conf_tar" ] && nand_restore_config "$conf_tar" +- echo "sysupgrade successful" +- umount -a +- reboot -f +-} +- +-# Flash the UBI image to MTD partition +-nand_upgrade_ubinized() { +- local ubi_file="$1" +- local mtdnum="$(find_mtd_index "$CI_UBIPART")" +- +- [ ! "$mtdnum" ] && { +- CI_UBIPART="rootfs" +- mtdnum="$(find_mtd_index "$CI_UBIPART")" +- } +- +- if [ ! "$mtdnum" ]; then +- echo "cannot find mtd device $CI_UBIPART" +- umount -a +- reboot -f +- fi +- +- local mtddev="/dev/mtd${mtdnum}" +- ubidetach -p "${mtddev}" || true +- sync +- ubiformat "${mtddev}" -y -f "${ubi_file}" +- ubiattach -p "${mtddev}" +- nand_do_upgrade_success +-} +- +-# Write the UBIFS image to UBI volume +-nand_upgrade_ubifs() { +- local rootfs_length=`(cat $1 | wc -c) 2> /dev/null` +- +- nand_upgrade_prepare_ubi "$rootfs_length" "ubifs" "0" "0" +- +- local ubidev="$( nand_find_ubi "$CI_UBIPART" )" +- local root_ubivol="$(nand_find_volume $ubidev rootfs)" +- ubiupdatevol /dev/$root_ubivol -s $rootfs_length $1 +- +- nand_do_upgrade_success +-} +- +-nand_board_name() { +- if type 'platform_nand_board_name' >/dev/null 2>/dev/null; then +- platform_nand_board_name +- return +- fi +- +- cat /tmp/sysinfo/board_name +-} +- +-nand_upgrade_tar() { +- local tar_file="$1" +- local board_name="$(nand_board_name)" +- local kernel_mtd="$(find_mtd_index $CI_KERNPART)" +- +- local kernel_length=`(tar xf $tar_file sysupgrade-$board_name/kernel -O | wc -c) 2> /dev/null` +- local rootfs_length=`(tar xf $tar_file sysupgrade-$board_name/root -O | wc -c) 2> /dev/null` +- +- local rootfs_type="$(identify_tar "$tar_file" sysupgrade-$board_name/root)" +- +- local has_kernel=1 +- local has_env=0 +- +- [ "$kernel_length" != 0 -a -n "$kernel_mtd" ] && { +- tar xf $tar_file sysupgrade-$board_name/kernel -O | mtd write - $CI_KERNPART +- } +- [ "$kernel_length" = 0 -o ! -z "$kernel_mtd" ] && has_kernel=0 +- +- nand_upgrade_prepare_ubi "$rootfs_length" "$rootfs_type" "$has_kernel" "$has_env" +- +- local ubidev="$( nand_find_ubi "$CI_UBIPART" )" +- [ "$has_kernel" = "1" ] && { +- local kern_ubivol="$(nand_find_volume $ubidev kernel)" +- tar xf $tar_file sysupgrade-$board_name/kernel -O | \ +- ubiupdatevol /dev/$kern_ubivol -s $kernel_length - +- } +- +- local root_ubivol="$(nand_find_volume $ubidev rootfs)" +- tar xf $tar_file sysupgrade-$board_name/root -O | \ +- ubiupdatevol /dev/$root_ubivol -s $rootfs_length - +- +- nand_do_upgrade_success +-} +- +-# Recognize type of passed file and start the upgrade process +-nand_do_upgrade_stage2() { +- local file_type=$(identify $1) +- +- if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then +- platform_nand_pre_upgrade "$1" +- fi +- +- [ ! "$(find_mtd_index "$CI_UBIPART")" ] && CI_UBIPART="rootfs" +- +- case "$file_type" in +- "ubi") nand_upgrade_ubinized $1;; +- "ubifs") nand_upgrade_ubifs $1;; +- *) nand_upgrade_tar $1;; +- esac +-} +- +-nand_upgrade_stage2() { +- [ $1 = "nand" ] && { +- [ -f "$2" ] && { +- touch /tmp/sysupgrade +- +- killall -9 telnetd +- killall -9 dropbear +- killall -9 ash +- +- kill_remaining TERM +- sleep 3 +- kill_remaining KILL +- +- sleep 1 +- +- if [ -n "$(rootfs_type)" ]; then +- v "Switching to ramdisk..." +- run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2" +- else +- nand_do_upgrade_stage2 $2 +- fi +- return 0 +- } +- echo "Nand upgrade failed" +- exit 1 +- } +-} +- +-nand_upgrade_stage1() { +- [ -f /tmp/sysupgrade-nand-path ] && { +- path="$(cat /tmp/sysupgrade-nand-path)" +- [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] && +- rm $CONF_TAR +- +- ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }" +- exit 0 +- } +-} +- +-# Check if passed file is a valid one for NAND sysupgrade. Currently it accepts +-# 3 types of files: +-# 1) UBI - should contain an ubinized image, header is checked for the proper +-# MAGIC +-# 2) UBIFS - should contain UBIFS partition that will replace "rootfs" volume, +-# header is checked for the proper MAGIC +-# 3) TAR - archive has to include "sysupgrade-BOARD" directory with a non-empty +-# "CONTROL" file (at this point its content isn't verified) +-# +-# You usually want to call this function in platform_check_image. +-# +-# $(1): board name, used in case of passing TAR file +-# $(2): file to be checked +-nand_do_platform_check() { +- local board_name="$1" +- local tar_file="$2" +- local control_length=`(tar xf $tar_file sysupgrade-$board_name/CONTROL -O | wc -c) 2> /dev/null` +- local file_type="$(identify $2)" +- +- [ "$control_length" = 0 -a "$file_type" != "ubi" -a "$file_type" != "ubifs" ] && { +- echo "Invalid sysupgrade file." +- return 1 +- } +- +- return 0 +-} +- +-# Start NAND upgrade process +-# +-# $(1): file to be used for upgrade +-nand_do_upgrade() { +- echo -n $1 > /tmp/sysupgrade-nand-path +- install_bin /sbin/upgraded +- ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded +- nand_upgrade_stage1 +-} diff --git a/patches/lede/0015-base-files-always-use-staged-sysupgrade.patch b/patches/lede/0015-base-files-always-use-staged-sysupgrade.patch new file mode 100644 index 00000000..003e74b9 --- /dev/null +++ b/patches/lede/0015-base-files-always-use-staged-sysupgrade.patch @@ -0,0 +1,476 @@ +From: Matthias Schiffer +Date: Sat, 22 Apr 2017 00:54:50 +0200 +Subject: base-files: always use staged sysupgrade + +Support for the -d and -p options is dropped; it may be added again at some +point by adding these flags to the ubus sysupgrade call. + +A downside of this is that we get a lot less information about the progress +of the upgrade: as soon as the actual upgrade starts, all shell sessions +are killed to allow unmounting the root filesystem. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh +index 8c1b3b180e1ecfdd2c106dd3b8853cd487ff89b4..ef9aac709fc1619ba15eeb0aeb4a9a6a372369b2 100644 +--- a/package/base-files/files/lib/upgrade/common.sh ++++ b/package/base-files/files/lib/upgrade/common.sh +@@ -56,7 +56,6 @@ run_ramfs() { # [...] + /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \ + /bin/mknod + +- install_bin /bin/uclient-fetch /bin/wget + install_bin /sbin/mtd + install_bin /sbin/mount_root + install_bin /sbin/snapshot +@@ -96,51 +95,37 @@ run_ramfs() { # [...] + exec /bin/busybox ash -c "$*" + } + +-kill_remaining() { # [ ] ++kill_remaining() { # [ [ ] ] + local sig="${1:-TERM}" ++ local loop="${2:-0}" ++ local run=true ++ local stat ++ + echo -n "Sending $sig to remaining processes ... " + +- local my_pid=$$ +- local my_ppid=$(cut -d' ' -f4 /proc/$my_pid/stat) +- local my_ppisupgraded= +- grep -q upgraded /proc/$my_ppid/cmdline >/dev/null && { +- local my_ppisupgraded=1 +- } +- +- local stat +- for stat in /proc/[0-9]*/stat; do +- [ -f "$stat" ] || continue +- +- local pid name state ppid rest +- read pid name state ppid rest < $stat +- name="${name#(}"; name="${name%)}" +- +- local cmdline +- read cmdline < /proc/$pid/cmdline +- +- # Skip kernel threads +- [ -n "$cmdline" ] || continue +- +- if [ $$ -eq 1 ] || [ $my_ppid -eq 1 ] && [ -n "$my_ppisupgraded" ]; then +- # Running as init process, kill everything except me +- if [ $pid -ne $$ ] && [ $pid -ne $my_ppid ]; then +- echo -n "$name " +- kill -$sig $pid 2>/dev/null +- fi +- else +- case "$name" in +- # Skip essential services +- *procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*|*relayd*) : ;; +- +- # Killable process +- *) +- if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then +- echo -n "$name " +- kill -$sig $pid 2>/dev/null +- fi +- ;; +- esac +- fi ++ while $run; do ++ run=false ++ for stat in /proc/[0-9]*/stat; do ++ [ -f "$stat" ] || continue ++ ++ local pid name state ppid rest ++ read pid name state ppid rest < $stat ++ name="${name#(}"; name="${name%)}" ++ ++ # Skip PID1, ourself and our children ++ [ $pid -ne 1 -a $pid -ne $$ -a $ppid -ne $$ ] || continue ++ ++ local cmdline ++ read cmdline < /proc/$pid/cmdline ++ ++ # Skip kernel threads ++ [ -n "$cmdline" ] || continue ++ ++ echo -n "$name " ++ kill -$sig $pid 2>/dev/null ++ ++ [ $loop -eq 1 ] && run=true ++ done + done + echo "" + } +@@ -175,28 +160,31 @@ v() { + [ "$VERBOSE" -ge 1 ] && echo "$@" + } + ++json_string() { ++ local v="$1" ++ v="${v//\\/\\\\}" ++ v="${v//\"/\\\"}" ++ echo "\"$v\"" ++} ++ + rootfs_type() { + /bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }' + } + + get_image() { # [ ] + local from="$1" +- local conc="$2" +- local cmd +- +- case "$from" in +- http://*|ftp://*) cmd="wget -O- -q";; +- *) cmd="cat";; +- esac +- if [ -z "$conc" ]; then +- local magic="$(eval $cmd \"$from\" 2>/dev/null | dd bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')" ++ local cat="$2" ++ ++ if [ -z "$cat" ]; then ++ local magic="$(dd if="$from" bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')" + case "$magic" in +- 1f8b) conc="zcat";; +- 425a) conc="bzcat";; ++ 1f8b) cat="zcat";; ++ 425a) cat="bzcat";; ++ *) cat="cat";; + esac + fi + +- eval "$cmd \"$from\" 2>/dev/null ${conc:+| $conc}" ++ $cat "$from" 2>/dev/null + } + + get_magic_word() { +@@ -331,12 +319,14 @@ default_do_upgrade() { + fi + } + +-do_upgrade() { ++do_upgrade_stage2() { + v "Performing system upgrade..." +- if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then +- platform_do_upgrade "$ARGV" ++ if [ -n "$do_upgrade" ]; then ++ $do_upgrade "$IMAGE" ++ elif type 'platform_do_upgrade' >/dev/null 2>/dev/null; then ++ platform_do_upgrade "$IMAGE" + else +- default_do_upgrade "$ARGV" ++ default_do_upgrade "$IMAGE" + fi + + if [ "$SAVE_CONFIG" -eq 1 ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then +@@ -344,12 +334,11 @@ do_upgrade() { + fi + + v "Upgrade completed" +- [ -n "$DELAY" ] && sleep "$DELAY" +- ask_bool 1 "Reboot" && { +- v "Rebooting system..." +- umount -a +- reboot -f +- sleep 5 +- echo b 2>/dev/null >/proc/sysrq-trigger +- } ++ sleep 1 ++ ++ v "Rebooting system..." ++ umount -a ++ reboot -f ++ sleep 5 ++ echo b 2>/dev/null >/proc/sysrq-trigger + } +diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh +index 6bd2005344c081df20e5a330a69e49e37225c39f..1e69c8f9657b39adf2a2c33bd9bac9303bcbc3d7 100644 +--- a/package/base-files/files/lib/upgrade/nand.sh ++++ b/package/base-files/files/lib/upgrade/nand.sh +@@ -283,7 +283,16 @@ nand_upgrade_tar() { + } + + # Recognize type of passed file and start the upgrade process +-nand_do_upgrade_stage2() { ++nand_do_upgrade() { ++ if [ -n "$IS_PRE_UPGRADE" ]; then ++ # Previously, nand_do_upgrade was called from the platform_pre_upgrade ++ # hook; this piece of code handles scripts that haven't been ++ # updated. All scripts should gradually move to call nand_do_upgrade ++ # from platform_do_upgrade instead. ++ export do_upgrade=nand_do_upgrade ++ return ++ fi ++ + local file_type=$(identify $1) + + if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then +@@ -299,45 +308,6 @@ nand_do_upgrade_stage2() { + esac + } + +-nand_upgrade_stage2() { +- [ $1 = "nand" ] && { +- [ -f "$2" ] && { +- touch /tmp/sysupgrade +- +- killall -9 telnetd +- killall -9 dropbear +- killall -9 ash +- +- kill_remaining TERM +- sleep 3 +- kill_remaining KILL +- +- sleep 1 +- +- if [ -n "$(rootfs_type)" ]; then +- v "Switching to ramdisk..." +- run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2" +- else +- nand_do_upgrade_stage2 $2 +- fi +- return 0 +- } +- echo "Nand upgrade failed" +- exit 1 +- } +-} +- +-nand_upgrade_stage1() { +- [ -f /tmp/sysupgrade-nand-path ] && { +- path="$(cat /tmp/sysupgrade-nand-path)" +- [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] && +- rm $CONF_TAR +- +- ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }" +- exit 0 +- } +-} +- + # Check if passed file is a valid one for NAND sysupgrade. Currently it accepts + # 3 types of files: + # 1) UBI - should contain an ubinized image, header is checked for the proper +@@ -364,13 +334,3 @@ nand_do_platform_check() { + + return 0 + } +- +-# Start NAND upgrade process +-# +-# $(1): file to be used for upgrade +-nand_do_upgrade() { +- echo -n $1 > /tmp/sysupgrade-nand-path +- install_bin /sbin/upgraded +- ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded +- nand_upgrade_stage1 +-} +diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 +new file mode 100755 +index 0000000000000000000000000000000000000000..4e2aa3a23c3bab07a795762a30a4d4f701081934 +--- /dev/null ++++ b/package/base-files/files/lib/upgrade/stage2 +@@ -0,0 +1,50 @@ ++#!/bin/sh ++ ++. /lib/functions.sh ++. /lib/functions/system.sh ++ ++export IMAGE="$1" ++COMMAND="$2" ++ ++export ARGV="$IMAGE" ++export ARGC=1 ++ ++export SAVE_CONFIG=1 ++export SAVE_PARTITIONS=1 ++ ++export INTERACTIVE=0 ++export VERBOSE=1 ++export CONFFILES=/tmp/sysupgrade.conffiles ++export CONF_TAR=/tmp/sysupgrade.tgz ++ ++ ++[ -f "$CONF_TAR" ] || export SAVE_CONFIG=0 ++[ -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap ] && export SAVE_PARTITIONS=0 ++ ++include /lib/upgrade ++ ++ ++killall -9 telnetd ++killall -9 dropbear ++killall -9 ash ++ ++kill_remaining TERM ++sleep 3 ++kill_remaining KILL 1 ++ ++sleep 1 ++ ++ ++if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then ++ IS_PRE_UPGRADE=1 platform_pre_upgrade "$IMAGE" ++ ++ # Needs to be unset again because of busybox weirdness ... ++ IS_PRE_UPGRADE= ++fi ++ ++if [ -n "$(rootfs_type)" ]; then ++ echo "Switching to ramdisk..." ++ run_ramfs "$COMMAND" ++else ++ exec /bin/busybox ash -c "$COMMAND" ++fi +diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade +index 71c7faa6dbc485ff33e776ff087e1aca58cfb0b0..fa08f4194daa0ee74758b9f49a23fe8dcb4b933d 100755 +--- a/package/base-files/files/sbin/sysupgrade ++++ b/package/base-files/files/sbin/sysupgrade +@@ -1,4 +1,7 @@ + #!/bin/sh ++ ++[ "$1" = "nand" ] && exec /lib/upgrade/stage2 "$2" "$3" ++ + . /lib/functions.sh + . /lib/functions/system.sh + +@@ -11,7 +14,6 @@ export VERBOSE=1 + export SAVE_CONFIG=1 + export SAVE_OVERLAY=0 + export SAVE_PARTITIONS=1 +-export DELAY= + export CONF_IMAGE= + export CONF_BACKUP_LIST=0 + export CONF_BACKUP= +@@ -25,7 +27,6 @@ export TEST=0 + while [ -n "$1" ]; do + case "$1" in + -i) export INTERACTIVE=1;; +- -d) export DELAY="$2"; shift;; + -v) export VERBOSE="$(($VERBOSE + 1))";; + -q) export VERBOSE="$(($VERBOSE - 1))";; + -n) export SAVE_CONFIG=0;; +@@ -50,10 +51,9 @@ done + export CONFFILES=/tmp/sysupgrade.conffiles + export CONF_TAR=/tmp/sysupgrade.tgz + +-export ARGV="$*" +-export ARGC="$#" ++IMAGE="$1" + +-[ -z "$ARGV" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && { ++[ -z "$IMAGE" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && { + cat <...] + $0 [-q] [-i] +@@ -90,7 +90,7 @@ EOF + exit 1 + } + +-[ -n "$ARGV" -a -n "$NEED_IMAGE" ] && { ++[ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && { + cat <<-EOF + -b|--create-backup and -r|--restore-backup do not perform a firmware upgrade. + Do not specify both -b|-r and a firmware image. +@@ -155,14 +155,13 @@ sysupgrade_pre_upgrade="fwtool_pre_upgrade" + + include /lib/upgrade + +-[ "$1" = "nand" ] && nand_upgrade_stage2 $@ +- + do_save_conffiles() { + local conf_tar="${1:-$CONF_TAR}" + + [ -z "$(rootfs_type)" ] && { + echo "Cannot save config while running from ramdisk." + ask_bool 0 "Abort" && exit ++ rm -f "$conf_tar" + return 0 + } + run_hooks "$CONFFILES" $sysupgrade_init_conffiles +@@ -203,8 +202,33 @@ type platform_check_image >/dev/null 2>/dev/null || { + exit 1 + } + ++case "$IMAGE" in ++ http://*) ++ wget -O/tmp/sysupgrade.img "$IMAGE" ++ IMAGE=/tmp/sysupgrade.img ++ ;; ++esac ++ ++IMAGE="$(readlink -f "$IMAGE")" ++ ++case "$IMAGE" in ++ '') ++ echo "Image file not found." ++ exit 1 ++ ;; ++ /tmp/*) ;; ++ *) ++ v "Image not in /tmp, copying..." ++ cp -f "$IMAGE" /tmp/sysupgrade.img ++ IMAGE=/tmp/sysupgrade.img ++ ;; ++esac ++ ++export ARGV="$IMAGE" ++export ARGC=1 ++ + for check in $sysupgrade_image_check; do +- ( eval "$check \"\$ARGV\"" ) || { ++ ( $check "$IMAGE" ) || { + if [ $FORCE -eq 1 ]; then + echo "Image check '$check' failed but --force given - will update anyway!" + break +@@ -230,6 +254,7 @@ elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then + [ $TEST -eq 1 ] || do_save_conffiles + export SAVE_CONFIG=1 + else ++ [ $TEST -eq 1 ] || rm -f "$CONF_TAR" + export SAVE_CONFIG=0 + fi + +@@ -237,28 +262,18 @@ if [ $TEST -eq 1 ]; then + exit 0 + fi + +-run_hooks "" $sysupgrade_pre_upgrade +- +-# Some platforms/devices may want different sysupgrade process, e.g. without +-# killing processes yet or calling ubus system upgrade method. +-# This is needed e.g. on NAND devices where we just want to trigger stage1 at +-# this point. +-if type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then +- platform_pre_upgrade "$ARGV" ++if [ $SAVE_PARTITIONS -eq 0 ]; then ++ touch /tmp/sysupgrade.always.overwrite.bootdisk.partmap ++else ++ rm -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap + fi + +-ubus call system upgrade +-touch /tmp/sysupgrade +- +-if [ ! -f /tmp/failsafe ] ; then +- kill_remaining TERM +- sleep 3 +- kill_remaining KILL +-fi ++run_hooks "" $sysupgrade_pre_upgrade + +-if [ -n "$(rootfs_type)" ]; then +- v "Switching to ramdisk..." +- run_ramfs '. /lib/functions.sh; include /lib/upgrade; do_upgrade' +-else +- do_upgrade +-fi ++install_bin /sbin/upgraded ++v "Commencing upgrade. All shell sessions will be closed now." ++ubus call system sysupgrade "{ ++ \"prefix\": \"$RAM_ROOT\", ++ \"path\": $(json_string "$IMAGE"), ++ \"command\": \". /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2\" ++}" diff --git a/patches/lede/0016-fstools-clean-up-trailing-whitespace-in-snapshot-script.patch b/patches/lede/0016-fstools-clean-up-trailing-whitespace-in-snapshot-script.patch new file mode 100644 index 00000000..2df0942a --- /dev/null +++ b/patches/lede/0016-fstools-clean-up-trailing-whitespace-in-snapshot-script.patch @@ -0,0 +1,19 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 08:29:24 +0200 +Subject: fstools: clean up trailing whitespace in snapshot script + +Signed-off-by: Matthias Schiffer + +diff --git a/package/system/fstools/files/snapshot b/package/system/fstools/files/snapshot +index c1a5b733f3c70e2bb5f2e83d3589e2f10832760f..baf24f1e3e90fe7708e0f28c17ba270a35a2cd52 100644 +--- a/package/system/fstools/files/snapshot ++++ b/package/system/fstools/files/snapshot +@@ -42,7 +42,7 @@ do_snapshot_upgrade() { + + opkg list-upgradable + [ $? -eq 0 ] || exit 2 +- ++ + UPDATES=`opkg list-upgradable | cut -d" " -f1` + [ -z "${UPDATES}" ] && exit 0 + diff --git a/patches/lede/0017-fstools-snapshot-handle-jffs2-conversion-using-upgraded.patch b/patches/lede/0017-fstools-snapshot-handle-jffs2-conversion-using-upgraded.patch new file mode 100644 index 00000000..2b1d4ff3 --- /dev/null +++ b/patches/lede/0017-fstools-snapshot-handle-jffs2-conversion-using-upgraded.patch @@ -0,0 +1,49 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 08:29:55 +0200 +Subject: fstools: snapshot: handle jffs2 conversion using upgraded + +We can reuse the kill_remaining and run_ramfs facilities of the stage2 run +by upgraded. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/system/fstools/Makefile b/package/system/fstools/Makefile +index 6f1f511d387e900426832f40966012bc11d53075..f2e0580912ab7d475fab576bea4fd84f0dfe6a3d 100644 +--- a/package/system/fstools/Makefile ++++ b/package/system/fstools/Makefile +@@ -8,7 +8,7 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=fstools +-PKG_RELEASE:=1 ++PKG_RELEASE:=2 + + PKG_SOURCE_PROTO:=git + PKG_SOURCE_URL=$(LEDE_GIT)/project/fstools.git +diff --git a/package/system/fstools/files/snapshot b/package/system/fstools/files/snapshot +index baf24f1e3e90fe7708e0f28c17ba270a35a2cd52..a495e3434523b7a4b1b2f1bc3f4c9298197fc745 100644 +--- a/package/system/fstools/files/snapshot ++++ b/package/system/fstools/files/snapshot +@@ -64,14 +64,16 @@ do_convert_jffs2() { + do_convert() { + . /lib/functions.sh + . /lib/upgrade/common.sh +- ubus call system upgrade +- touch /tmp/sysupgrade ++ + cd /overlay/upper + tar czf /tmp/snapshot.tar.gz * +- kill_remaining TERM +- sleep 3 +- kill_remaining KILL +- run_ramfs '. /sbin/snapshot; do_convert_jffs2' ++ ++ install_bin /sbin/upgraded ++ ubus call system sysupgrade "{ ++ \"prefix\": \"$RAM_ROOT\", ++ \"path\": \"\", ++ \"command\": \". /sbin/snapshot; do_convert_jffs2\" ++ }" + } + + [ -n "$(cat /proc/mounts|grep /overlay|grep jffs2)" ] && { diff --git a/patches/lede/0018-base-files-sysupgrade-cleanup.patch b/patches/lede/0018-base-files-sysupgrade-cleanup.patch new file mode 100644 index 00000000..61ba1717 --- /dev/null +++ b/patches/lede/0018-base-files-sysupgrade-cleanup.patch @@ -0,0 +1,258 @@ +From: Matthias Schiffer +Date: Sun, 23 Apr 2017 23:33:14 +0200 +Subject: base-files: sysupgrade cleanup + +Some functions only used by stage2 are moved there from common.sh. + +One piece that could still use more cleanup is platform_pre_upgrade: many +targets reference files from there are aren't available in the ramfs, so +we need to evaluate it before the switch; conversely, flash writes happen +in that function on some targets. Targets that do the latter should be +fixed eventually to use platform_do_upgrade for that purpose. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh +index ef9aac709fc1619ba15eeb0aeb4a9a6a372369b2..af7682c29e005c6ca47b91e9be2d60c359a90d05 100644 +--- a/package/base-files/files/lib/upgrade/common.sh ++++ b/package/base-files/files/lib/upgrade/common.sh +@@ -30,106 +30,6 @@ install_bin() { # [ ... ] + }; done + } + +-supivot() { # +- /bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1 +- mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \ +- /bin/mount -o noatime,move /proc $1/proc && \ +- pivot_root $1 $1$2 || { +- /bin/umount -l $1 $1 +- return 1 +- } +- +- /bin/mount -o noatime,move $2/sys /sys +- /bin/mount -o noatime,move $2/dev /dev +- /bin/mount -o noatime,move $2/tmp /tmp +- /bin/mount -o noatime,move $2/overlay /overlay 2>&- +- return 0 +-} +- +-run_ramfs() { # [...] +- install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \ +- /sbin/pivot_root /sbin/reboot /bin/sync /bin/dd /bin/grep \ +- /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" /bin/dd \ +- /bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump \ +- /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc \ +- /bin/cut /usr/bin/printf /bin/sync /bin/mkdir /bin/rmdir \ +- /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \ +- /bin/mknod +- +- install_bin /sbin/mtd +- install_bin /sbin/mount_root +- install_bin /sbin/snapshot +- install_bin /sbin/snapshot_tool +- install_bin /usr/sbin/ubiupdatevol +- install_bin /usr/sbin/ubiattach +- install_bin /usr/sbin/ubiblock +- install_bin /usr/sbin/ubiformat +- install_bin /usr/sbin/ubidetach +- install_bin /usr/sbin/ubirsvol +- install_bin /usr/sbin/ubirmvol +- install_bin /usr/sbin/ubimkvol +- install_bin /usr/sbin/partx +- install_bin /usr/sbin/losetup +- install_bin /usr/sbin/mkfs.ext4 +- for file in $RAMFS_COPY_BIN; do +- install_bin ${file//:/ } +- done +- install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA +- +- [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64 +- +- supivot $RAM_ROOT /mnt || { +- echo "Failed to switch over to ramfs. Please reboot." +- exit 1 +- } +- +- /bin/mount -o remount,ro /mnt +- /bin/umount -l /mnt +- +- grep /overlay /proc/mounts > /dev/null && { +- /bin/mount -o noatime,remount,ro /overlay +- /bin/umount -l /overlay +- } +- +- # spawn a new shell from ramdisk to reduce the probability of cache issues +- exec /bin/busybox ash -c "$*" +-} +- +-kill_remaining() { # [ [ ] ] +- local sig="${1:-TERM}" +- local loop="${2:-0}" +- local run=true +- local stat +- +- echo -n "Sending $sig to remaining processes ... " +- +- while $run; do +- run=false +- for stat in /proc/[0-9]*/stat; do +- [ -f "$stat" ] || continue +- +- local pid name state ppid rest +- read pid name state ppid rest < $stat +- name="${name#(}"; name="${name%)}" +- +- # Skip PID1, ourself and our children +- [ $pid -ne 1 -a $pid -ne $$ -a $ppid -ne $$ ] || continue +- +- local cmdline +- read cmdline < /proc/$pid/cmdline +- +- # Skip kernel threads +- [ -n "$cmdline" ] || continue +- +- echo -n "$name " +- kill -$sig $pid 2>/dev/null +- +- [ $loop -eq 1 ] && run=true +- done +- done +- echo "" +-} +- + run_hooks() { + local arg="$1"; shift + for func in "$@"; do +diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 +index 4e2aa3a23c3bab07a795762a30a4d4f701081934..cc8047d988e39ca9ba27d2588744aad469d1d978 100755 +--- a/package/base-files/files/lib/upgrade/stage2 ++++ b/package/base-files/files/lib/upgrade/stage2 +@@ -24,6 +24,104 @@ export CONF_TAR=/tmp/sysupgrade.tgz + include /lib/upgrade + + ++supivot() { # ++ /bin/mount | grep "on $1 type" 2>&- 1>&- || /bin/mount -o bind $1 $1 ++ mkdir -p $1$2 $1/proc $1/sys $1/dev $1/tmp $1/overlay && \ ++ /bin/mount -o noatime,move /proc $1/proc && \ ++ pivot_root $1 $1$2 || { ++ /bin/umount -l $1 $1 ++ return 1 ++ } ++ ++ /bin/mount -o noatime,move $2/sys /sys ++ /bin/mount -o noatime,move $2/dev /dev ++ /bin/mount -o noatime,move $2/tmp /tmp ++ /bin/mount -o noatime,move $2/overlay /overlay 2>&- ++ return 0 ++} ++ ++switch_to_ramfs() { ++ install_bin /bin/busybox /bin/ash /bin/sh /bin/mount /bin/umount \ ++ /sbin/pivot_root /sbin/reboot /bin/sync /bin/dd /bin/grep \ ++ /bin/cp /bin/mv /bin/tar /usr/bin/md5sum "/usr/bin/[" /bin/dd \ ++ /bin/vi /bin/ls /bin/cat /usr/bin/awk /usr/bin/hexdump \ ++ /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc \ ++ /bin/cut /usr/bin/printf /bin/sync /bin/mkdir /bin/rmdir \ ++ /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \ ++ /bin/mknod ++ ++ install_bin /sbin/mtd ++ install_bin /sbin/mount_root ++ install_bin /sbin/snapshot ++ install_bin /sbin/snapshot_tool ++ install_bin /usr/sbin/ubiupdatevol ++ install_bin /usr/sbin/ubiattach ++ install_bin /usr/sbin/ubiblock ++ install_bin /usr/sbin/ubiformat ++ install_bin /usr/sbin/ubidetach ++ install_bin /usr/sbin/ubirsvol ++ install_bin /usr/sbin/ubirmvol ++ install_bin /usr/sbin/ubimkvol ++ install_bin /usr/sbin/partx ++ install_bin /usr/sbin/losetup ++ install_bin /usr/sbin/mkfs.ext4 ++ for file in $RAMFS_COPY_BIN; do ++ install_bin ${file//:/ } ++ done ++ install_file /etc/resolv.conf /lib/*.sh /lib/functions/*.sh /lib/upgrade/*.sh $RAMFS_COPY_DATA ++ ++ [ -L "/lib64" ] && ln -s /lib $RAM_ROOT/lib64 ++ ++ supivot $RAM_ROOT /mnt || { ++ echo "Failed to switch over to ramfs. Please reboot." ++ exit 1 ++ } ++ ++ /bin/mount -o remount,ro /mnt ++ /bin/umount -l /mnt ++ ++ grep /overlay /proc/mounts > /dev/null && { ++ /bin/mount -o noatime,remount,ro /overlay ++ /bin/umount -l /overlay ++ } ++} ++ ++kill_remaining() { # [ [ ] ] ++ local sig="${1:-TERM}" ++ local loop="${2:-0}" ++ local run=true ++ local stat ++ ++ echo -n "Sending $sig to remaining processes ... " ++ ++ while $run; do ++ run=false ++ for stat in /proc/[0-9]*/stat; do ++ [ -f "$stat" ] || continue ++ ++ local pid name state ppid rest ++ read pid name state ppid rest < $stat ++ name="${name#(}"; name="${name%)}" ++ ++ # Skip PID1, ourself and our children ++ [ $pid -ne 1 -a $pid -ne $$ -a $ppid -ne $$ ] || continue ++ ++ local cmdline ++ read cmdline < /proc/$pid/cmdline ++ ++ # Skip kernel threads ++ [ -n "$cmdline" ] || continue ++ ++ echo -n "$name " ++ kill -$sig $pid 2>/dev/null ++ ++ [ $loop -eq 1 ] && run=true ++ done ++ done ++ echo "" ++} ++ ++ + killall -9 telnetd + killall -9 dropbear + killall -9 ash +@@ -44,7 +142,8 @@ fi + + if [ -n "$(rootfs_type)" ]; then + echo "Switching to ramdisk..." +- run_ramfs "$COMMAND" +-else +- exec /bin/busybox ash -c "$COMMAND" ++ switch_to_ramfs + fi ++ ++# Exec new shell from ramfs ++exec /bin/busybox ash -c "$COMMAND" +diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade +index fa08f4194daa0ee74758b9f49a23fe8dcb4b933d..347860d00af27a61152703320bb210d30726db83 100755 +--- a/package/base-files/files/sbin/sysupgrade ++++ b/package/base-files/files/sbin/sysupgrade +@@ -1,7 +1,5 @@ + #!/bin/sh + +-[ "$1" = "nand" ] && exec /lib/upgrade/stage2 "$2" "$3" +- + . /lib/functions.sh + . /lib/functions/system.sh + diff --git a/patches/lede/0019-base-files-add-support-for-staged-sysupgrades-from-failsafe-mode.patch b/patches/lede/0019-base-files-add-support-for-staged-sysupgrades-from-failsafe-mode.patch new file mode 100644 index 00000000..688a30d9 --- /dev/null +++ b/patches/lede/0019-base-files-add-support-for-staged-sysupgrades-from-failsafe-mode.patch @@ -0,0 +1,72 @@ +From: Matthias Schiffer +Date: Mon, 24 Apr 2017 01:31:04 +0200 +Subject: base-files: add support for staged sysupgrades from failsafe mode + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/preinit/40_run_failsafe_hook b/package/base-files/files/lib/preinit/40_run_failsafe_hook +index 7301f77349a1a1e42fcef9bcbc927ef55c83b991..533b0a9771e1aac603f00ecf7a4622ea9fee969d 100644 +--- a/package/base-files/files/lib/preinit/40_run_failsafe_hook ++++ b/package/base-files/files/lib/preinit/40_run_failsafe_hook +@@ -5,8 +5,12 @@ + run_failsafe_hook() { + [ "$pi_preinit_no_failsafe" = "y" ] && return + if [ "$FAILSAFE" = "true" ]; then ++ lock /tmp/.failsafe + boot_run_hook failsafe +- lock -w /tmp/.failsafe ++ while [ ! -e /tmp/sysupgrade ]; do ++ lock -w /tmp/.failsafe ++ done ++ exit + fi + } + +diff --git a/package/base-files/files/lib/preinit/99_10_failsafe_login b/package/base-files/files/lib/preinit/99_10_failsafe_login +index 3147cdc5a68a69cef6b1af6618a4e2367a143c2c..728c63b2e8aebf970cd7dff0d15518ccda83029c 100644 +--- a/package/base-files/files/lib/preinit/99_10_failsafe_login ++++ b/package/base-files/files/lib/preinit/99_10_failsafe_login +@@ -8,10 +8,13 @@ failsafe_netlogin () { + } + + failsafe_shell() { +- lock /tmp/.failsafe +- ash --login +- echo "Please reboot system when done with failsafe network logins" +- while true; do sleep 1; done ++ local console="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | head -1 | sed -e 's/^console=//' -e 's/,.*//')" ++ [ -n "$console" ] || console=console ++ [ -c "/dev/$console" ] || return 0 ++ while true; do ++ ash --login <"/dev/$console" >"/dev/$console" 2>"/dev/$console" ++ sleep 1 ++ done & + } + + boot_hook_add failsafe failsafe_netlogin +diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade +index 347860d00af27a61152703320bb210d30726db83..4a133a65e0960619b9cd0d722b6c27ac7894de5b 100755 +--- a/package/base-files/files/sbin/sysupgrade ++++ b/package/base-files/files/sbin/sysupgrade +@@ -270,8 +270,16 @@ run_hooks "" $sysupgrade_pre_upgrade + + install_bin /sbin/upgraded + v "Commencing upgrade. All shell sessions will be closed now." +-ubus call system sysupgrade "{ +- \"prefix\": \"$RAM_ROOT\", +- \"path\": $(json_string "$IMAGE"), +- \"command\": \". /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2\" +-}" ++ ++COMMAND='. /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2' ++ ++if [ -n "$FAILSAFE" ]; then ++ printf '%s\x00%s\x00%s' "$RAM_ROOT" "$IMAGE" "$COMMAND" >/tmp/sysupgrade ++ lock -u /tmp/.failsafe ++else ++ ubus call system sysupgrade "{ ++ \"prefix\": $(json_string "$RAM_ROOT"), ++ \"path\": $(json_string "$IMAGE"), ++ \"command\": $(json_string "$COMMAND") ++ }" ++fi diff --git a/patches/lede/0020-ramips-sysupgrade-move-nand_do_upgrade-call-to-platform_do_upgrade.patch b/patches/lede/0020-ramips-sysupgrade-move-nand_do_upgrade-call-to-platform_do_upgrade.patch new file mode 100644 index 00000000..4663dbc6 --- /dev/null +++ b/patches/lede/0020-ramips-sysupgrade-move-nand_do_upgrade-call-to-platform_do_upgrade.patch @@ -0,0 +1,35 @@ +From: Matthias Schiffer +Date: Sat, 22 Apr 2017 21:27:04 +0200 +Subject: ramips: sysupgrade: move nand_do_upgrade call to platform_do_upgrade + +All targets with NAND support should gradually move their nand_do_upgrade +calls from platform_pre_upgrade to platform_do_upgrade. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh +index 7f5b1dd070b1bfe0b86b093a55165b5a139eb37c..a5cca2080d3b96cef92286b1b15f4f8832d9f8c5 100755 +--- a/target/linux/ramips/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh +@@ -254,20 +254,13 @@ platform_nand_pre_upgrade() { + esac + } + +-platform_pre_upgrade() { ++platform_do_upgrade() { + local board=$(ramips_board_name) + + case "$board" in + ubnt-erx) + nand_do_upgrade "$ARGV" + ;; +- esac +-} +- +-platform_do_upgrade() { +- local board=$(ramips_board_name) +- +- case "$board" in + *) + default_do_upgrade "$ARGV" + ;; diff --git a/patches/lede/0021-x86-sysupgrade-move-partition-table-change-check-to-platform_check_image.patch b/patches/lede/0021-x86-sysupgrade-move-partition-table-change-check-to-platform_check_image.patch new file mode 100644 index 00000000..8da5a5d2 --- /dev/null +++ b/patches/lede/0021-x86-sysupgrade-move-partition-table-change-check-to-platform_check_image.patch @@ -0,0 +1,62 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 08:57:29 +0200 +Subject: x86: sysupgrade: move partition table change check to platform_check_image + +The staged sysupgrade will prevent us from using ask_bool in +platform_do_upgrade; therefore, the check is moved to platform_check_image. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh +index d3e9f360aadedad0995da55205364940c9884ba4..81b349a81816033eef9df464b2a70fdb998e5a1d 100644 +--- a/target/linux/x86/base-files/lib/upgrade/platform.sh ++++ b/target/linux/x86/base-files/lib/upgrade/platform.sh +@@ -1,13 +1,37 @@ + platform_check_image() { ++ local diskdev partdev diff + [ "$#" -gt 1 ] && return 1 + + case "$(get_magic_word "$1")" in +- eb48|eb63) return 0;; ++ eb48|eb63) ;; + *) + echo "Invalid image type" + return 1 + ;; + esac ++ ++ export_bootdevice && export_partdevice diskdev 0 || { ++ echo "Unable to determine upgrade device" ++ return 1 ++ } ++ ++ get_partitions "/dev/$diskdev" bootdisk ++ ++ #extract the boot sector from the image ++ get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b 2>/dev/null ++ ++ get_partitions /tmp/image.bs image ++ ++ #compare tables ++ diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" ++ ++ rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image ++ ++ if [ -n "$diff" ]; then ++ echo "Partition layout has changed. Full image will be written." ++ ask_bool 0 "Abort" && exit 1 ++ return 0 ++ fi + } + + platform_copy_config() { +@@ -36,9 +60,6 @@ platform_do_upgrade() { + #compare tables + diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" + if [ -n "$diff" ]; then +- echo "Partition layout is changed. Full image will be written." +- ask_bool 0 "Abort" && exit +- + get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync + return 0 + fi diff --git a/patches/lede/0022-x86-sysupgrade-refactor-platform_do_upgrade.patch b/patches/lede/0022-x86-sysupgrade-refactor-platform_do_upgrade.patch new file mode 100644 index 00000000..a70f3ad4 --- /dev/null +++ b/patches/lede/0022-x86-sysupgrade-refactor-platform_do_upgrade.patch @@ -0,0 +1,90 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 09:05:25 +0200 +Subject: x86: sysupgrade: refactor platform_do_upgrade + +By returning early when no upgrade device can be found and handling the +SAVE_PARTITIONS=0 case differently, we can get rid of two levels of if. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh +index 81b349a81816033eef9df464b2a70fdb998e5a1d..4fa71999be7be3972676a1019488972dccd57fa2 100644 +--- a/target/linux/x86/base-files/lib/upgrade/platform.sh ++++ b/target/linux/x86/base-files/lib/upgrade/platform.sh +@@ -47,40 +47,43 @@ platform_copy_config() { + platform_do_upgrade() { + local diskdev partdev diff + +- if export_bootdevice && export_partdevice diskdev 0; then +- sync +- if [ "$SAVE_PARTITIONS" = "1" ]; then +- get_partitions "/dev/$diskdev" bootdisk +- +- #extract the boot sector from the image +- get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b +- +- get_partitions /tmp/image.bs image +- +- #compare tables +- diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" +- if [ -n "$diff" ]; then +- get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync +- return 0 +- fi +- +- #iterate over each partition from the image and write it to the boot disk +- while read part start size; do +- if export_partdevice partdev $part; then +- echo "Writing image to /dev/$partdev..." +- get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync +- else +- echo "Unable to find partition $part device, skipped." +- fi +- done < /tmp/partmap.image +- +- #copy partition uuid +- echo "Writing new UUID to /dev/$diskdev..." +- get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync ++ export_bootdevice && export_partdevice diskdev 0 || { ++ echo "Unable to determine upgrade device" ++ return 1 ++ } ++ ++ sync ++ ++ if [ "$SAVE_PARTITIONS" = "1" ]; then ++ get_partitions "/dev/$diskdev" bootdisk ++ ++ #extract the boot sector from the image ++ get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b ++ ++ get_partitions /tmp/image.bs image ++ ++ #compare tables ++ diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" ++ else ++ diff=1 ++ fi ++ ++ if [ -n "$diff" ]; then ++ get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync ++ return 0 ++ fi ++ ++ #iterate over each partition from the image and write it to the boot disk ++ while read part start size; do ++ if export_partdevice partdev $part; then ++ echo "Writing image to /dev/$partdev..." ++ get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync + else +- get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync ++ echo "Unable to find partition $part device, skipped." + fi ++ done < /tmp/partmap.image + +- sleep 1 +- fi ++ #copy partition uuid ++ echo "Writing new UUID to /dev/$diskdev..." ++ get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync + } diff --git a/patches/lede/0023-x86-sysupgrade-explicitly-rescan-disk-after-writing-partition-table.patch b/patches/lede/0023-x86-sysupgrade-explicitly-rescan-disk-after-writing-partition-table.patch new file mode 100644 index 00000000..4e46ce60 --- /dev/null +++ b/patches/lede/0023-x86-sysupgrade-explicitly-rescan-disk-after-writing-partition-table.patch @@ -0,0 +1,26 @@ +From: Matthias Schiffer +Date: Wed, 3 May 2017 09:08:29 +0200 +Subject: x86: sysupgrade: explicitly rescan disk after writing partition table + +This should ensure that the kernel partition can be mounted in +platform_copy_config when its size has changed. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh +index 4fa71999be7be3972676a1019488972dccd57fa2..439ba8f5125d97932248ff966340165a84e1b24a 100644 +--- a/target/linux/x86/base-files/lib/upgrade/platform.sh ++++ b/target/linux/x86/base-files/lib/upgrade/platform.sh +@@ -70,6 +70,12 @@ platform_do_upgrade() { + + if [ -n "$diff" ]; then + get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync ++ ++ # Separate removal and addtion is necessary; otherwise, partition 1 ++ # will be missing if it overlaps with the old partition 2 ++ partx -d - "/dev/$diskdev" ++ partx -a - "/dev/$diskdev" ++ + return 0 + fi + diff --git a/patches/lede/0024-sunxi-sysupgrade-don-t-write-partitions-twice.patch b/patches/lede/0024-sunxi-sysupgrade-don-t-write-partitions-twice.patch new file mode 100644 index 00000000..6aabf26b --- /dev/null +++ b/patches/lede/0024-sunxi-sysupgrade-don-t-write-partitions-twice.patch @@ -0,0 +1,29 @@ +From: Matthias Schiffer +Date: Thu, 4 May 2017 07:29:58 +0200 +Subject: sunxi: sysupgrade: don't write partitions twice + +When existing partitions are retained, the dd call writing the uboot image +in the space before the first partition was accidentally writing the whole +image, making the code for individual partitions redundant. Limit the copy +to 1016KiB (the first 8KiB are skipped, and the first partition starts at +1024KiB). + +In addition, conv=notrunc is replaced with conv=fsync. It seems this was an +oversight, as notrunc doesn't make sense for block devices and all other dd +commands use conv=fsync. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/sunxi/base-files/lib/upgrade/platform.sh b/target/linux/sunxi/base-files/lib/upgrade/platform.sh +index f2cd970d428a780d7497d8802765c656a47ff421..776bdf53bf89c5eafc24b7b59b943e12f3fab77e 100644 +--- a/target/linux/sunxi/base-files/lib/upgrade/platform.sh ++++ b/target/linux/sunxi/base-files/lib/upgrade/platform.sh +@@ -43,7 +43,7 @@ platform_do_upgrade() { + fi + + #write uboot image +- get_image "$@" | dd of="$diskdev" bs=1024 skip=8 seek=8 conv=notrunc ++ get_image "$@" | dd of="$diskdev" bs=1024 skip=8 seek=8 count=1016 conv=fsync + #iterate over each partition from the image and write it to the boot disk + while read part start size; do + part="$(($part - 2))" diff --git a/patches/lede/0025-sunxi-sysupgrade-sync-with-x86.patch b/patches/lede/0025-sunxi-sysupgrade-sync-with-x86.patch new file mode 100644 index 00000000..293d07d7 --- /dev/null +++ b/patches/lede/0025-sunxi-sysupgrade-sync-with-x86.patch @@ -0,0 +1,163 @@ +From: Matthias Schiffer +Date: Thu, 4 May 2017 07:39:20 +0200 +Subject: sunxi: sysupgrade: sync with x86 + +sunxi sysupgrade was based on the x86 implementation; sync fixes and other +changes from the current x86 version: + +x86: fix sysupgrades on disks with 4k block size +x86: sysupgrade: move partition table change check to platform_check_image +x86: sysupgrade: refactor platform_do_upgrade +x86: sysupgrade: explicitly rescan disk after writing partition table + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/sunxi/Makefile b/target/linux/sunxi/Makefile +index 3c2f14b8418e1d296a239027f6fdee9b5ba8f9b2..f8b8aa750a7145c9954df5a5a6a2e85f2610a72f 100644 +--- a/target/linux/sunxi/Makefile ++++ b/target/linux/sunxi/Makefile +@@ -28,6 +28,6 @@ KERNELNAME:=zImage dtbs + include $(INCLUDE_DIR)/target.mk + + DEFAULT_PACKAGES += uboot-envtools +-DEFAULT_PACKAGES += mkf2fs e2fsprogs ++DEFAULT_PACKAGES += partx-utils mkf2fs e2fsprogs + + $(eval $(call BuildTarget)) +diff --git a/target/linux/sunxi/base-files/lib/upgrade/platform.sh b/target/linux/sunxi/base-files/lib/upgrade/platform.sh +index 776bdf53bf89c5eafc24b7b59b943e12f3fab77e..88ef4790e9c1452f8ce57fe1c265ce47810830ee 100644 +--- a/target/linux/sunxi/base-files/lib/upgrade/platform.sh ++++ b/target/linux/sunxi/base-files/lib/upgrade/platform.sh +@@ -1,5 +1,28 @@ + platform_check_image() { +- true ++ local diskdev partdev diff ++ ++ export_bootdevice && export_partdevice diskdev -2 || { ++ echo "Unable to determine upgrade device" ++ return 1 ++ } ++ ++ get_partitions "/dev/$diskdev" bootdisk ++ ++ #extract the boot sector from the image ++ get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b 2>/dev/null ++ ++ get_partitions /tmp/image.bs image ++ ++ #compare tables ++ diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" ++ ++ rm -f /tmp/image.bs /tmp/partmap.bootdisk /tmp/partmap.image ++ ++ if [ -n "$diff" ]; then ++ echo "Partition layout has changed. Full image will be written." ++ ask_bool 0 "Abort" && exit 1 ++ return 0 ++ fi + } + + platform_copy_config() { +@@ -13,55 +36,54 @@ platform_copy_config() { + } + + platform_do_upgrade() { +- local diskdev partdev ibs diff +- +- if export_bootdevice && export_partdevice diskdev -2; then +- sync +- if [ "$SAVE_PARTITIONS" = "1" ]; then +- get_partitions "/dev/$diskdev" bootdisk +- +- #get block size +- if [ -f "/sys/block/$diskdev/queue/physical_block_size" ]; then +- ibs="$(cat "/sys/block/$diskdev/queue/physical_block_size")" +- else +- ibs=512 +- fi +- +- #extract the boot sector from the image +- get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b +- +- get_partitions /tmp/image.bs image +- +- #compare tables +- diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" +- if [ -n "$diff" ]; then +- echo "Partition layout is changed. Full image will be written." +- ask_bool 0 "Abort" && exit +- +- get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync +- return 0 +- fi +- +- #write uboot image +- get_image "$@" | dd of="$diskdev" bs=1024 skip=8 seek=8 count=1016 conv=fsync +- #iterate over each partition from the image and write it to the boot disk +- while read part start size; do +- part="$(($part - 2))" +- if export_partdevice partdev $part; then +- echo "Writing image to /dev/$partdev..." +- get_image "$@" | dd of="/dev/$partdev" ibs="$ibs" obs=1M skip="$start" count="$size" conv=fsync +- else +- echo "Unable to find partition $part device, skipped." +- fi +- done < /tmp/partmap.image +- +- #copy partition uuid +- echo "Writing new UUID to /dev/$diskdev..." +- get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync ++ local diskdev partdev diff ++ ++ export_bootdevice && export_partdevice diskdev -2 || { ++ echo "Unable to determine upgrade device" ++ return 1 ++ } ++ ++ sync ++ ++ if [ "$SAVE_PARTITIONS" = "1" ]; then ++ get_partitions "/dev/$diskdev" bootdisk ++ ++ #extract the boot sector from the image ++ get_image "$@" | dd of=/tmp/image.bs count=1 bs=512b ++ ++ get_partitions /tmp/image.bs image ++ ++ #compare tables ++ diff="$(grep -F -x -v -f /tmp/partmap.bootdisk /tmp/partmap.image)" ++ else ++ diff=1 ++ fi ++ ++ if [ -n "$diff" ]; then ++ get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync ++ ++ # Separate removal and addtion is necessary; otherwise, partition 1 ++ # will be missing if it overlaps with the old partition 2 ++ partx -d - "/dev/$diskdev" ++ partx -a - "/dev/$diskdev" ++ ++ return 0 ++ fi ++ ++ #write uboot image ++ get_image "$@" | dd of="$diskdev" bs=1024 skip=8 seek=8 count=1016 conv=fsync ++ #iterate over each partition from the image and write it to the boot disk ++ while read part start size; do ++ part="$(($part - 2))" ++ if export_partdevice partdev $part; then ++ echo "Writing image to /dev/$partdev..." ++ get_image "$@" | dd of="/dev/$partdev" ibs="512" obs=1M skip="$start" count="$size" conv=fsync + else +- get_image "$@" | dd of="/dev/$diskdev" bs=4096 conv=fsync ++ echo "Unable to find partition $part device, skipped." + fi ++ done < /tmp/partmap.image + +- sleep 1 +- fi ++ #copy partition uuid ++ echo "Writing new UUID to /dev/$diskdev..." ++ get_image "$@" | dd of="/dev/$diskdev" bs=1 skip=440 count=4 seek=440 conv=fsync + } diff --git a/patches/lede/0026-mvebu-fix-sysupgrade.patch b/patches/lede/0026-mvebu-fix-sysupgrade.patch new file mode 100644 index 00000000..bf29f526 --- /dev/null +++ b/patches/lede/0026-mvebu-fix-sysupgrade.patch @@ -0,0 +1,85 @@ +From: Matthias Schiffer +Date: Thu, 1 Jun 2017 18:39:12 +0200 +Subject: mvebu: fix sysupgrade + +mvebu was modifying RAMFS_COPY_BIN and RAMFS_COPY_DATA from a +sysupgrade_pre_upgrade hook. As the ramfs is created from stage2, this +did not have an effect anymore after the staged sysupgrade changes. + +As it doesn't really hurt to copy fw_printenv and fw_setenv +unconditionally, simply add them in /lib/upgrade/platform.sh, so stage2 +will see them. + +Config copying is moved to a function called by platform_copy_config, where +it belongs. + +Signed-off-by: Matthias Schiffer +Fixes: FS#821 +Fixes: 30f61a34b4cf "base-files: always use staged sysupgrade" + +diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 +index cc8047d988e39ca9ba27d2588744aad469d1d978..bdbb8926643287f48a4ae62c5d1d4b4a29130859 100755 +--- a/package/base-files/files/lib/upgrade/stage2 ++++ b/package/base-files/files/lib/upgrade/stage2 +@@ -48,7 +48,7 @@ switch_to_ramfs() { + /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc \ + /bin/cut /usr/bin/printf /bin/sync /bin/mkdir /bin/rmdir \ + /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \ +- /bin/mknod ++ /bin/mknod /bin/touch + + install_bin /sbin/mtd + install_bin /sbin/mount_root +diff --git a/target/linux/mvebu/base-files/lib/upgrade/linksys.sh b/target/linux/mvebu/base-files/lib/upgrade/linksys.sh +index d06a1b8ed0534364b595618f24b65f9f3a3e275d..63d1cd14a4deed407b217a518ae25a752f62969e 100644 +--- a/target/linux/mvebu/base-files/lib/upgrade/linksys.sh ++++ b/target/linux/mvebu/base-files/lib/upgrade/linksys.sh +@@ -73,21 +73,7 @@ platform_do_upgrade_linksys() { + } + } + +-linksys_preupgrade() { +- local board=$(mvebu_board_name) +- +- case "$board" in +- armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-shelby|armada-xp-linksys-mamba|armada-385-linksys-rango) +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /usr/sbin/fw_printenv /usr/sbin/fw_setenv" +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /bin/mkdir /bin/touch" +- export RAMFS_COPY_DATA="${RAMFS_COPY_DATA} /etc/fw_env.config /var/lock/fw_printenv.lock" +- +- [ -f /tmp/sysupgrade.tgz ] && { +- cp /tmp/sysupgrade.tgz /tmp/syscfg/sysupgrade.tgz +- } +- ;; +- esac ++platform_copy_config_linksys() { ++ cp -f /tmp/sysupgrade.tgz /tmp/syscfg/sysupgrade.tgz ++ sync + } +- +-append sysupgrade_pre_upgrade linksys_preupgrade +- +diff --git a/target/linux/mvebu/base-files/lib/upgrade/platform.sh b/target/linux/mvebu/base-files/lib/upgrade/platform.sh +index 77578e28d42fb7ca5e3f057e42ac5818e851736f..55c084483995d548556a560e171462f2d5456172 100755 +--- a/target/linux/mvebu/base-files/lib/upgrade/platform.sh ++++ b/target/linux/mvebu/base-files/lib/upgrade/platform.sh +@@ -5,7 +5,8 @@ + + . /lib/mvebu.sh + +-RAMFS_COPY_DATA=/lib/mvebu.sh ++RAMFS_COPY_BIN='/usr/sbin/fw_printenv /usr/sbin/fw_setenv' ++RAMFS_COPY_DATA='/lib/mvebu.sh /etc/fw_env.config /var/lock/fw_printenv.lock' + REQUIRE_IMAGE_METADATA=1 + + platform_check_image() { +@@ -31,6 +32,9 @@ platform_copy_config() { + local board=$(mvebu_board_name) + + case "$board" in ++ armada-385-linksys-caiman|armada-385-linksys-cobra|armada-385-linksys-rango|armada-385-linksys-shelby|armada-xp-linksys-mamba) ++ platform_copy_config_linksys ++ ;; + armada-388-clearfog) + platform_copy_config_clearfog "$ARGV" + ;; diff --git a/patches/openwrt/0031-kernel-mtd-spi-nor-wait-until-status-register-writes-are-ready.patch b/patches/lede/0027-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch similarity index 58% rename from patches/openwrt/0031-kernel-mtd-spi-nor-wait-until-status-register-writes-are-ready.patch rename to patches/lede/0027-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch index f90f9c61..55193310 100644 --- a/patches/openwrt/0031-kernel-mtd-spi-nor-wait-until-status-register-writes-are-ready.patch +++ b/patches/lede/0027-generic-mtd-backport-unlock-support-and-asserted-fixes-for-certain-Winbond-Spansion-flash-chips.patch @@ -1,12 +1,12 @@ From: Matthias Schiffer -Date: Sat, 7 May 2016 00:17:55 +0200 -Subject: kernel: mtd: spi-nor: wait until status register writes are ready +Date: Tue, 20 Jun 2017 11:01:27 +0200 +Subject: generic: mtd: backport unlock support and asserted fixes for certain Winbond/Spansion flash chips -diff --git a/target/linux/generic/patches-3.18/094-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch b/target/linux/generic/patches-3.18/094-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch +diff --git a/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch b/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch new file mode 100644 -index 0000000..2c2e5f3 +index 0000000000000000000000000000000000000000..c8aafe2ebbf7368f47e8f4d7a24dd5e45583a136 --- /dev/null -+++ b/target/linux/generic/patches-3.18/094-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch ++++ b/target/linux/generic/patches-4.4/049-0001-mtd-spi-nor-wait-until-lock-unlock-operations-are-re.patch @@ -0,0 +1,66 @@ +From 32321e950d8a237d7e8f3a9b76220007dfa87544 Mon Sep 17 00:00:00 2001 +Message-Id: <32321e950d8a237d7e8f3a9b76220007dfa87544.1462572686.git.mschiffer@universe-factory.net> @@ -34,7 +34,7 @@ index 0000000..2c2e5f3 + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c -+@@ -462,6 +462,7 @@ static int stm_lock(struct spi_nor *nor, ++@@ -463,6 +463,7 @@ static int stm_lock(struct spi_nor *nor, + u8 status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; @@ -42,7 +42,7 @@ index 0000000..2c2e5f3 + + status_old = read_sr(nor); + -+@@ -498,7 +499,10 @@ static int stm_lock(struct spi_nor *nor, ++@@ -499,7 +500,10 @@ static int stm_lock(struct spi_nor *nor, + return -EINVAL; + + write_enable(nor); @@ -54,7 +54,7 @@ index 0000000..2c2e5f3 + } + + /* -+@@ -512,6 +516,7 @@ static int stm_unlock(struct spi_nor *no ++@@ -513,6 +517,7 @@ static int stm_unlock(struct spi_nor *no + uint8_t status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; @@ -62,7 +62,7 @@ index 0000000..2c2e5f3 + + status_old = read_sr(nor); + -+@@ -546,7 +551,10 @@ static int stm_unlock(struct spi_nor *no ++@@ -547,7 +552,10 @@ static int stm_unlock(struct spi_nor *no + return -EINVAL; + + write_enable(nor); @@ -74,11 +74,11 @@ index 0000000..2c2e5f3 + } + + /* -diff --git a/target/linux/generic/patches-3.18/094-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch b/target/linux/generic/patches-3.18/094-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch +diff --git a/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch b/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch new file mode 100644 -index 0000000..a0573d5 +index 0000000000000000000000000000000000000000..0541c95594ec14f62b5db787f4d52d5a42777cdc --- /dev/null -+++ b/target/linux/generic/patches-3.18/094-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch ++++ b/target/linux/generic/patches-4.4/049-0002-mtd-spi-nor-wait-for-SR_WIP-to-clear-on-initial-unlo.patch @@ -0,0 +1,33 @@ +From edf891ef9ab773363f8e58022a26d7d31604aed6 Mon Sep 17 00:00:00 2001 +Message-Id: @@ -105,11 +105,35 @@ index 0000000..a0573d5 + +--- a/drivers/mtd/spi-nor/spi-nor.c ++++ b/drivers/mtd/spi-nor/spi-nor.c -+@@ -1167,6 +1167,7 @@ int spi_nor_scan(struct spi_nor *nor, co -+ JEDEC_MFR(info) == SNOR_MFR_SST) { ++@@ -1169,6 +1169,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ info->flags & SPI_NOR_HAS_LOCK) { + write_enable(nor); + write_sr(nor, 0); ++ spi_nor_wait_till_ready(nor); + } + + if (!mtd->name) +diff --git a/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..7c6530a5e0e8bc144e1d4497428e3c3691c2ef22 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/466-revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch +@@ -0,0 +1,18 @@ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1161,6 +1161,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ JEDEC_MFR(info) == SNOR_MFR_INTEL || ++ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || ++ JEDEC_MFR(info) == SNOR_MFR_SST || +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ write_enable(nor); ++ write_sr(nor, 0); ++@@ -1178,6 +1179,7 @@ int spi_nor_scan(struct spi_nor *nor, co ++ ++ /* NOR protection support for STmicro/Micron chips and similar */ ++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || +++ JEDEC_MFR(info) == SNOR_MFR_WINBOND || ++ info->flags & SPI_NOR_HAS_LOCK) { ++ nor->flash_lock = stm_lock; ++ nor->flash_unlock = stm_unlock; diff --git a/patches/lede/0028-generic-vxlan-backport-support-for-VXLAN-over-link-local-IPv6.patch b/patches/lede/0028-generic-vxlan-backport-support-for-VXLAN-over-link-local-IPv6.patch new file mode 100644 index 00000000..43bbf105 --- /dev/null +++ b/patches/lede/0028-generic-vxlan-backport-support-for-VXLAN-over-link-local-IPv6.patch @@ -0,0 +1,436 @@ +From: Matthias Schiffer +Date: Wed, 21 Jun 2017 00:54:57 +0200 +Subject: generic: vxlan: backport support for VXLAN over link-local IPv6 + +diff --git a/target/linux/generic/patches-4.4/075-0001-vxlan-improve-validation-of-address-family-configura.patch b/target/linux/generic/patches-4.4/075-0001-vxlan-improve-validation-of-address-family-configura.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..439eb5d0f769f1cde23ff4deacc80728e82605f2 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/075-0001-vxlan-improve-validation-of-address-family-configura.patch +@@ -0,0 +1,68 @@ ++From 434a1bb54b24b538f81d7945128b7ca25976d19b Mon Sep 17 00:00:00 2001 ++Message-Id: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Mon, 19 Jun 2017 10:03:57 +0200 ++Subject: [PATCH 1/4] vxlan: improve validation of address family configuration ++ ++Address families of source and destination addresses must match, and ++changelink operations can't change the address family. ++ ++In addition, always use the VXLAN_F_IPV6 to check if a VXLAN device uses ++IPv4 or IPv6. ++ ++Signed-off-by: Matthias Schiffer ++Signed-off-by: David S. Miller ++[Matthias Schiffer: rebase to v4.4.y] ++--- ++ drivers/net/vxlan.c | 23 +++++++++++++++-------- ++ 1 file changed, 15 insertions(+), 8 deletions(-) ++ ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -2784,12 +2784,20 @@ static int vxlan_dev_configure(struct ne ++ ++ memcpy(&dst->remote_ip, &conf->remote_ip, sizeof(conf->remote_ip)); ++ ++- /* Unless IPv6 is explicitly requested, assume IPv4 */ ++- if (!dst->remote_ip.sa.sa_family) +++ if (!dst->remote_ip.sa.sa_family && !conf->saddr.sa.sa_family) { +++ /* Unless IPv6 is explicitly requested, assume IPv4 */ ++ dst->remote_ip.sa.sa_family = AF_INET; +++ conf->saddr.sa.sa_family = AF_INET; +++ } else if (!dst->remote_ip.sa.sa_family) { +++ dst->remote_ip.sa.sa_family = conf->saddr.sa.sa_family; +++ } else if (!conf->saddr.sa.sa_family) { +++ conf->saddr.sa.sa_family = dst->remote_ip.sa.sa_family; +++ } +++ +++ if (conf->saddr.sa.sa_family != dst->remote_ip.sa.sa_family) +++ return -EINVAL; ++ ++- if (dst->remote_ip.sa.sa_family == AF_INET6 || ++- vxlan->cfg.saddr.sa.sa_family == AF_INET6) { +++ if (conf->saddr.sa.sa_family == AF_INET6) { ++ if (!IS_ENABLED(CONFIG_IPV6)) ++ return -EPFNOSUPPORT; ++ use_ipv6 = true; ++@@ -2843,11 +2851,9 @@ static int vxlan_dev_configure(struct ne ++ ++ list_for_each_entry(tmp, &vn->vxlan_list, next) { ++ if (tmp->cfg.vni == conf->vni && ++- (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 || ++- tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 && ++ tmp->cfg.dst_port == vxlan->cfg.dst_port && ++- (tmp->flags & VXLAN_F_RCV_FLAGS) == ++- (vxlan->flags & VXLAN_F_RCV_FLAGS)) +++ (tmp->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) == +++ (vxlan->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6))) ++ return -EEXIST; ++ } ++ ++@@ -2915,6 +2921,7 @@ static int vxlan_newlink(struct net *src ++ ++ if (data[IFLA_VXLAN_GROUP]) { ++ conf.remote_ip.sin.sin_addr.s_addr = nla_get_in_addr(data[IFLA_VXLAN_GROUP]); +++ conf.remote_ip.sa.sa_family = AF_INET; ++ } else if (data[IFLA_VXLAN_GROUP6]) { ++ if (!IS_ENABLED(CONFIG_IPV6)) ++ return -EPFNOSUPPORT; +diff --git a/target/linux/generic/patches-4.4/075-0002-vxlan-check-valid-combinations-of-address-scopes.patch b/target/linux/generic/patches-4.4/075-0002-vxlan-check-valid-combinations-of-address-scopes.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..abf9b8a0eae88aa5a64be5cc82a6827d4d562c55 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/075-0002-vxlan-check-valid-combinations-of-address-scopes.patch +@@ -0,0 +1,84 @@ ++From 8956b9db43347a51e88dddc3c08fb88ff60dea54 Mon Sep 17 00:00:00 2001 ++Message-Id: <8956b9db43347a51e88dddc3c08fb88ff60dea54.1498005061.git.mschiffer@universe-factory.net> ++In-Reply-To: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++References: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Mon, 19 Jun 2017 10:03:58 +0200 ++Subject: [PATCH 2/4] vxlan: check valid combinations of address scopes ++ ++* Multicast addresses are never valid as local address ++* Link-local IPv6 unicast addresses may only be used as remote when the ++ local address is link-local as well ++* Don't allow link-local IPv6 local/remote addresses without interface ++ ++We also store in the flags field if link-local addresses are used for the ++follow-up patches that actually make VXLAN over link-local IPv6 work. ++ ++Signed-off-by: Matthias Schiffer ++Signed-off-by: David S. Miller ++[Matthias Schiffer: rebase to v4.4.y] ++--- ++ drivers/net/vxlan.c | 29 +++++++++++++++++++++++++++++ ++ include/net/vxlan.h | 1 + ++ 2 files changed, 30 insertions(+) ++ ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -2797,11 +2797,35 @@ static int vxlan_dev_configure(struct ne ++ if (conf->saddr.sa.sa_family != dst->remote_ip.sa.sa_family) ++ return -EINVAL; ++ +++ if (vxlan_addr_multicast(&conf->saddr)) +++ return -EINVAL; +++ ++ if (conf->saddr.sa.sa_family == AF_INET6) { ++ if (!IS_ENABLED(CONFIG_IPV6)) ++ return -EPFNOSUPPORT; ++ use_ipv6 = true; ++ vxlan->flags |= VXLAN_F_IPV6; +++ +++ if (!(conf->flags & VXLAN_F_COLLECT_METADATA)) { +++ int local_type = +++ ipv6_addr_type(&conf->saddr.sin6.sin6_addr); +++ int remote_type = +++ ipv6_addr_type(&dst->remote_ip.sin6.sin6_addr); +++ +++ if (local_type & IPV6_ADDR_LINKLOCAL) { +++ if (!(remote_type & IPV6_ADDR_LINKLOCAL) && +++ (remote_type != IPV6_ADDR_ANY)) +++ return -EINVAL; +++ +++ vxlan->flags |= VXLAN_F_IPV6_LINKLOCAL; +++ } else { +++ if (remote_type == +++ (IPV6_ADDR_UNICAST | IPV6_ADDR_LINKLOCAL)) +++ return -EINVAL; +++ +++ vxlan->flags &= ~VXLAN_F_IPV6_LINKLOCAL; +++ } +++ } ++ } ++ ++ if (conf->remote_ifindex) { ++@@ -2827,6 +2851,11 @@ static int vxlan_dev_configure(struct ne ++ dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); ++ ++ needed_headroom = lowerdev->hard_header_len; +++ } else { +++#if IS_ENABLED(CONFIG_IPV6) +++ if (vxlan->flags & VXLAN_F_IPV6_LINKLOCAL) +++ return -EINVAL; +++#endif ++ } ++ ++ if (conf->mtu) { ++--- a/include/net/vxlan.h +++++ b/include/net/vxlan.h ++@@ -185,6 +185,7 @@ struct vxlan_dev { ++ #define VXLAN_F_GBP 0x800 ++ #define VXLAN_F_REMCSUM_NOPARTIAL 0x1000 ++ #define VXLAN_F_COLLECT_METADATA 0x2000 +++#define VXLAN_F_IPV6_LINKLOCAL 0x8000 ++ ++ /* Flags that are used in the receive path. These flags must match in ++ * order for a socket to be shareable +diff --git a/target/linux/generic/patches-4.4/075-0003-vxlan-fix-snooping-for-link-local-IPv6-addresses.patch b/target/linux/generic/patches-4.4/075-0003-vxlan-fix-snooping-for-link-local-IPv6-addresses.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..5ebbce6e0682fff11b0d86c8df781a5c2fab5125 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/075-0003-vxlan-fix-snooping-for-link-local-IPv6-addresses.patch +@@ -0,0 +1,88 @@ ++From e3bdb4bc6c4020e90c1bbafd91645ff3ae8966b9 Mon Sep 17 00:00:00 2001 ++Message-Id: ++In-Reply-To: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++References: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Mon, 19 Jun 2017 10:03:59 +0200 ++Subject: [PATCH 3/4] vxlan: fix snooping for link-local IPv6 addresses ++ ++If VXLAN is run over link-local IPv6 addresses, it is necessary to store ++the ifindex in the FDB entries. Otherwise, the used interface is undefined ++and unicast communication will most likely fail. ++ ++Support for link-local IPv4 addresses should be possible as well, but as ++the semantics aren't as well defined as for IPv6, and there doesn't seem to ++be much interest in having the support, it's not implemented for now. ++ ++Signed-off-by: Matthias Schiffer ++Signed-off-by: David S. Miller ++[Matthias Schiffer: rebase to v4.4.y] ++--- ++ drivers/net/vxlan.c | 20 +++++++++++++++----- ++ 1 file changed, 15 insertions(+), 5 deletions(-) ++ ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -947,16 +947,25 @@ out: ++ * Return true if packet is bogus and should be dropped. ++ */ ++ static bool vxlan_snoop(struct net_device *dev, ++- union vxlan_addr *src_ip, const u8 *src_mac) +++ union vxlan_addr *src_ip, const u8 *src_mac, +++ u32 src_ifindex) ++ { ++ struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_fdb *f; +++ u32 ifindex = 0; +++ +++#if IS_ENABLED(CONFIG_IPV6) +++ if (src_ip->sa.sa_family == AF_INET6 && +++ (ipv6_addr_type(&src_ip->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)) +++ ifindex = src_ifindex; +++#endif ++ ++ f = vxlan_find_mac(vxlan, src_mac); ++ if (likely(f)) { ++ struct vxlan_rdst *rdst = first_remote_rcu(f); ++ ++- if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip))) +++ if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) && +++ rdst->remote_ifindex == ifindex)) ++ return false; ++ ++ /* Don't migrate static entries, drop packets */ ++@@ -982,7 +991,7 @@ static bool vxlan_snoop(struct net_devic ++ NLM_F_EXCL|NLM_F_CREATE, ++ vxlan->cfg.dst_port, ++ vxlan->default_dst.remote_vni, ++- 0, NTF_SELF); +++ ifindex, NTF_SELF); ++ spin_unlock(&vxlan->hash_lock); ++ } ++ ++@@ -1157,6 +1166,7 @@ static void vxlan_rcv(struct vxlan_sock ++ struct vxlan_dev *vxlan; ++ struct pcpu_sw_netstats *stats; ++ union vxlan_addr saddr; +++ u32 ifindex = skb->dev->ifindex; ++ int err = 0; ++ ++ /* For flow based devices, map all packets to VNI 0 */ ++@@ -1196,7 +1206,7 @@ static void vxlan_rcv(struct vxlan_sock ++ } ++ ++ if ((vxlan->flags & VXLAN_F_LEARN) && ++- vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source)) +++ vxlan_snoop(skb->dev, &saddr, eth_hdr(skb)->h_source, ifindex)) ++ goto drop; ++ ++ skb_reset_network_header(skb); ++@@ -1898,7 +1908,7 @@ static void vxlan_encap_bypass(struct sk ++ } ++ ++ if (dst_vxlan->flags & VXLAN_F_LEARN) ++- vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source); +++ vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0); ++ ++ u64_stats_update_begin(&tx_stats->syncp); ++ tx_stats->tx_packets++; +diff --git a/target/linux/generic/patches-4.4/075-0004-vxlan-allow-multiple-VXLANs-with-same-VNI-for-IPv6-l.patch b/target/linux/generic/patches-4.4/075-0004-vxlan-allow-multiple-VXLANs-with-same-VNI-for-IPv6-l.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..c184c32385e6c802f1bed7647ce720f0e429f4a5 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/075-0004-vxlan-allow-multiple-VXLANs-with-same-VNI-for-IPv6-l.patch +@@ -0,0 +1,168 @@ ++From 7a1fa05f8d460e2a81cb724f441f7346f950680a Mon Sep 17 00:00:00 2001 ++Message-Id: <7a1fa05f8d460e2a81cb724f441f7346f950680a.1498005061.git.mschiffer@universe-factory.net> ++In-Reply-To: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++References: <434a1bb54b24b538f81d7945128b7ca25976d19b.1498005061.git.mschiffer@universe-factory.net> ++From: Matthias Schiffer ++Date: Mon, 19 Jun 2017 10:04:00 +0200 ++Subject: [PATCH 4/4] vxlan: allow multiple VXLANs with same VNI for IPv6 ++ link-local addresses ++ ++As link-local addresses are only valid for a single interface, we can allow ++to use the same VNI for multiple independent VXLANs, as long as the used ++interfaces are distinct. This way, VXLANs can always be used as a drop-in ++replacement for VLANs with greater ID space. ++ ++This also extends VNI lookup to respect the ifindex when link-local IPv6 ++addresses are used, so using the same VNI on multiple interfaces can ++actually work. ++ ++Signed-off-by: Matthias Schiffer ++Signed-off-by: David S. Miller ++[Matthias Schiffer: rebase to v4.4.y] ++--- ++ drivers/net/vxlan.c | 53 +++++++++++++++++++++++++++++++++++++---------------- ++ 1 file changed, 37 insertions(+), 16 deletions(-) ++ ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -242,22 +242,33 @@ static struct vxlan_sock *vxlan_find_soc ++ return NULL; ++ } ++ ++-static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, u32 id) +++static struct vxlan_dev *vxlan_vs_find_vni(struct vxlan_sock *vs, int ifindex, +++ u32 id) ++ { ++ struct vxlan_dev *vxlan; ++ ++ hlist_for_each_entry_rcu(vxlan, vni_head(vs, id), hlist) { ++- if (vxlan->default_dst.remote_vni == id) ++- return vxlan; +++ if (vxlan->default_dst.remote_vni != id) +++ continue; +++ +++ if (IS_ENABLED(CONFIG_IPV6)) { +++ const struct vxlan_config *cfg = &vxlan->cfg; +++ +++ if ((vxlan->flags & VXLAN_F_IPV6_LINKLOCAL) && +++ cfg->remote_ifindex != ifindex) +++ continue; +++ } +++ +++ return vxlan; ++ } ++ ++ return NULL; ++ } ++ ++ /* Look up VNI in a per net namespace table */ ++-static struct vxlan_dev *vxlan_find_vni(struct net *net, u32 id, ++- sa_family_t family, __be16 port, ++- u32 flags) +++static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex, +++ u32 id, sa_family_t family, +++ __be16 port, u32 flags) ++ { ++ struct vxlan_sock *vs; ++ ++@@ -265,7 +276,7 @@ static struct vxlan_dev *vxlan_find_vni( ++ if (!vs) ++ return NULL; ++ ++- return vxlan_vs_find_vni(vs, id); +++ return vxlan_vs_find_vni(vs, ifindex, id); ++ } ++ ++ /* Fill in neighbour message in skbuff. */ ++@@ -1174,7 +1185,7 @@ static void vxlan_rcv(struct vxlan_sock ++ vni = 0; ++ ++ /* Is this VNI defined? */ ++- vxlan = vxlan_vs_find_vni(vs, vni); +++ vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni); ++ if (!vxlan) ++ goto drop; ++ ++@@ -1942,6 +1953,7 @@ static void vxlan_xmit_one(struct sk_buf ++ u32 vni; ++ __be16 df = 0; ++ __u8 tos, ttl; +++ int ifindex; ++ int err; ++ u32 flags = vxlan->flags; ++ ++@@ -1950,6 +1962,7 @@ static void vxlan_xmit_one(struct sk_buf ++ if (rdst) { ++ dst_port = rdst->remote_port ? rdst->remote_port : vxlan->cfg.dst_port; ++ vni = rdst->remote_vni; +++ ifindex = rdst->remote_ifindex; ++ dst = &rdst->remote_ip; ++ } else { ++ if (!info) { ++@@ -1959,6 +1972,7 @@ static void vxlan_xmit_one(struct sk_buf ++ } ++ dst_port = info->key.tp_dst ? : vxlan->cfg.dst_port; ++ vni = be64_to_cpu(info->key.tun_id); +++ ifindex = 0; ++ remote_ip.sa.sa_family = ip_tunnel_info_af(info); ++ if (remote_ip.sa.sa_family == AF_INET) ++ remote_ip.sin.sin_addr.s_addr = info->key.u.ipv4.dst; ++@@ -2015,7 +2029,7 @@ static void vxlan_xmit_one(struct sk_buf ++ } ++ ++ memset(&fl4, 0, sizeof(fl4)); ++- fl4.flowi4_oif = rdst ? rdst->remote_ifindex : 0; +++ fl4.flowi4_oif = ifindex; ++ fl4.flowi4_tos = RT_TOS(tos); ++ fl4.flowi4_mark = skb->mark; ++ fl4.flowi4_proto = IPPROTO_UDP; ++@@ -2043,7 +2057,7 @@ static void vxlan_xmit_one(struct sk_buf ++ struct vxlan_dev *dst_vxlan; ++ ++ ip_rt_put(rt); ++- dst_vxlan = vxlan_find_vni(vxlan->net, vni, +++ dst_vxlan = vxlan_find_vni(vxlan->net, ifindex, vni, ++ dst->sa.sa_family, dst_port, ++ vxlan->flags); ++ if (!dst_vxlan) ++@@ -2076,8 +2090,7 @@ static void vxlan_xmit_one(struct sk_buf ++ goto drop; ++ sk = vxlan->vn6_sock->sock->sk; ++ ++- ndst = vxlan6_get_route(vxlan, skb, ++- rdst ? rdst->remote_ifindex : 0, +++ ndst = vxlan6_get_route(vxlan, skb, ifindex, ++ &dst->sin6.sin6_addr, &saddr); ++ if (IS_ERR(ndst)) { ++ netdev_dbg(dev, "no route to %pI6\n", ++@@ -2101,7 +2114,7 @@ static void vxlan_xmit_one(struct sk_buf ++ struct vxlan_dev *dst_vxlan; ++ ++ dst_release(ndst); ++- dst_vxlan = vxlan_find_vni(vxlan->net, vni, +++ dst_vxlan = vxlan_find_vni(vxlan->net, ifindex, vni, ++ dst->sa.sa_family, dst_port, ++ vxlan->flags); ++ if (!dst_vxlan) ++@@ -2889,10 +2902,18 @@ static int vxlan_dev_configure(struct ne ++ vxlan->cfg.age_interval = FDB_AGE_DEFAULT; ++ ++ list_for_each_entry(tmp, &vn->vxlan_list, next) { ++- if (tmp->cfg.vni == conf->vni && ++- tmp->cfg.dst_port == vxlan->cfg.dst_port && ++- (tmp->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) == +++ if (tmp->cfg.vni != conf->vni) +++ continue; +++ if (tmp->cfg.dst_port != vxlan->cfg.dst_port) +++ continue; +++ if ((tmp->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6)) != ++ (vxlan->flags & (VXLAN_F_RCV_FLAGS | VXLAN_F_IPV6))) +++ continue; +++ +++ if ((vxlan->flags & VXLAN_F_IPV6_LINKLOCAL) && +++ tmp->cfg.remote_ifindex != vxlan->cfg.remote_ifindex) +++ continue; +++ ++ return -EEXIST; ++ } ++ diff --git a/patches/lede/0029-vxlan-add-new-package-for-netifd-VXLAN-proto.patch b/patches/lede/0029-vxlan-add-new-package-for-netifd-VXLAN-proto.patch new file mode 100644 index 00000000..446e6af1 --- /dev/null +++ b/patches/lede/0029-vxlan-add-new-package-for-netifd-VXLAN-proto.patch @@ -0,0 +1,198 @@ +From: Matthias Schiffer +Date: Fri, 10 Mar 2017 01:23:50 +0100 +Subject: vxlan: add new package for netifd VXLAN proto + +Signed-off-by: Matthias Schiffer + +diff --git a/package/network/config/vxlan/Makefile b/package/network/config/vxlan/Makefile +new file mode 100644 +index 0000000000000000000000000000000000000000..a471d4e90cbe30c1d1dd01dbf7553995d8c0485e +--- /dev/null ++++ b/package/network/config/vxlan/Makefile +@@ -0,0 +1,32 @@ ++include $(TOPDIR)/rules.mk ++ ++PKG_NAME:=vxlan ++PKG_VERSION:=1 ++PKG_LICENSE:=GPL-2.0 ++ ++include $(INCLUDE_DIR)/package.mk ++ ++define Package/vxlan ++ SECTION:=net ++ CATEGORY:=Network ++ MAINTAINER:=Matthias Schiffer ++ TITLE:=Virtual eXtensible LAN config support ++ DEPENDS:=+kmod-vxlan ++endef ++ ++define Package/vxlan/description ++ Virtual eXtensible LAN config support in /etc/config/network. ++endef ++ ++define Build/Compile ++endef ++ ++define Build/Configure ++endef ++ ++define Package/vxlan/install ++ $(INSTALL_DIR) $(1)/lib/netifd/proto ++ $(INSTALL_BIN) ./files/vxlan.sh $(1)/lib/netifd/proto/vxlan.sh ++endef ++ ++$(eval $(call BuildPackage,vxlan)) +diff --git a/package/network/config/vxlan/files/vxlan.sh b/package/network/config/vxlan/files/vxlan.sh +new file mode 100755 +index 0000000000000000000000000000000000000000..27ccd8f12759f69c7c226cac0c923335b8ccc6a8 +--- /dev/null ++++ b/package/network/config/vxlan/files/vxlan.sh +@@ -0,0 +1,148 @@ ++#!/bin/sh ++ ++[ -n "$INCLUDE_ONLY" ] || { ++ . /lib/functions.sh ++ . /lib/functions/network.sh ++ . ../netifd-proto.sh ++ init_proto "$@" ++} ++ ++vxlan_generic_setup() { ++ local cfg="$1" ++ local mode="$2" ++ local local="$3" ++ local remote="$4" ++ ++ local link="$cfg" ++ ++ local port vid ttl tos mtu macaddr zone ++ json_get_vars port vid ttl tos mtu macaddr zone ++ ++ ++ proto_init_update "$link" 1 ++ ++ proto_add_tunnel ++ json_add_string mode "$mode" ++ ++ [ -n "$tunlink" ] && json_add_string link "$tunlink" ++ [ -n "$local" ] && json_add_string local "$local" ++ [ -n "$remote" ] && json_add_string remote "$remote" ++ ++ [ -n "$ttl" ] && json_add_int ttl "$ttl" ++ [ -n "$tos" ] && json_add_string tos "$tos" ++ [ -n "$mtu" ] && json_add_int mtu "$mtu" ++ ++ json_add_object 'data' ++ [ -n "$port" ] && json_add_int port "$port" ++ [ -n "$vid" ] && json_add_int id "$vid" ++ [ -n "$macaddr" ] && json_add_string macaddr "$macaddr" ++ json_close_object ++ ++ proto_close_tunnel ++ ++ proto_add_data ++ [ -n "$zone" ] && json_add_string zone "$zone" ++ proto_close_data ++ ++ proto_send_update "$cfg" ++} ++ ++proto_vxlan_setup() { ++ local cfg="$1" ++ ++ local ipaddr peeraddr ++ json_get_vars ipaddr peeraddr tunlink ++ ++ [ -z "$peeraddr" ] && { ++ proto_notify_error "$cfg" "MISSING_ADDRESS" ++ proto_block_restart "$cfg" ++ exit ++ } ++ ++ ( proto_add_host_dependency "$cfg" '' "$tunlink" ) ++ ++ [ -z "$ipaddr" ] && { ++ local wanif="$tunlink" ++ if [ -z "$wanif" ] && ! network_find_wan wanif; then ++ proto_notify_error "$cfg" "NO_WAN_LINK" ++ exit ++ fi ++ ++ if ! network_get_ipaddr ipaddr "$wanif"; then ++ proto_notify_error "$cfg" "NO_WAN_LINK" ++ exit ++ fi ++ } ++ ++ vxlan_generic_setup "$cfg" 'vxlan' "$ipaddr" "$peeraddr" ++} ++ ++proto_vxlan6_setup() { ++ local cfg="$1" ++ ++ local ip6addr peer6addr ++ json_get_vars ip6addr peer6addr tunlink ++ ++ [ -z "$peer6addr" ] && { ++ proto_notify_error "$cfg" "MISSING_ADDRESS" ++ proto_block_restart "$cfg" ++ exit ++ } ++ ++ ( proto_add_host_dependency "$cfg" '' "$tunlink" ) ++ ++ [ -z "$ip6addr" ] && { ++ local wanif="$tunlink" ++ if [ -z "$wanif" ] && ! network_find_wan6 wanif; then ++ proto_notify_error "$cfg" "NO_WAN_LINK" ++ exit ++ fi ++ ++ if ! network_get_ipaddr6 ip6addr "$wanif"; then ++ proto_notify_error "$cfg" "NO_WAN_LINK" ++ exit ++ fi ++ } ++ ++ vxlan_generic_setup "$cfg" 'vxlan6' "$ip6addr" "$peer6addr" ++} ++ ++proto_vxlan_teardown() { ++ local cfg="$1" ++} ++ ++proto_vxlan6_teardown() { ++ local cfg="$1" ++} ++ ++vxlan_generic_init_config() { ++ no_device=1 ++ available=1 ++ ++ proto_config_add_string "tunlink" ++ proto_config_add_string "zone" ++ ++ proto_config_add_int "vid" ++ proto_config_add_int "port" ++ proto_config_add_int "ttl" ++ proto_config_add_int "tos" ++ proto_config_add_int "mtu" ++ proto_config_add_string "macaddr" ++} ++ ++proto_vxlan_init_config() { ++ vxlan_generic_init_config ++ proto_config_add_string "ipaddr" ++ proto_config_add_string "peeraddr" ++} ++ ++proto_vxlan6_init_config() { ++ vxlan_generic_init_config ++ proto_config_add_string "ip6addr" ++ proto_config_add_string "peer6addr" ++} ++ ++[ -n "$INCLUDE_ONLY" ] || { ++ add_protocol vxlan ++ add_protocol vxlan6 ++} diff --git a/patches/lede/0030-Revert-scripts-package-metadata.pl-inhibit-compile-deps-on-missing-build-types.patch b/patches/lede/0030-Revert-scripts-package-metadata.pl-inhibit-compile-deps-on-missing-build-types.patch new file mode 100644 index 00000000..655765af --- /dev/null +++ b/patches/lede/0030-Revert-scripts-package-metadata.pl-inhibit-compile-deps-on-missing-build-types.patch @@ -0,0 +1,88 @@ +From: Matthias Schiffer +Date: Tue, 9 Jan 2018 16:31:07 +0100 +Subject: Revert "scripts/package-metadata.pl: inhibit compile deps on missing build types" + +This reverts commit b616aa6db7a9952c182ab49d7942fb67c09803d5. The change +conflicts with our PROVIDES fix and is not strictly necessary for Gluon. + +diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl +index c49d132912828531c7125787f4f53d7130323123..2da32c770ef3333bfcc18922ede556f9734510c7 100755 +--- a/scripts/package-metadata.pl ++++ b/scripts/package-metadata.pl +@@ -460,27 +460,20 @@ sub gen_package_mk() { + next unless $pkg->{"builddepends/$type"}; + foreach my $dep (@{$pkg->{"builddepends/$type"}}) { + my $suffix = ""; +- my $deptype = ""; + my $condition; + + if ($dep =~ /^(.+):(.+)/) { + $condition = $1; + $dep = $2; + } +- if ($dep =~ /^(.+)\/(.+)/) { ++ if ($dep =~ /^(.+)(\/.+)/) { + $dep = $1; +- $deptype = $2; +- $suffix = "/$2"; ++ $suffix = $2; + } + + my $idx = ""; + my $pkg_dep = $package{$dep}; + if (defined($pkg_dep) && defined($pkg_dep->{src})) { +- unless (!$deptype || grep { $_ eq $deptype } @{$pkg_dep->{buildtypes}}) { +- warn sprintf "WARNING: Makefile '%s' has a %s build dependency on '%s/%s' but '%s' does not implement a '%s' build type\n", +- $pkg->{makefile}, $type, $pkg_dep->{src}, $deptype, $pkg_dep->{makefile}, $deptype; +- next; +- } + $idx = $pkg_dep->{subdir}.$pkg_dep->{src}; + } elsif (defined($srcpackage{$dep})) { + $idx = $subdir{$dep}.$dep; +@@ -506,16 +499,14 @@ sub gen_package_mk() { + my $condition; + my $prefix = ""; + my $suffix = ""; +- my $deptype = ""; + + if ($deps =~ /^(.+):(.+)/) { + $condition = $1; + $deps = $2; + } +- if ($deps =~ /^(.+)\/(.+)/) { ++ if ($deps =~ /^(.+)(\/.+)/) { + $deps = $1; +- $deptype = $2; +- $suffix = "/$2"; ++ $suffix = $2; + } + + my $pkg_dep = $package{$deps}; +@@ -530,17 +521,7 @@ sub gen_package_mk() { + foreach my $dep (@deps) { + $pkg_dep = $package{$deps}; + if (defined $pkg_dep->{src}) { +- unless (!$deptype || grep { $_ eq $deptype } @{$pkg_dep->{buildtypes}}) { +- warn sprintf "WARNING: Makefile '%s' has a build dependency on '%s/%s' but '%s' does not implement a '%s' build type\n", +- $pkg->{makefile}, $pkg_dep->{src}, $deptype, $pkg_dep->{makefile}, $deptype; +- next; +- } +- unless ($pkg->{src} ne $pkg_dep->{sec}.$suffix) { +- warn sprintf "WARNING: Makefile '%s' has a build dependency on itself\n", +- $pkg->{makefile}; +- next; +- } +- $idx = $pkg_dep->{subdir}.$pkg_dep->{src}; ++ ($pkg->{src} ne $pkg_dep->{src}.$suffix) and $idx = $pkg_dep->{subdir}.$pkg_dep->{src}; + } elsif (defined($srcpackage{$dep})) { + $idx = $subdir{$dep}.$dep; + } +@@ -592,7 +573,7 @@ ifndef DUMP_TARGET_DB + ( \\ + $cmds \\ + ) > \$@ +- ++ + ifneq (\$(IMAGEOPT)\$(CONFIG_IMAGEOPT),) + package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig + endif diff --git a/patches/lede/0031-scripts-metadata-always-resolve-dependencies-through-provides-list.patch b/patches/lede/0031-scripts-metadata-always-resolve-dependencies-through-provides-list.patch new file mode 100644 index 00000000..cf2c4a3a --- /dev/null +++ b/patches/lede/0031-scripts-metadata-always-resolve-dependencies-through-provides-list.patch @@ -0,0 +1,306 @@ +From: Matthias Schiffer +Date: Sat, 8 Jul 2017 01:35:35 +0200 +Subject: scripts: metadata: always resolve dependencies through provides list + +Instead of adding virtual packages to the normal package list, keep a +separate list for provides, make each package provide itself, and resolve +all dependencies through this list. This allows to use PROVIDES to replace +existing packages. + +A side effect of the changes in the makefile dependency logic is that +build dependencies are now always interpreted as source package names, +instead of putting build and runtime dependencies into the same list. + +Fixes FS#837. + +Signed-off-by: Matthias Schiffer + +diff --git a/scripts/feeds b/scripts/feeds +index 55c294ad0a4ec2f0419d12deddeda7324c349e04..a38eb454585f5dd27b707db23184b7df07ab2658 100755 +--- a/scripts/feeds ++++ b/scripts/feeds +@@ -252,7 +252,6 @@ sub search_feed { + my $substr; + my $pkgmatch = 1; + +- next if $pkg->{vdepends}; + foreach my $substr (@substr) { + my $match; + foreach my $key (qw(name title description src)) { +@@ -306,7 +305,6 @@ sub list_feed { + get_feed($feed); + foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { + my $pkg = $feed_package->{$name}; +- next if $pkg->{vdepends}; + if($pkg->{name}) { + printf "\%-32s\t\%s\n", $pkg->{name}, $pkg->{title}; + } +@@ -588,7 +586,6 @@ sub install { + get_feed($f->[1]); + foreach my $name (sort { lc($a) cmp lc($b) } keys %$feed_package) { + my $p = $feed_package->{$name}; +- next if $p->{vdepends}; + if( $p->{name} ) { + install_package($feed, $p->{name}, exists($opts{f})) == 0 or $ret = 1; + get_feed($f->[1]); +diff --git a/scripts/metadata.pm b/scripts/metadata.pm +index 8334f26d3179a0eb83aa1aa976778ff5828faf45..e7bdbab4568ddd7e10c10b2ca6a718380c7d6308 100644 +--- a/scripts/metadata.pm ++++ b/scripts/metadata.pm +@@ -2,9 +2,10 @@ package metadata; + use base 'Exporter'; + use strict; + use warnings; +-our @EXPORT = qw(%package %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore); ++our @EXPORT = qw(%package %vpackage %srcpackage %category %subdir %preconfig %features %overrides clear_packages parse_package_metadata parse_target_metadata get_multiline @ignore); + + our %package; ++our %vpackage; + our %preconfig; + our %srcpackage; + our %category; +@@ -124,6 +125,7 @@ sub clear_packages() { + %subdir = (); + %preconfig = (); + %package = (); ++ %vpackage = (); + %srcpackage = (); + %category = (); + %features = (); +@@ -179,6 +181,9 @@ sub parse_package_metadata($) { + $pkg->{override} = $override; + $package{$1} = $pkg; + push @{$srcpackage{$src}}, $pkg; ++ ++ $vpackage{$1} or $vpackage{$1} = []; ++ unshift @{$vpackage{$1}}, $1; + }; + /^Feature:\s*(.+?)\s*$/ and do { + undef $pkg; +@@ -210,14 +215,8 @@ sub parse_package_metadata($) { + /^Provides: \s*(.+)\s*$/ and do { + my @vpkg = split /\s+/, $1; + foreach my $vpkg (@vpkg) { +- $package{$vpkg} or $package{$vpkg} = { +- name => $vpkg, +- vdepends => [], +- src => $src, +- subdir => $subdir, +- makefile => $makefile +- }; +- push @{$package{$vpkg}->{vdepends}}, $pkg->{name}; ++ $vpackage{$vpkg} or $vpackage{$vpkg} = []; ++ push @{$vpackage{$vpkg}}, $pkg->{name}; + } + }; + /^Menu-Depends: \s*(.+)\s*$/ and $pkg->{mdepends} = [ split /\s+/, $1 ]; +diff --git a/scripts/package-metadata.pl b/scripts/package-metadata.pl +index 2da32c770ef3333bfcc18922ede556f9734510c7..998d37dd415d89e7eccad2ddf73f855f6a9b017c 100755 +--- a/scripts/package-metadata.pl ++++ b/scripts/package-metadata.pl +@@ -101,14 +101,16 @@ my %dep_check; + sub __find_package_dep($$) { + my $pkg = shift; + my $name = shift; +- my $deps = ($pkg->{vdepends} or $pkg->{depends}); ++ my $deps = $pkg->{depends}; + + return 0 unless defined $deps; +- foreach my $dep (@{$deps}) { +- next if $dep_check{$dep}; +- $dep_check{$dep} = 1; +- return 1 if $dep eq $name; +- return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1)); ++ foreach my $vpkg (@{$deps}) { ++ foreach my $dep (@{$vpackage{$vpkg}}) { ++ next if $dep_check{$dep}; ++ $dep_check{$dep} = 1; ++ return 1 if $dep eq $name; ++ return 1 if ($package{$dep} and (__find_package_dep($package{$dep},$name) == 1)); ++ } + } + return 0; + } +@@ -156,7 +158,6 @@ sub mconf_depends { + my $m = "depends on"; + my $flags = ""; + $depend =~ s/^([@\+]+)// and $flags = $1; +- my $vdep; + my $condition = $parent_condition; + + next if $condition eq $depend; +@@ -173,9 +174,9 @@ sub mconf_depends { + } + $depend = $2; + } +- next if $package{$depend} and $package{$depend}->{buildonly}; + if ($flags =~ /\+/) { +- if ($vdep = $package{$depend}->{vdepends}) { ++ my $vdep = $vpackage{$depend}; ++ if ($vdep and @$vdep > 0) { + my @vdeps; + $depend = undef; + +@@ -209,7 +210,8 @@ sub mconf_depends { + + $flags =~ /@/ or $depend = "PACKAGE_$depend"; + } else { +- if ($vdep = $package{$depend}->{vdepends}) { ++ my $vdep = $vpackage{$depend}; ++ if ($vdep and @$vdep > 0) { + $depend = join("||", map { "PACKAGE_".$_ } @$vdep); + } else { + $flags =~ /@/ or $depend = "PACKAGE_$depend"; +@@ -413,7 +415,6 @@ sub get_conditional_dep($$) { + + sub gen_package_mk() { + my %conf; +- my %dep; + my %done; + my $line; + +@@ -423,8 +424,6 @@ sub gen_package_mk() { + my $pkg = $package{$name}; + my @srcdeps; + +- next if defined $pkg->{vdepends}; +- + $config = "\$(CONFIG_PACKAGE_$name)"; + if ($config) { + $pkg->{buildonly} and $config = ""; +@@ -445,16 +444,7 @@ sub gen_package_mk() { + print "buildtypes-$pkg->{subdir}$pkg->{src} = ".join(' ', @{$pkg->{buildtypes}})."\n"; + } + +- foreach my $spkg (@{$srcpackage{$pkg->{src}}}) { +- foreach my $dep (@{$spkg->{depends}}, @{$spkg->{builddepends}}) { +- $dep =~ /@/ or do { +- $dep =~ s/\+//g; +- push @srcdeps, $dep; +- }; +- } +- } + foreach my $type (@{$pkg->{buildtypes}}) { +- my @extra_deps; + my %deplines; + + next unless $pkg->{"builddepends/$type"}; +@@ -492,63 +482,70 @@ sub gen_package_mk() { + } + } + +- my $hasdeps = 0; + my %deplines; +- foreach my $deps (@srcdeps) { +- my $idx; +- my $condition; +- my $prefix = ""; +- my $suffix = ""; +- +- if ($deps =~ /^(.+):(.+)/) { +- $condition = $1; +- $deps = $2; +- } +- if ($deps =~ /^(.+)(\/.+)/) { +- $deps = $1; +- $suffix = $2; +- } ++ foreach my $spkg (@{$srcpackage{$pkg->{src}}}) { ++ foreach my $bdep (@{$spkg->{builddepends}}) { ++ my $condition; ++ my $suffix = ""; + +- my $pkg_dep = $package{$deps}; +- my @deps; ++ if ($bdep =~ /^(.+):(.+)/) { ++ $condition = $1; ++ $bdep = $2; ++ } ++ if ($bdep =~ /^(.+)(\/.+)/) { ++ $bdep = $1; ++ $suffix = $2; ++ } + +- if ($pkg_dep->{vdepends}) { +- @deps = @{$pkg_dep->{vdepends}}; +- } else { +- @deps = ($deps); ++ next unless $subdir{$bdep}; ++ my $idx = $subdir{$bdep}.$bdep.$suffix; ++ ++ my $depline = get_conditional_dep($condition, "\$(curdir)/$idx/compile"); ++ if ($depline) { ++ $deplines{$depline}++; ++ } + } + +- foreach my $dep (@deps) { +- $pkg_dep = $package{$deps}; +- if (defined $pkg_dep->{src}) { +- ($pkg->{src} ne $pkg_dep->{src}.$suffix) and $idx = $pkg_dep->{subdir}.$pkg_dep->{src}; +- } elsif (defined($srcpackage{$dep})) { +- $idx = $subdir{$dep}.$dep; ++ foreach my $dep (@{$spkg->{depends}}) { ++ my $condition; ++ my $suffix = ""; ++ ++ next if $dep =~ /@/; ++ $dep =~ s/\+//g; ++ ++ if ($dep =~ /^(.+):(.+)/) { ++ $condition = $1; ++ $dep = $2; + } +- undef $idx if $idx eq 'base-files'; +- if ($idx) { +- $idx .= $suffix; ++ if ($dep =~ /^(.+)(\/.+)/) { ++ $dep = $1; ++ $suffix = $2; ++ } ++ ++ next unless $vpackage{$dep}; ++ ++ my @vdeps = @{$vpackage{$dep}}; ++ foreach my $vdep (@vdeps) { ++ my $pkg_dep = $package{$vdep}; + +- my $depline; ++ next unless $pkg_dep; + next if $pkg->{src} eq $pkg_dep->{src}.$suffix; +- next if $dep{$condition.":".$pkg->{src}."->".$idx}; +- next if $dep{$pkg->{src}."->($dep)".$idx} and $pkg_dep->{vdepends}; +- my $depstr; + +- if ($pkg_dep->{vdepends}) { +- $depstr = "\$(if \$(CONFIG_PACKAGE_$dep),\$(curdir)/$idx/compile)"; +- $dep{$pkg->{src}."->($dep)".$idx} = 1; ++ my $idx = $pkg_dep->{subdir}.$pkg_dep->{src}.$suffix; ++ my $depstr; ++ if (@vdeps > 1) { ++ $depstr = "\$(if \$(CONFIG_PACKAGE_$vdep),\$(curdir)/$idx/compile)"; + } else { + $depstr = "\$(curdir)/$idx/compile"; +- $dep{$pkg->{src}."->".$idx} = 1; + } +- $depline = get_conditional_dep($condition, $depstr); ++ my $depline = get_conditional_dep($condition, $depstr); + if ($depline) { + $deplines{$depline}++; + } + } + } + } ++ + my $depline = join(" ", sort keys %deplines); + if ($depline) { + $line .= "\$(curdir)/".$pkg->{subdir}."$pkg->{src}/compile += $depline\n"; +@@ -573,7 +570,7 @@ ifndef DUMP_TARGET_DB + ( \\ + $cmds \\ + ) > \$@ +- ++ + ifneq (\$(IMAGEOPT)\$(CONFIG_IMAGEOPT),) + package/preconfig: \$(TARGET_DIR)/etc/uci-defaults/$preconfig + endif diff --git a/patches/lede/0032-base-files-upgrade-correctly-handle-nand_do_upgrade-argument-passed-from-preupgrade.patch b/patches/lede/0032-base-files-upgrade-correctly-handle-nand_do_upgrade-argument-passed-from-preupgrade.patch new file mode 100644 index 00000000..82de1177 --- /dev/null +++ b/patches/lede/0032-base-files-upgrade-correctly-handle-nand_do_upgrade-argument-passed-from-preupgrade.patch @@ -0,0 +1,33 @@ +From: Matthias Schiffer +Date: Mon, 10 Jul 2017 10:35:19 +0200 +Subject: base-files: upgrade: correctly handle nand_do_upgrade argument passed from preupgrade + +Fixes: 30f61a34b4cf "base-files: always use staged sysupgrade" +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh +index af7682c29e005c6ca47b91e9be2d60c359a90d05..6ccd84c5a95348124412adc8bf41d3fa4894435a 100644 +--- a/package/base-files/files/lib/upgrade/common.sh ++++ b/package/base-files/files/lib/upgrade/common.sh +@@ -222,7 +222,7 @@ default_do_upgrade() { + do_upgrade_stage2() { + v "Performing system upgrade..." + if [ -n "$do_upgrade" ]; then +- $do_upgrade "$IMAGE" ++ eval "$do_upgrade" + elif type 'platform_do_upgrade' >/dev/null 2>/dev/null; then + platform_do_upgrade "$IMAGE" + else +diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh +index 1e69c8f9657b39adf2a2c33bd9bac9303bcbc3d7..72f0fe0e10312e74ce085ad53f0adceb921fd013 100644 +--- a/package/base-files/files/lib/upgrade/nand.sh ++++ b/package/base-files/files/lib/upgrade/nand.sh +@@ -289,7 +289,7 @@ nand_do_upgrade() { + # hook; this piece of code handles scripts that haven't been + # updated. All scripts should gradually move to call nand_do_upgrade + # from platform_do_upgrade instead. +- export do_upgrade=nand_do_upgrade ++ export do_upgrade="nand_do_upgrade '$1'" + return + fi + diff --git a/patches/lede/0033-base-files-upgrade-don-t-loop-forever-trying-to-kill-processes.patch b/patches/lede/0033-base-files-upgrade-don-t-loop-forever-trying-to-kill-processes.patch new file mode 100644 index 00000000..2dfe0ca6 --- /dev/null +++ b/patches/lede/0033-base-files-upgrade-don-t-loop-forever-trying-to-kill-processes.patch @@ -0,0 +1,42 @@ +From: Matthias Schiffer +Date: Thu, 13 Jul 2017 00:19:32 +0200 +Subject: base-files: upgrade: don't loop forever trying to kill processes + +When processes don't die on SIGKILL (usually because of kernel bugs), it's +better to give up instead of looping forever. + +upgraded will trigger a reboot in this case (and if this fails, a hardware +watchdog will eventually time out and reset the system, if present). + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 +index bdbb8926643287f48a4ae62c5d1d4b4a29130859..097ad63adfecdd70019acaa5b652d2056e774c3f 100755 +--- a/package/base-files/files/lib/upgrade/stage2 ++++ b/package/base-files/files/lib/upgrade/stage2 +@@ -87,6 +87,8 @@ switch_to_ramfs() { + } + + kill_remaining() { # [ [ ] ] ++ local loop_limit=10 ++ + local sig="${1:-TERM}" + local loop="${2:-0}" + local run=true +@@ -117,8 +119,15 @@ kill_remaining() { # [ [ ] ] + + [ $loop -eq 1 ] && run=true + done ++ ++ let loop_limit-- ++ [ $loop_limit -eq 0 ] && { ++ echo ++ echo "Failed to kill all processes." ++ exit 1 ++ } + done +- echo "" ++ echo + } + + diff --git a/patches/lede/0034-bcm53xx-upgrade-fix-RAMFS_COPY_.patch b/patches/lede/0034-bcm53xx-upgrade-fix-RAMFS_COPY_.patch new file mode 100644 index 00000000..c9052f73 --- /dev/null +++ b/patches/lede/0034-bcm53xx-upgrade-fix-RAMFS_COPY_.patch @@ -0,0 +1,39 @@ +From: Matthias Schiffer +Date: Sat, 10 Jun 2017 16:14:54 +0200 +Subject: bcm53xx: upgrade: fix RAMFS_COPY_* + +Fixes: 30f61a34b4cf "base-files: always use staged sysupgrade" +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2 +index 097ad63adfecdd70019acaa5b652d2056e774c3f..8cc8c8b34e9f349f1d1283ac00f9782b52ab01c1 100755 +--- a/package/base-files/files/lib/upgrade/stage2 ++++ b/package/base-files/files/lib/upgrade/stage2 +@@ -48,7 +48,7 @@ switch_to_ramfs() { + /bin/sleep /bin/zcat /usr/bin/bzcat /usr/bin/printf /usr/bin/wc \ + /bin/cut /usr/bin/printf /bin/sync /bin/mkdir /bin/rmdir \ + /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \ +- /bin/mknod /bin/touch ++ /bin/mknod /bin/touch /bin/sed + + install_bin /sbin/mtd + install_bin /sbin/mount_root +diff --git a/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh b/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh +index f2e007db22fa8fde93bf0dd58b359f6515e0445c..6a9e4950450cb896db7ebb3eb901b5cf51030295 100644 +--- a/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/bcm53xx/base-files/lib/upgrade/platform.sh +@@ -1,3 +1,5 @@ ++RAMFS_COPY_BIN='/usr/bin/osafeloader /usr/bin/oseama' ++ + PART_NAME=firmware + + # $(1): file to read magic from +@@ -260,8 +262,6 @@ platform_pre_upgrade_seama() { + } + + platform_pre_upgrade() { +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /usr/bin/osafeloader /usr/bin/oseama /bin/sed" +- + local file_type=$(platform_identify "$1") + + [ "$(platform_flash_type)" != "nand" ] && return diff --git a/patches/lede/0035-ipq806x-upgrade-fix-RAMFS_COPY_.patch b/patches/lede/0035-ipq806x-upgrade-fix-RAMFS_COPY_.patch new file mode 100644 index 00000000..71b800fb --- /dev/null +++ b/patches/lede/0035-ipq806x-upgrade-fix-RAMFS_COPY_.patch @@ -0,0 +1,68 @@ +From: Matthias Schiffer +Date: Mon, 10 Jul 2017 18:03:39 +0200 +Subject: ipq806x: upgrade: fix RAMFS_COPY_* + +RAMFS_COPY_* are moved to platform.sh toplevel. The unneeded +linksys_preupgrade function is removed, and the nand_do_upgrade call is +moved to platform_do_upgrade. + +Fixes: 30f61a34b4cf "base-files: always use staged sysupgrade" +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ipq806x/base-files/lib/upgrade/linksys.sh b/target/linux/ipq806x/base-files/lib/upgrade/linksys.sh +index 12f25efdae87979e79a252237f735932cb66d42f..0234ce0a51a0a92dcd719102f83e19686442574a 100644 +--- a/target/linux/ipq806x/base-files/lib/upgrade/linksys.sh ++++ b/target/linux/ipq806x/base-files/lib/upgrade/linksys.sh +@@ -99,12 +99,3 @@ platform_do_upgrade_linksys() { + fi + } + } +- +-linksys_preupgrade() { +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /usr/sbin/fw_printenv /usr/sbin/fw_setenv" +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /bin/mkdir /bin/touch" +- export RAMFS_COPY_DATA="${RAMFS_COPY_DATA} /etc/fw_env.config /var/lock/fw_printenv.lock" +- +-} +- +-append sysupgrade_pre_upgrade linksys_preupgrade +diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +index c3741f9ff242cddb3c185c2f638c7b4dff781e1b..6455b57cfb1346b7cc9e103065080d8ae92edc19 100644 +--- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh +@@ -3,11 +3,14 @@ + PART_NAME=firmware + REQUIRE_IMAGE_METADATA=1 + ++RAMFS_COPY_BIN='/usr/sbin/fw_printenv /usr/sbin/fw_setenv' ++RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' ++ + platform_check_image() { + return 0; + } + +-platform_pre_upgrade() { ++platform_do_upgrade() { + local board=$(ipq806x_board_name) + + case "$board" in +@@ -17,18 +20,8 @@ platform_pre_upgrade() { + r7500 |\ + r7500v2 |\ + r7800) +- nand_do_upgrade "$1" +- ;; +- ea8500) +- linksys_preupgrade "$1" ++ nand_do_upgrade "$ARGV" + ;; +- esac +-} +- +-platform_do_upgrade() { +- local board=$(ipq806x_board_name) +- +- case "$board" in + c2600) + PART_NAME="os-image:rootfs" + MTD_CONFIG_ARGS="-s 0x200000" diff --git a/patches/lede/0036-kirkwood-upgrade-fix-RAMFS_COPY_.patch b/patches/lede/0036-kirkwood-upgrade-fix-RAMFS_COPY_.patch new file mode 100644 index 00000000..7c58d6ce --- /dev/null +++ b/patches/lede/0036-kirkwood-upgrade-fix-RAMFS_COPY_.patch @@ -0,0 +1,60 @@ +From: Matthias Schiffer +Date: Mon, 10 Jul 2017 18:16:23 +0200 +Subject: kirkwood: upgrade: fix RAMFS_COPY_* + +RAMFS_COPY_* are moved to platform.sh toplevel. The nand_do_upgrade call is +moved to platform_do_upgrade. + +Fixes: 30f61a34b4cf "base-files: always use staged sysupgrade" +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/kirkwood/base-files/lib/upgrade/linksys.sh b/target/linux/kirkwood/base-files/lib/upgrade/linksys.sh +index 13a8f1cb554462acf39a59c9d5c1e6cd4ec222f5..dde3bd1b2190d68ce54e6c2883a45032d58599b2 100644 +--- a/target/linux/kirkwood/base-files/lib/upgrade/linksys.sh ++++ b/target/linux/kirkwood/base-files/lib/upgrade/linksys.sh +@@ -69,11 +69,3 @@ platform_do_upgrade_linksys() { + fi + } + } +- +-linksys_preupgrade() { +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /usr/sbin/fw_printenv /usr/sbin/fw_setenv" +- export RAMFS_COPY_BIN="${RAMFS_COPY_BIN} /bin/mkdir /bin/touch" +- export RAMFS_COPY_DATA="${RAMFS_COPY_DATA} /etc/fw_env.config /var/lock/fw_printenv.lock" +-} +- +-append sysupgrade_pre_upgrade linksys_preupgrade +diff --git a/target/linux/kirkwood/base-files/lib/upgrade/platform.sh b/target/linux/kirkwood/base-files/lib/upgrade/platform.sh +index e7c6a1120a90147380f4fcf644eb7078c1bc1659..c8c66c1b9d67759305ee836f9d84b9a2968a9493 100644 +--- a/target/linux/kirkwood/base-files/lib/upgrade/platform.sh ++++ b/target/linux/kirkwood/base-files/lib/upgrade/platform.sh +@@ -1,5 +1,8 @@ + . /lib/kirkwood.sh + ++RAMFS_COPY_BIN='/usr/sbin/fw_printenv /usr/sbin/fw_setenv' ++RAMFS_COPY_DATA='/etc/fw_env.config /var/lock/fw_printenv.lock' ++ + platform_check_image() { + [ "$#" -gt 1 ] && return 1 + local board="$(kirkwood_board_name)" +@@ -33,19 +36,7 @@ platform_do_upgrade() { + platform_do_upgrade_linksys "$ARGV" + ;; + *) +- default_do_upgrade "$@" +- ;; +- esac +-} +- +-platform_pre_upgrade() { +- local board=$(kirkwood_board_name) +- +- case "$board" in +- "linksys-audi"|\ +- "linksys-viper") ;; +- *) +- nand_do_upgrade $1 ++ nand_do_upgrade "$ARGV" + ;; + esac + } diff --git a/patches/lede/0037-ar71xx-add-uImageArcher-to-tp-link.mk.patch b/patches/lede/0037-ar71xx-add-uImageArcher-to-tp-link.mk.patch new file mode 100644 index 00000000..547548fd --- /dev/null +++ b/patches/lede/0037-ar71xx-add-uImageArcher-to-tp-link.mk.patch @@ -0,0 +1,29 @@ +From: Andreas Ziegler +Date: Sun, 6 Aug 2017 16:27:53 +0200 +Subject: ar71xx: add uImageArcher to tp-link.mk + +backport from e39dc8d823c86559eedbbdcee5f5c14b827fed0f +ar71xx: add support to TP-Link Archer C59v1 and C60v1 + +Based-on-patch-by: Henryk Heisig +Signed-off-by: Andreas Ziegler + +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index b76ed02ca394fc1a8b15218d64b5dc722552bbfd..9cd6c6372ac8f7e509a0a2422616097c1c19edf6 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -45,6 +45,14 @@ define Build/mktplinkfw-kernel + @mv $@.new $@ + endef + ++define Build/uImageArcher ++ mkimage -A $(LINUX_KARCH) \ ++ -O linux -T kernel \ ++ -C $(1) -a $(KERNEL_LOADADDR) -e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \ ++ -n '$(call toupper,$(LINUX_KARCH)) LEDE Linux-$(LINUX_VERSION)' -d $@ $@.new ++ @mv $@.new $@ ++endef ++ + define Device/tplink + TPLINK_HWREV := 0x1 + TPLINK_HEADER_VERSION := 1 diff --git a/patches/lede/0038-ar71xx-add-support-for-TP-Link-Archer-C25-v1.patch b/patches/lede/0038-ar71xx-add-support-for-TP-Link-Archer-C25-v1.patch new file mode 100644 index 00000000..30217b25 --- /dev/null +++ b/patches/lede/0038-ar71xx-add-support-for-TP-Link-Archer-C25-v1.patch @@ -0,0 +1,444 @@ +From: Ludwig Thomeczek +Date: Sat, 22 Apr 2017 18:21:47 +0200 +Subject: ar71xx: add support for TP-Link Archer C25 v1 + +The TP-Link Archer C25 is a low-cost dual-band router. + +Specification: + +- CPU: Atheros QCA9561 775 MHz +- RAM: 64 MB +- Flash: 8 MB +- Wifi: 3x3 2.4 GHz (integrated), 1x1 5 GHz QCA9887 +- NET: 5x 10/100 Mbps Ethernet + +Some LEDs are controlled by an additional 74HC595 chip. + +Signed-off-by: Ludwig Thomeczek +[minor code style fixes, boards alphabetical order fixes, +reworked commit message] +Signed-off-by: Piotr Dymacz + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 833522f27b61ac2208c2862bc0f29f34dea5e701..e1efb561b33da4dcfcb82ee953cd888170476dfb 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -53,6 +53,15 @@ ap121f) + ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" + ;; ++archer-c25-v1) ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x10" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" ++ ;; + arduino-yun) + ucidef_set_led_wlan "wlan" "WLAN" "arduino:blue:wlan" "phy0tpt" + ucidef_set_led_usbdev "usb" "USB" "arduino:white:usb" "1-1.1" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 6d8a5c3d0a86a627663dee6e2905e03d5dec99fb..cefb7413eac6ffc50e67f1eaf63def749314428b 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -122,6 +122,7 @@ ar71xx_setup_interfaces() + a60|\ + alfa-ap96|\ + alfa-nx|\ ++ archer-c25-v1|\ + dr344|\ + gl-ar150|\ + gl-ar300m|\ +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index bc2fc2f774c4f2f0bbfa6e43d9b9a55e9b63153d..38cc5d7853c79f2a7800a387310a95abb3b4de1b 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -50,6 +50,7 @@ get_status_led() { + ap135-020) + status_led="ap135:green:status" + ;; ++ archer-c25-v1|\ + mr12|\ + mr16|\ + nbg6616|\ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 96ca65e694bb5ed449dcae8dbca1930d25612602..fc9eb005623fc029f839d7ce14788ffba32e42e5 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -98,6 +98,7 @@ case "$FIRMWARE" in + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) + ;; ++ archer-c25-v1|\ + tl-wdr6500-v2) + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -2) +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 170c6f01b4310c4d6c261e9ba97af8786b21c93b..fc7d862c2911e96f76622cbed23e99863814da63 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -463,6 +463,9 @@ ar71xx_board_detect() { + *AP90Q) + name="ap90q" + ;; ++ *"Archer C25 v1") ++ name="archer-c25-v1" ++ ;; + *"Archer C5") + name="archer-c5" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index d2dc88127c02746cdecc4ced28f33548f35d037c..6258713dd0e3325ab109689f0ed3b51e27c41f89 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -214,6 +214,7 @@ platform_check_image() { + ap121f|\ + ap132|\ + ap90q|\ ++ archer-c25-v1|\ + bullet-m|\ + c-55|\ + carambola2|\ +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index 91eb9f0de7ef6c472cdccf2022d888df53b75e46..d1d879cd764259571cce2a5e091ae99f0d7a6d6d 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -51,6 +51,7 @@ CONFIG_ATH79_MACH_AP152=y + # CONFIG_ATH79_MACH_AP81 is not set + CONFIG_ATH79_MACH_AP90Q=y + CONFIG_ATH79_MACH_AP96=y ++CONFIG_ATH79_MACH_ARCHER_C25_V1=y + CONFIG_ATH79_MACH_ARCHER_C7=y + CONFIG_ATH79_MACH_ARDUINO_YUN=y + CONFIG_ATH79_MACH_AW_NR580=y +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 58d7e435362e0bac105e8183206e593329e4ae96..fb2afb965c4641df7cdcaf0920f2d56b3717fa9b 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1234,6 +1234,16 @@ config ATH79_MACH_BSB + select ATH79_DEV_USB + select ATH79_DEV_WMAC + ++config ATH79_MACH_ARCHER_C25_V1 ++ bool "TP-LINK Archer C25 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ + config ATH79_MACH_ARCHER_C7 + bool "TP-LINK Archer C5/C7/TL-WDR4900 v2 board support" + select SOC_QCA955X +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index 7aee76019552e14ebdbf7bea357859dedb1a5bbb..3365a43ce16fc77b3212b39b92081efe678e8803 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -56,6 +56,7 @@ obj-$(CONFIG_ATH79_MACH_AP147) += mach-ap147.o + obj-$(CONFIG_ATH79_MACH_AP152) += mach-ap152.o + obj-$(CONFIG_ATH79_MACH_AP90Q) += mach-ap90q.o + obj-$(CONFIG_ATH79_MACH_AP96) += mach-ap96.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C25_V1) += mach-archer-c25-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o + obj-$(CONFIG_ATH79_MACH_ARDUINO_YUN) += mach-arduino-yun.o + obj-$(CONFIG_ATH79_MACH_AW_NR580) += mach-aw-nr580.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c +new file mode 100644 +index 0000000000000000000000000000000000000000..a0f001cb49af5aa501c6825c40f3a98ab99503b2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c25-v1.c +@@ -0,0 +1,227 @@ ++/* ++ * TP-Link Archer C25 v1 board support ++ * ++ * Copyright (C) 2017 Ludwig Thomeczek ++ * based on mach-archer-c60/C59-v1.c ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include ++#include ++ ++#define ARCHER_C25_GPIO_SHIFT_OE 21 /* OE, Output Enable */ ++#define ARCHER_C25_GPIO_SHIFT_SER 14 /* DS, Data Serial Input */ ++#define ARCHER_C25_GPIO_SHIFT_SRCLK 15 /* SHCP, Shift Reg Clock Input */ ++#define ARCHER_C25_GPIO_SHIFT_SRCLR 19 /* MR, Master Reset */ ++#define ARCHER_C25_GPIO_SHIFT_RCLK 16 /* STCP, Storage Reg Clock Input */ ++ ++#define ARCHER_C25_74HC_GPIO_BASE QCA956X_GPIO_COUNT ++#define ARCHER_C25_74HC_GPIO_LED_WAN_AMBER 27 ++#define ARCHER_C25_74HC_GPIO_LED_WAN_GREEN 28 ++#define ARCHER_C25_74HC_GPIO_LED_WLAN2 29 ++#define ARCHER_C25_74HC_GPIO_LED_WLAN5 30 ++#define ARCHER_C25_74HC_GPIO_LED_LAN1 23 ++#define ARCHER_C25_74HC_GPIO_LED_LAN2 24 ++#define ARCHER_C25_74HC_GPIO_LED_LAN3 25 ++#define ARCHER_C25_74HC_GPIO_LED_LAN4 26 ++ ++#define ARCHER_C25_V1_SSR_BIT_0 0 ++#define ARCHER_C25_V1_SSR_BIT_1 1 ++#define ARCHER_C25_V1_SSR_BIT_2 2 ++#define ARCHER_C25_V1_SSR_BIT_3 3 ++#define ARCHER_C25_V1_SSR_BIT_4 4 ++#define ARCHER_C25_V1_SSR_BIT_5 5 ++#define ARCHER_C25_V1_SSR_BIT_6 6 ++#define ARCHER_C25_V1_SSR_BIT_7 7 ++ ++ ++#define ARCHER_C25_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL \ ++ (3 * ARCHER_C25_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C25_V1_GPIO_BTN_RESET 1 ++#define ARCHER_C25_V1_GPIO_BTN_RFKILL 22 ++ ++#define ARCHER_C25_V1_GPIO_LED_POWER 17 ++#define ARCHER_C25_V1_GPIO_LED_WPS 2 ++ ++#define ARCHER_C25_V1_WMAC_CALDATA_OFFSET 0x1000 ++ ++static struct spi_gpio_platform_data archer_c25_v1_spi_data = { ++ .sck = ARCHER_C25_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C25_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c25_v1_ssr_initdata[] __initdata = { ++ BIT(ARCHER_C25_V1_SSR_BIT_7) | ++ BIT(ARCHER_C25_V1_SSR_BIT_6) | ++ BIT(ARCHER_C25_V1_SSR_BIT_5) | ++ BIT(ARCHER_C25_V1_SSR_BIT_4) | ++ BIT(ARCHER_C25_V1_SSR_BIT_3) | ++ BIT(ARCHER_C25_V1_SSR_BIT_2) | ++ BIT(ARCHER_C25_V1_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data archer_c25_v1_ssr_data = { ++ .base = ARCHER_C25_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(archer_c25_v1_ssr_initdata), ++ .init_data = archer_c25_v1_ssr_initdata, ++}; ++ ++static struct platform_device archer_c25_v1_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c25_v1_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c25_v1_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c25_v1_ssr_data, ++ .controller_data = (void *) ARCHER_C25_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static struct gpio_led archer_c25_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c25-v1:green:power", ++ .gpio = ARCHER_C25_V1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wps", ++ .gpio = ARCHER_C25_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wlan2g", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wlan5g", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan1", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan2", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan3", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:lan4", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:green:wan", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "archer-c25-v1:amber:wan", ++ .gpio = ARCHER_C25_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c25_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C25_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C25_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C25_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init archer_c25_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f7e0008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ spi_register_board_info(archer_c25_v1_spi_info, ++ ARRAY_SIZE(archer_c25_v1_spi_info)); ++ ++ platform_device_register(&archer_c25_v1_spi_device); ++ ++ gpio_request_one(ARCHER_C25_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ ++ gpio_request_one(ARCHER_C25_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c25_v1_leds_gpio), ++ archer_c25_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C25_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c25_v1_gpio_keys), ++ archer_c25_v1_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C25_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(NULL, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C25_V1, "ARCHER-C25-V1", "TP-LINK Archer C25 v1", ++ archer_c25_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index a12685cd11a7a6cefe9b69991a5e41db55ccea85..8864e0deda57b926e88dceebd26056a2f8099380 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -40,6 +40,7 @@ enum ath79_mach_type { + ATH79_MACH_AP152, /* Atheros AP152 reference board */ + ATH79_MACH_AP90Q, /* YunCore AP90Q */ + ATH79_MACH_AP96, /* Atheros AP96 */ ++ ATH79_MACH_ARCHER_C25_V1, /* TP-LINK Archer C25 V1 board */ + ATH79_MACH_ARCHER_C5, /* TP-LINK Archer C5 board */ + ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */ + ATH79_MACH_ARCHER_C7_V2, /* TP-LINK Archer C7 V2 board */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 9cd6c6372ac8f7e509a0a2422616097c1c19edf6..6933654e575a1ef2c92e4c656696a479cba4c594 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -103,6 +103,22 @@ $(Device/tplink) + IMAGE_SIZE := 15872k + endef + ++define Device/archer-c25-v1 ++ DEVICE_TITLE := TP-LINK Archer C25 v1 ++ DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca9887 ++ BOARDNAME := ARCHER-C25-V1 ++ TPLINK_BOARD_NAME := ARCHER-C25-V1 ++ DEVICE_PROFILE := ARCHERC25V1 ++ IMAGE_SIZE := 7808k ++ LOADER_TYPE := elf ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,64k(u-boot)ro,1536k(kernel),6272k(rootfs),128k(config)ro,64k(art)ro,7808k@0x30000(firmware) ++endef ++TARGET_DEVICES += archer-c25-v1 ++ + define Device/cpe510-520 + DEVICE_TITLE := TP-LINK CPE510/520 + DEVICE_PACKAGES := rssileds +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index f8d255fd87b8c53511b34b42f4117422218219fe..376835a703f91532300d0dd7c8ef66704acc6e05 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -16,6 +16,7 @@ + # CONFIG_ATH79_MACH_AP152 is not set + # CONFIG_ATH79_MACH_AP90Q is not set + # CONFIG_ATH79_MACH_AP96 is not set ++# CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set + # CONFIG_ATH79_MACH_ARDUINO_YUN is not set + # CONFIG_ATH79_MACH_AW_NR580 is not set +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index c1b5e61c3e9e5f02979584f72621f5e54cde2e36..62be218e33cc6366ea89f363983f36523c419650 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -9,6 +9,7 @@ + # CONFIG_ATH79_MACH_AP136 is not set + # CONFIG_ATH79_MACH_AP147 is not set + # CONFIG_ATH79_MACH_AP96 is not set ++# CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set + # CONFIG_ATH79_MACH_AW_NR580 is not set + # CONFIG_ATH79_MACH_CAP324 is not set diff --git a/patches/lede/0039-firmware-utils-tplink-safeloader-add-TP-Link-Archer-C25-v1.patch b/patches/lede/0039-firmware-utils-tplink-safeloader-add-TP-Link-Archer-C25-v1.patch new file mode 100644 index 00000000..77817224 --- /dev/null +++ b/patches/lede/0039-firmware-utils-tplink-safeloader-add-TP-Link-Archer-C25-v1.patch @@ -0,0 +1,102 @@ +From: Ludwig Thomeczek +Date: Sat, 13 May 2017 11:40:48 +0200 +Subject: firmware-utils: tplink-safeloader: add TP-Link Archer C25 v1 + +This adds the necessary firmware layout definitions for the Archer C25. +It has an addtional partition containing some static data ("extra-para") +without which no factory flash is possible, therefore put_data() has been +added. + +Signed-off-by: Ludwig Thomeczek + +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 4e3d2058b286fb7220e5a8308dcdfb25626a1b59..7617566829e159ae9fec00d5de95919a0fb234c6 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -293,6 +293,48 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "file-system" + }, + ++ /** Firmware layout for the C25v1 */ ++ { ++ .id = "ARCHER-C25-V1", ++ .support_list = ++ "SupportList:\n" ++ "{product_name:ArcherC25,product_ver:1.0.0,special_id:00000000}\n" ++ "{product_name:ArcherC25,product_ver:1.0.0,special_id:55530000}\n" ++ "{product_name:ArcherC25,product_ver:1.0.0,special_id:45550000}\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ ++ /** ++ We use a bigger os-image partition than the stock images (and thus ++ smaller file-system), as our kernel doesn't fit in the stock firmware's ++ 1MB os-image. ++ */ ++ .partitions = { ++ {"factory-boot", 0x00000, 0x20000}, ++ {"fs-uboot", 0x20000, 0x10000}, ++ {"os-image", 0x30000, 0x180000}, /* Stock: base 0x30000 size 0x100000 */ ++ {"file-system", 0x1b0000, 0x620000}, /* Stock: base 0x130000 size 0x6a0000 */ ++ {"user-config", 0x7d0000, 0x04000}, ++ {"default-mac", 0x7e0000, 0x00100}, ++ {"device-id", 0x7e0100, 0x00100}, ++ {"extra-para", 0x7e0200, 0x00100}, ++ {"pin", 0x7e0300, 0x00100}, ++ {"support-list", 0x7e0400, 0x00400}, ++ {"soft-version", 0x7e0800, 0x00400}, ++ {"product-info", 0x7e0c00, 0x01400}, ++ {"partition-table", 0x7e2000, 0x01000}, ++ {"profile", 0x7e3000, 0x01000}, ++ {"default-config", 0x7e4000, 0x04000}, ++ {"merge-config", 0x7ec000, 0x02000}, ++ {"qos-db", 0x7ee000, 0x02000}, ++ {"radio", 0x7f0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system", ++ }, ++ + /** Firmware layout for the C5 */ + { + .id = "ARCHER-C5-V2", +@@ -615,6 +657,15 @@ static struct image_partition_entry read_file(const char *part_name, const char + return entry; + } + ++/** Creates a new image partition from arbitrary data */ ++static struct image_partition_entry put_data(const char *part_name, const char *datain, size_t len) { ++ ++ struct image_partition_entry entry = alloc_image_partition(part_name, len); ++ ++ memcpy(entry.data, datain, len); ++ ++ return entry; ++} + + /** + Copies a list of image partitions into an image buffer and generates the image partition table while doing so +@@ -796,7 +847,8 @@ static void build_image(const char *output, + bool add_jffs2_eof, + bool sysupgrade, + const struct device_info *info) { +- struct image_partition_entry parts[6] = {}; ++ ++ struct image_partition_entry parts[7] = {}; + + parts[0] = make_partition_table(info->partitions); + parts[1] = make_soft_version(rev); +@@ -804,6 +856,11 @@ static void build_image(const char *output, + parts[3] = read_file("os-image", kernel_image, false); + parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); + ++ if (strcasecmp(info->id, "ARCHER-C25-V1") == 0) { ++ const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; ++ parts[5] = put_data("extra-para", mdat, 11); ++ } ++ + size_t len; + void *image; + if (sysupgrade) diff --git a/patches/lede/0040-firmware-utils-tplink-safeloader-support-strings-as-soft_version.patch b/patches/lede/0040-firmware-utils-tplink-safeloader-support-strings-as-soft_version.patch new file mode 100644 index 00000000..3a27379c --- /dev/null +++ b/patches/lede/0040-firmware-utils-tplink-safeloader-support-strings-as-soft_version.patch @@ -0,0 +1,152 @@ +From: Jan Niehusmann +Date: Fri, 19 May 2017 09:42:24 +0200 +Subject: firmware-utils: tplink-safeloader: support strings as soft_version + +Some TP-Link routers (C25, C59, C60) contain a version string instead +of a binary structure in the soft_version partition. + +Flashing LEDE from the original firmware's GUI, this version string +taken from the soft_ver partition of the firmware image is written to +the router's config partition. + +When using tftp recovery to go back to the original Archer C25 firmware, +a version check compares that version to the version of the firmware to +be flashed. + +Without proper contents in the config partition, reverting to the +original firmware fails. + +Therefore, write the string "soft_ver:1.0.0\n" to that soft_ver +partition. + +Signed-off-by: Jan Niehusmann + +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 7617566829e159ae9fec00d5de95919a0fb234c6..24684268b1a3fe491c4eb876a5ebefc700f2e56e 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -75,6 +75,7 @@ struct device_info { + const char *vendor; + const char *support_list; + char support_trail; ++ const char *soft_ver; + const struct flash_partition_entry partitions[MAX_PARTITIONS+1]; + const char *first_sysupgrade_partition; + const char *last_sysupgrade_partition; +@@ -130,6 +131,7 @@ static struct device_info boards[] = { + "CPE220(TP-LINK|US|N300-2):1.1\r\n" + "CPE220(TP-LINK|EU|N300-2):1.1\r\n", + .support_trail = '\xff', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +@@ -167,6 +169,7 @@ static struct device_info boards[] = { + "CPE520(TP-LINK|US|N300-5):1.1\r\n" + "CPE520(TP-LINK|EU|N300-5):1.1\r\n", + .support_trail = '\xff', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +@@ -198,6 +201,7 @@ static struct device_info boards[] = { + "WBS210(TP-LINK|US|N300-2):1.20\r\n" + "WBS210(TP-LINK|EU|N300-2):1.20\r\n", + .support_trail = '\xff', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +@@ -229,6 +233,7 @@ static struct device_info boards[] = { + "WBS510(TP-LINK|US|N300-5):1.20\r\n" + "WBS510(TP-LINK|EU|N300-5):1.20\r\n", + .support_trail = '\xff', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +@@ -259,6 +264,7 @@ static struct device_info boards[] = { + "SupportList:\r\n" + "{product_name:Archer C2600,product_ver:1.0.0,special_id:00000000}\r\n", + .support_trail = '\x00', ++ .soft_ver = NULL, + + .partitions = { + {"SBL1", 0x00000, 0x20000}, +@@ -345,6 +351,7 @@ static struct device_info boards[] = { + "product_ver:2.0.0," + "special_id:00000000}\r\n", + .support_trail = '\x00', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x40000}, +@@ -379,6 +386,7 @@ static struct device_info boards[] = { + "product_ver:1.0.0," + "special_id:00000000}\n", + .support_trail = '\x00', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x40000}, +@@ -411,6 +419,7 @@ static struct device_info boards[] = { + "SupportList:\r\n" + "EAP120(TP-LINK|UN|N300-2):1.0\r\n", + .support_trail = '\xff', ++ .soft_ver = NULL, + + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +@@ -440,6 +449,7 @@ static struct device_info boards[] = { + "SupportList:\n" + "{product_name:TL-WR1043ND,product_ver:4.0.0,special_id:45550000}\n", + .support_trail = '\x00', ++ .soft_ver = NULL, + + /** + We use a bigger os-image partition than the stock images (and thus +@@ -483,6 +493,7 @@ static struct device_info boards[] = { + "{product_name:RE450,product_ver:1.0.0,special_id:4B520000}\r\n" + "{product_name:RE450,product_ver:1.0.0,special_id:55534100}\r\n", + .support_trail = '\x00', ++ .soft_ver = NULL, + + /** + The flash partition table for RE450; +@@ -611,6 +622,23 @@ static struct image_partition_entry make_soft_version(uint32_t rev) { + return entry; + } + ++static struct image_partition_entry make_soft_version_from_string(const char *soft_ver) { ++ /** String length _including_ the terminating zero byte */ ++ uint32_t ver_len = strlen(soft_ver) + 1; ++ /** Partition contains 64 bit header, the version string, and one additional null byte */ ++ size_t partition_len = 2*sizeof(uint32_t) + ver_len + 1; ++ struct image_partition_entry entry = alloc_image_partition("soft-version", partition_len); ++ ++ uint32_t *len = (uint32_t *)entry.data; ++ len[0] = htonl(ver_len); ++ len[1] = 0; ++ memcpy(&len[2], soft_ver, ver_len); ++ ++ entry.data[partition_len - 1] = 0; ++ ++ return entry; ++} ++ + /** Generates the support-list partition */ + static struct image_partition_entry make_support_list(const struct device_info *info) { + size_t len = strlen(info->support_list); +@@ -851,7 +879,11 @@ static void build_image(const char *output, + struct image_partition_entry parts[7] = {}; + + parts[0] = make_partition_table(info->partitions); +- parts[1] = make_soft_version(rev); ++ if (info->soft_ver) ++ parts[1] = make_soft_version_from_string(info->soft_ver); ++ else ++ parts[1] = make_soft_version(rev); ++ + parts[2] = make_support_list(info); + parts[3] = read_file("os-image", kernel_image, false); + parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); diff --git a/patches/lede/0041-add-CONFIG_GPIO_74X164-and-CONFIG_SPI_GPIO-for-Archer-C25.patch b/patches/lede/0041-add-CONFIG_GPIO_74X164-and-CONFIG_SPI_GPIO-for-Archer-C25.patch new file mode 100644 index 00000000..f44774b1 --- /dev/null +++ b/patches/lede/0041-add-CONFIG_GPIO_74X164-and-CONFIG_SPI_GPIO-for-Archer-C25.patch @@ -0,0 +1,30 @@ +From: Andreas Ziegler +Date: Thu, 3 Aug 2017 03:34:19 +0200 +Subject: add CONFIG_GPIO_74X164 and CONFIG_SPI_GPIO for Archer C25 + +backport from e39dc8d823c86559eedbbdcee5f5c14b827fed0f +introduced for Archer C59/C60 + +Based-on-patch-by: Henryk Heisig +Signed-off-by: Andreas Ziegler + +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index d1d879cd764259571cce2a5e091ae99f0d7a6d6d..e576fd2ec4f0a8d3613f00aa0a29586b8c65abe0 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -273,6 +273,7 @@ CONFIG_GENERIC_TIME_VSYSCALL=y + CONFIG_GPIOLIB=y + CONFIG_GPIOLIB_IRQCHIP=y + CONFIG_GPIO_DEVRES=y ++CONFIG_GPIO_74X164=y + # CONFIG_GPIO_LATCH is not set + CONFIG_GPIO_NXP_74HC153=y + CONFIG_GPIO_PCF857X=y +@@ -430,6 +431,7 @@ CONFIG_SOC_QCA956X=y + CONFIG_SPI=y + CONFIG_SPI_ATH79=y + CONFIG_SPI_BITBANG=y ++CONFIG_SPI_GPIO=y + CONFIG_SPI_MASTER=y + # CONFIG_SPI_RB4XX is not set + # CONFIG_SPI_VSC7385 is not set diff --git a/patches/lede/0042-ramips-use-GPIO_ACTIVE-macros-in-UBNT-ERX.dts.patch b/patches/lede/0042-ramips-use-GPIO_ACTIVE-macros-in-UBNT-ERX.dts.patch new file mode 100644 index 00000000..e5126c64 --- /dev/null +++ b/patches/lede/0042-ramips-use-GPIO_ACTIVE-macros-in-UBNT-ERX.dts.patch @@ -0,0 +1,35 @@ +From: Sven Roederer +Date: Fri, 5 May 2017 22:18:44 +0200 +Subject: ramips: use GPIO_ACTIVE macros in UBNT-ERX.dts + +- reorder includes +- use GPIO_ACTIVE_LOW macro instead of hardcoded "1" + +Signed-off-by: Sven Roederer + +diff --git a/target/linux/ramips/dts/UBNT-ERX.dts b/target/linux/ramips/dts/UBNT-ERX.dts +index 0b2da95b30f0e181e1929502b8ef1aa50a684f69..cf86bbb7e67b1c521c279367ee9e99fee88fae85 100644 +--- a/target/linux/ramips/dts/UBNT-ERX.dts ++++ b/target/linux/ramips/dts/UBNT-ERX.dts +@@ -1,9 +1,10 @@ +-#include +- + /dts-v1/; + + #include "mt7621.dtsi" + ++#include ++#include ++ + / { + model = "UBNT-ERX"; + +@@ -24,7 +25,7 @@ + + reset { + label = "reset"; +- gpios = <&gpio0 12 1>; ++ gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; diff --git a/patches/lede/0043-ramips-add-support-for-Ubiquiti-EdgeRouter-X-SFP.patch b/patches/lede/0043-ramips-add-support-for-Ubiquiti-EdgeRouter-X-SFP.patch new file mode 100644 index 00000000..18a91d4e --- /dev/null +++ b/patches/lede/0043-ramips-add-support-for-Ubiquiti-EdgeRouter-X-SFP.patch @@ -0,0 +1,413 @@ +From: Sven Roederer +Date: Mon, 29 May 2017 11:24:49 +0200 +Subject: ramips: add support for Ubiquiti EdgeRouter X-SFP + +This patch adds support for the Ubiquiti EdgeRouter X-SFP and +improves support for the EdgeRouter X (PoE-passthrough). + +Specification: +- SoC: MediaTek MT7621AT +- Flash: 256 MiB +- RAM: 265 MiB +- Ethernet: 5 x LAN (1000 Mbps) +- UART: 1 x UART on PCB (3.3V, RX, TX, GND) - 57600 8N1 +- EdgeRouter X: + - 1 x PoE-Passtrough (Eth4) + - powered by Wallwart or passive PoE +- EdgeRouter X-SFP: + - 5 x PoE-Out (24V, passive) + - 1 x SFP (unknown status) + - powered by Wallwart (24V) + +Doesn't work: +* SoC has crypto engine but no open driver. +* SoC has nat acceleration, but no open driver. +* This router has 2MB spi flash soldered in but MT + nand/spi drivers do not support pin sharing, + so it is not accessable and disabled. Stock + firmware could read it and it was empty. + +Installation + +via vendor firmware: +- build an Initrd-image (> 3MiB) and upload the factory-image +- initrd can have luci-mod-failsafe +- flash final firmware via LuCI / sysupgrade on rebooted system + +via TFTP: +- stop uboot into tftp-load into option "1" +- upload factory.bin image + +Signed-off-by: Sven Roederer + +diff --git a/target/linux/ramips/base-files/etc/board.d/02_network b/target/linux/ramips/base-files/etc/board.d/02_network +index 17d25b1954e69d6d2a02ad94885cb54486fc904c..5a4042339c6761703578e014612062ac78babd9d 100755 +--- a/target/linux/ramips/base-files/etc/board.d/02_network ++++ b/target/linux/ramips/base-files/etc/board.d/02_network +@@ -145,6 +145,7 @@ ramips_setup_interfaces() + rb750gr3|\ + rt-n14u|\ + ubnt-erx|\ ++ ubnt-erx-sfp|\ + ur-326n4g|\ + wrtnode|\ + wrtnode2p | \ +diff --git a/target/linux/ramips/base-files/etc/board.d/03_gpio_switches b/target/linux/ramips/base-files/etc/board.d/03_gpio_switches +new file mode 100755 +index 0000000000000000000000000000000000000000..859dfb31f51244e69d3dce5fc80b329cb57729f3 +--- /dev/null ++++ b/target/linux/ramips/base-files/etc/board.d/03_gpio_switches +@@ -0,0 +1,25 @@ ++#!/bin/sh ++ ++. /lib/functions/uci-defaults.sh ++. /lib/ramips.sh ++ ++board_config_update ++ ++board=$(ramips_board_name) ++ ++case "$board" in ++ubnt-erx) ++ ucidef_add_gpio_switch "poe_passthrough" "PoE Passthrough" "0" ++ ;; ++ubnt-erx-sfp) ++ ucidef_add_gpio_switch "poe_power_port0" "PoE Power Port0" "496" ++ ucidef_add_gpio_switch "poe_power_port1" "PoE Power Port1" "497" ++ ucidef_add_gpio_switch "poe_power_port2" "PoE Power Port2" "498" ++ ucidef_add_gpio_switch "poe_power_port3" "PoE Power Port3" "499" ++ ucidef_add_gpio_switch "poe_power_port4" "PoE Power Port4" "500" ++ ;; ++esac ++ ++board_config_flush ++ ++exit 0 +diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh +index 17ada648931f16d3e85630dd341defb89ba50d6f..b1091f66b2897a19bd01d4a26a1b3647656fa62b 100755 +--- a/target/linux/ramips/base-files/lib/ramips.sh ++++ b/target/linux/ramips/base-files/lib/ramips.sh +@@ -466,6 +466,9 @@ ramips_board_detect() { + *"UBNT-ERX") + name="ubnt-erx" + ;; ++ *"UBNT-ERX-SFP") ++ name="ubnt-erx-sfp" ++ ;; + *"UR-326N4G") + name="ur-326n4g" + ;; +diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh +index a5cca2080d3b96cef92286b1b15f4f8832d9f8c5..d3efc2dd37ed855a1c0e966e448b67ae73324d5f 100755 +--- a/target/linux/ramips/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh +@@ -234,7 +234,8 @@ platform_check_image() { + } + return 0 + ;; +- ubnt-erx) ++ ubnt-erx|\ ++ ubnt-erx-sfp) + nand_do_platform_check "$board" "$1" + return $?; + ;; +@@ -248,7 +249,8 @@ platform_nand_pre_upgrade() { + local board=$(ramips_board_name) + + case "$board" in +- ubnt-erx) ++ ubnt-erx|\ ++ ubnt-erx-sfp) + platform_upgrade_ubnt_erx "$ARGV" + ;; + esac +@@ -258,7 +260,8 @@ platform_do_upgrade() { + local board=$(ramips_board_name) + + case "$board" in +- ubnt-erx) ++ ubnt-erx|\ ++ ubnt-erx-sfp) + nand_do_upgrade "$ARGV" + ;; + *) +diff --git a/target/linux/ramips/dts/UBNT-ER-e50.dtsi b/target/linux/ramips/dts/UBNT-ER-e50.dtsi +new file mode 100644 +index 0000000000000000000000000000000000000000..b38c7194942db9f0a713fd8f707b53820d07c78e +--- /dev/null ++++ b/target/linux/ramips/dts/UBNT-ER-e50.dtsi +@@ -0,0 +1,106 @@ ++#include "mt7621.dtsi" ++ ++#include ++#include ++ ++/ { ++ compatible = "ubiquiti,edgerouterx"; ++ ++ memory@0 { ++ device_type = "memory"; ++ reg = <0x0 0x10000000>; ++ }; ++ ++ chosen { ++ bootargs = "console=ttyS0,57600"; ++ }; ++ ++ gpio-keys-polled { ++ compatible = "gpio-keys-polled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ poll-interval = <20>; ++ ++ reset { ++ label = "reset"; ++ gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; ++ linux,code = ; ++ }; ++ }; ++}; ++ ++ðernet { ++ mtd-mac-address = <&factory 0x22>; ++}; ++ ++&nand { ++ status = "okay"; ++ ++ partition@0 { ++ label = "u-boot"; ++ reg = <0x0 0x80000>; ++ read-only; ++ }; ++ ++ partition@80000 { ++ label = "u-boot-env"; ++ reg = <0x80000 0x60000>; ++ read-only; ++ }; ++ ++ factory: partition@e0000 { ++ label = "factory"; ++ reg = <0xe0000 0x60000>; ++ }; ++ ++ partition@140000 { ++ label = "kernel1"; ++ reg = <0x140000 0x300000>; ++ }; ++ ++ partition@440000 { ++ label = "kernel2"; ++ reg = <0x440000 0x300000>; ++ }; ++ ++ partition@740000 { ++ label = "ubi"; ++ reg = <0x740000 0xf7c0000>; ++ }; ++}; ++ ++&pinctrl { ++ state_default: pinctrl0 { ++ gpio { ++ ralink,group = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag"; ++ ralink,function = "gpio"; ++ }; ++ }; ++}; ++ ++&spi0 { ++ /* This board has 2Mb spi flash soldered in and visible ++ from manufacturer's firmware. ++ But this SoC shares spi and nand pins, ++ and current driver does't handle this sharing well */ ++ status = "disabled"; ++ ++ m25p80@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <1>; ++ spi-max-frequency = <10000000>; ++ m25p,chunked-io = <32>; ++ ++ partition@0 { ++ label = "spi"; ++ reg = <0x0 0x200000>; ++ read-only; ++ }; ++ }; ++}; ++ ++&xhci { ++ status = "disabled"; ++}; +diff --git a/target/linux/ramips/dts/UBNT-ERX-SFP.dts b/target/linux/ramips/dts/UBNT-ERX-SFP.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..ca26d817211e5a5a20a7da926cd2aee726875780 +--- /dev/null ++++ b/target/linux/ramips/dts/UBNT-ERX-SFP.dts +@@ -0,0 +1,24 @@ ++/dts-v1/; ++ ++#include "UBNT-ER-e50.dtsi" ++ ++#include ++ ++/ { ++ model = "UBNT-ERX-SFP"; ++ compatible = "ubiquiti,edgerouterx-sfp"; ++ ++ i2c-gpio { ++ compatible = "i2c-gpio"; ++ gpios = <&gpio0 3 GPIO_ACTIVE_HIGH /* sda */ ++ &gpio0 4 GPIO_ACTIVE_HIGH /* scl */ ++ >; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ pca9555@25 { ++ compatible = "pca9555"; ++ reg = <0x25>; ++ }; ++ }; ++}; +diff --git a/target/linux/ramips/dts/UBNT-ERX.dts b/target/linux/ramips/dts/UBNT-ERX.dts +index cf86bbb7e67b1c521c279367ee9e99fee88fae85..556d1156c352f76a94c6e39bc3b58c88f08815be 100644 +--- a/target/linux/ramips/dts/UBNT-ERX.dts ++++ b/target/linux/ramips/dts/UBNT-ERX.dts +@@ -1,108 +1,7 @@ + /dts-v1/; + +-#include "mt7621.dtsi" +- +-#include +-#include ++#include "UBNT-ER-e50.dtsi" + + / { + model = "UBNT-ERX"; +- +- memory@0 { +- device_type = "memory"; +- reg = <0x0 0x10000000>; +- }; +- +- chosen { +- bootargs = "console=ttyS0,57600"; +- }; +- +- gpio-keys-polled { +- compatible = "gpio-keys-polled"; +- #address-cells = <1>; +- #size-cells = <0>; +- poll-interval = <20>; +- +- reset { +- label = "reset"; +- gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; +- linux,code = ; +- }; +- }; +-}; +- +-ðernet { +- mtd-mac-address = <&factory 0x22>; +-}; +- +-&nand { +- status = "okay"; +- +- partition@0 { +- label = "u-boot"; +- reg = <0x0 0x80000>; +- read-only; +- }; +- +- partition@80000 { +- label = "u-boot-env"; +- reg = <0x80000 0x60000>; +- read-only; +- }; +- +- factory: partition@e0000 { +- label = "factory"; +- reg = <0xe0000 0x60000>; +- }; +- +- partition@140000 { +- label = "kernel1"; +- reg = <0x140000 0x300000>; +- }; +- +- partition@440000 { +- label = "kernel2"; +- reg = <0x440000 0x300000>; +- }; +- +- partition@740000 { +- label = "ubi"; +- reg = <0x740000 0xf7c0000>; +- }; +-}; +- +-&pinctrl { +- state_default: pinctrl0 { +- gpio { +- ralink,group = "uart2", "uart3", "i2c", "pcie", "rgmii2", "jtag"; +- ralink,function = "gpio"; +- }; +- }; +-}; +- +-&spi0 { +- /* This board has 2Mb spi flash soldered in and visible +- from manufacturer's firmware. +- But this SoC shares spi and nand pins, +- and current driver does't handle this sharing well */ +- status = "disabled"; +- +- m25p80@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <1>; +- spi-max-frequency = <10000000>; +- m25p,chunked-io = <32>; +- +- partition@0 { +- label = "spi"; +- reg = <0x0 0x200000>; +- read-only; +- }; +- }; +-}; +- +-&xhci { +- status = "disabled"; + }; +diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk +index 15ea9a13b6310b1454b5b3b92cd8ed30ee6255b3..8218bea84410536151a216cd2cc0300369ad977a 100644 +--- a/target/linux/ramips/image/mt7621.mk ++++ b/target/linux/ramips/image/mt7621.mk +@@ -144,6 +144,19 @@ define Device/ubnt-erx + endef + TARGET_DEVICES += ubnt-erx + ++define Device/ubnt-erx-sfp ++ DTS := UBNT-ERX-SFP ++ FILESYSTEMS := squashfs ++ KERNEL_SIZE := 3145728 ++ KERNEL := $(KERNEL_DTB) | uImage lzma ++ IMAGES := sysupgrade.tar ++ KERNEL_INITRAMFS := $$(KERNEL) | ubnt-erx-factory-image $(KDIR)/tmp/$$(KERNEL_INITRAMFS_PREFIX)-factory.tar ++ IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata ++ DEVICE_TITLE := Ubiquiti EdgeRouter X-SFP ++ DEVICE_PACKAGES := -kmod-mt76 -kmod-rt2x00-lib -kmod-mac80211 -kmod-cfg80211 -wpad-mini -iwinfo kmod-i2c-algo-pca kmod-gpio-pca953x kmod-i2c-gpio-custom ++endef ++TARGET_DEVICES += ubnt-erx-sfp ++ + define Device/vr500 + DTS := VR500 + IMAGE_SIZE := 66453504 diff --git a/patches/lede/0044-ar71xx-add-support-for-TP-Link-TL-WR1043N-v5.patch b/patches/lede/0044-ar71xx-add-support-for-TP-Link-TL-WR1043N-v5.patch new file mode 100644 index 00000000..6c91929e --- /dev/null +++ b/patches/lede/0044-ar71xx-add-support-for-TP-Link-TL-WR1043N-v5.patch @@ -0,0 +1,367 @@ +From: Tim Thorpe +Date: Mon, 25 Sep 2017 04:38:49 -0500 +Subject: ar71xx: add support for TP-Link TL-WR1043N v5 + +TP-Link TL-WR1043N v5 appears to be identical to the TL-WR1043ND v4, +except that the USB port has been removed and there is no longer a +removable antenna option. + +The software is more in line with the Archer series in that it uses a +nested bootloader scheme. + +Specifications: + + - QCA9563 at 775 MHz + - 64 MB RAM + - 16 MB flash + - 3 (non-detachable) Antennas / 450 Mbit + - 1x/4x WAN/LAN Gbps Ethernet (QCA8337) + - reset and Wi-Fi buttons + +Signed-off-by: Tim Thorpe +Signed-off-by: Ludwig Thomeczek + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index e1efb561b33da4dcfcb82ee953cd888170476dfb..e67b5e38561e841b88e486341950c52e1d454322 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -666,14 +666,20 @@ tl-wr1043nd-v2) + ucidef_set_led_usbdev "usb" "USB" "tp-link:green:usb" "1-1" + ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" + ;; ++tl-wr1043n-v5|\ + tl-wr1043nd-v4) +- ucidef_set_led_usbdev "usb" "USB" "tp-link:green:usb" "1-1" + ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" + ucidef_set_led_switch "wan" "WAN" "tp-link:green:wan" "switch0" "0x20" + ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" + ucidef_set_led_switch "lan2" "LAN2" "tp-link:green:lan2" "switch0" "0x08" + ucidef_set_led_switch "lan3" "LAN3" "tp-link:green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "tp-link:green:lan4" "switch0" "0x02" ++ ++ case "$board" in ++ tl-wr1043nd-v4) ++ ucidef_set_led_usbdev "usb" "USB" "tp-link:green:usb" "1-1" ++ ;; ++ esac + ;; + tl-wr2543n) + ucidef_set_led_usbdev "usb" "USB" "tp-link:green:usb" "1-1" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index cefb7413eac6ffc50e67f1eaf63def749314428b..454abe6a5005621967dd96e0282e7bce2a0b127e 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -243,7 +243,8 @@ ar71xx_setup_interfaces() + mynet-n750|\ + sr3200|\ + wndr3700v4|\ +- wndr4300) ++ wndr4300|\ ++ tl-wr1043n-v5) + ucidef_add_switch "switch0" \ + "0@eth0" "1:lan" "2:lan" "3:lan" "4:lan" "5:wan" + ;; +@@ -487,6 +488,7 @@ ar71xx_setup_macs() + lan_mac=$(mtd_get_mac_binary caldata 0) + wan_mac=$(mtd_get_mac_binary caldata 6) + ;; ++ tl-wr1043n-v5|\ + tl-wr1043nd-v4) + lan_mac=$(mtd_get_mac_binary product-info 8) + wan_mac=$(macaddr_add "$lan_mac" 1) +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 38cc5d7853c79f2a7800a387310a95abb3b4de1b..61db387c9ecefd7090c25a5f5d75fdbf65a44d65 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -359,6 +359,7 @@ get_status_led() { + tl-wdr3320-v2|\ + tl-wdr3500|\ + tl-wr1041n-v2|\ ++ tl-wr1043n-v5|\ + tl-wr1043nd|\ + tl-wr1043nd-v2|\ + tl-wr1043nd-v4|\ +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index fc7d862c2911e96f76622cbed23e99863814da63..8f8158bac8a28db4f4f15ce5c37f48a21084dc03 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -947,6 +947,9 @@ ar71xx_board_detect() { + *"TL-WR1043ND v4") + name="tl-wr1043nd-v4" + ;; ++ *"TL-WR1043N v5") ++ name="tl-wr1043n-v5" ++ ;; + *TL-WR2543N*) + name="tl-wr2543n" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 6258713dd0e3325ab109689f0ed3b51e27c41f89..774e3c8964ef724d1efbae56434aeaa9f1c298a4 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -269,6 +269,7 @@ platform_check_image() { + tew-712br|\ + tew-732br|\ + tew-823dru|\ ++ tl-wr1043n-v5|\ + unifi-outdoor|\ + unifiac-lite|\ + unifiac-pro|\ +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index e576fd2ec4f0a8d3613f00aa0a29586b8c65abe0..6da3c323d300705a29355cdccff09fce1ce1bad7 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -181,6 +181,7 @@ CONFIG_ATH79_MACH_TL_WR1041N_V2=y + CONFIG_ATH79_MACH_TL_WR1043ND=y + CONFIG_ATH79_MACH_TL_WR1043ND_V2=y + CONFIG_ATH79_MACH_TL_WR1043ND_V4=y ++CONFIG_ATH79_MACH_TL_WR1043N_V5=y + CONFIG_ATH79_MACH_TL_WR2543N=y + CONFIG_ATH79_MACH_TL_WR703N=y + CONFIG_ATH79_MACH_TL_WR720N_V3=y +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index fb2afb965c4641df7cdcaf0920f2d56b3717fa9b..7ad5419f51ec9909d8b59f33178221a7d81ec184 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1564,6 +1564,15 @@ config ATH79_MACH_TL_WR1041N_V2 + select ATH79_DEV_USB + select ATH79_DEV_WMAC + ++config ATH79_MACH_TL_WR1043N_V5 ++ bool "TP-LINK TL-WR1043N v5 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ + config ATH79_MACH_TL_WR1043ND + bool "TP-LINK TL-WR1043ND support" + select SOC_AR913X +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c +index b1539c5d71a61806b88c50f1a78f6a27d98d7a2d..450819a9e6baa997dab2dfba4c5a19261aae9664 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr1043nd-v4.c +@@ -5,6 +5,7 @@ + * Copyright (C) 2016 Matthias Schiffer + * Copyright (C) 2016 Andreas Ziegler + * Copyright (C) 2016 Ludwig Thomeczek ++ * Copyright (C) 2017 Tim Thorpe + * + * Derived from: mach-dir-869-a1.c + * +@@ -62,6 +63,8 @@ + #define TL_WR1043_V4_EEPROM_ADDR 0x1fff0000 + #define TL_WR1043_V4_WMAC_CALDATA_OFFSET 0x1000 + ++#define TL_WR1043N_V5_MAC_LOCATION 0x1ff00008 ++ + static struct gpio_led tl_wr1043nd_v4_leds_gpio[] __initdata = { + { + .name = "tp-link:green:wps", +@@ -188,3 +191,82 @@ static void __init tl_wr1043nd_v4_setup(void) + + MIPS_MACHINE(ATH79_MACH_TL_WR1043ND_V4, "TL-WR1043ND-v4", + "TP-LINK TL-WR1043ND v4", tl_wr1043nd_v4_setup); ++ ++static struct gpio_led tl_wr1043n_v5_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:wps", ++ .gpio = TL_WR1043_V4_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:system", ++ .gpio = TL_WR1043_V4_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wlan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:wan", ++ .gpio = TL_WR1043_V4_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan1", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan2", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan3", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:green:lan4", ++ .gpio = TL_WR1043_V4_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, ++}; ++ ++/* The 1043Nv5 is identical to the 1043NDv4, ++ * only missing the usb and small firmware layout changes */ ++static void __init tl_wr1043nv5_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(TL_WR1043_V4_EEPROM_ADDR); ++ u8 *mac = (u8 *) KSEG1ADDR(TL_WR1043N_V5_MAC_LOCATION); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr1043n_v5_leds_gpio), ++ tl_wr1043n_v5_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, TL_WR1043_V4_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043nd_v4_gpio_keys), ++ tl_wr1043nd_v4_gpio_keys); ++ ++ platform_device_register(&ath79_mdio0_device); ++ ++ mdiobus_register_board_info(tl_wr1043nd_v4_mdio0_info, ++ ARRAY_SIZE(tl_wr1043nd_v4_mdio0_info)); ++ ++ ath79_register_wmac(art + TL_WR1043_V4_WMAC_CALDATA_OFFSET, mac); ++ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_TL_WR1043N_V5, "TL-WR1043N-v5", "TP-LINK TL-WR1043N v5", ++ tl_wr1043nv5_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 8864e0deda57b926e88dceebd26056a2f8099380..9cb4a7f2e1df641232289721b676a9b0149c76e5 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -214,6 +214,7 @@ enum ath79_mach_type { + ATH79_MACH_TL_WDR6500_V2, /* TP-LINK TL-WDR6500 v2 */ + ATH79_MACH_TL_WPA8630, /* TP-Link TL-WPA8630 */ + ATH79_MACH_TL_WR1041N_V2, /* TP-LINK TL-WR1041N v2 */ ++ ATH79_MACH_TL_WR1043N_V5, /* TP-LINK TL-WR1043N v5 */ + ATH79_MACH_TL_WR1043ND, /* TP-LINK TL-WR1043ND */ + ATH79_MACH_TL_WR1043ND_V2, /* TP-LINK TL-WR1043ND v2 */ + ATH79_MACH_TL_WR1043ND_V4, /* TP-LINK TL-WR1043ND v4 */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 6933654e575a1ef2c92e4c656696a479cba4c594..5be7cbfbd4ab7d73d679d52d2581459250e04302 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -858,7 +858,22 @@ define Device/tl-wr1043nd-v4 + IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory + endef +-TARGET_DEVICES += tl-wr1043nd-v1 tl-wr1043nd-v2 tl-wr1043nd-v3 tl-wr1043nd-v4 ++ ++define Device/tl-wr1043n-v5 ++ DEVICE_TITLE := TP-LINK TL-WR1043N v5 ++ BOARDNAME := TL-WR1043N-v5 ++ SUPPORTED_DEVICES := tl-wr1043n-v5 ++ DEVICE_PROFILE := TLWR1043 ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,128k(u-boot)ro,15104k(firmware),128k(product-info)ro,640k(config)ro,64k(partition-table)ro,128k(logs)ro,64k(art)ro ++ IMAGE_SIZE := 15104k ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade | \ ++ append-metadata | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ TPLINK_BOARD_NAME := TLWR1043NV5 ++endef ++TARGET_DEVICES += tl-wr1043nd-v1 tl-wr1043nd-v2 tl-wr1043nd-v3 tl-wr1043nd-v4 tl-wr1043n-v5 + + define Device/tl-wr2543-v1 + $(Device/tplink-8mlzma) +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index 376835a703f91532300d0dd7c8ef66704acc6e05..f5af38a726f5ce33391223a4dbeb2fc0a8cac613 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -143,6 +143,7 @@ CONFIG_ATH79_MACH_RBSXTLITE=y + # CONFIG_ATH79_MACH_TL_WDR6500_V2 is not set + # CONFIG_ATH79_MACH_TL_WPA8630 is not set + # CONFIG_ATH79_MACH_TL_WR1041N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR1043N_V5 is not set + # CONFIG_ATH79_MACH_TL_WR1043ND is not set + # CONFIG_ATH79_MACH_TL_WR1043ND_V2 is not set + # CONFIG_ATH79_MACH_TL_WR1043ND_V4 is not set +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index 62be218e33cc6366ea89f363983f36523c419650..5c18f5d594d625f91ff10e21ddc5af2b3b4d768f 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -52,6 +52,7 @@ + # CONFIG_ATH79_MACH_TL_WDR3500 is not set + # CONFIG_ATH79_MACH_TL_WDR4300 is not set + # CONFIG_ATH79_MACH_TL_WR1041N_V2 is not set ++# CONFIG_ATH79_MACH_TL_WR1043N_V5 is not set + # CONFIG_ATH79_MACH_TL_WR1043ND is not set + # CONFIG_ATH79_MACH_TL_WR1043ND_V4 is not set + # CONFIG_ATH79_MACH_TL_WR2543N is not set +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 24684268b1a3fe491c4eb876a5ebefc700f2e56e..478d5d8e9b43bbe37694732c138048c8fe8d807c 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -478,6 +478,42 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "file-system" + }, + ++ /** Firmware layout for the TL-WR1043 v5 */ ++ { ++ .id = "TLWR1043NV5", ++ .vendor = "", ++ .support_list = ++ "SupportList:\n" ++ "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:45550000}\n" ++ "{product_name:TL-WR1043N,product_ver:5.0.0,special_id:55530000}\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ .partitions = { ++ {"factory-boot", 0x00000, 0x20000}, ++ {"fs-uboot", 0x20000, 0x20000}, ++ {"os-image", 0x40000, 0x180000}, ++ {"file-system", 0x1c0000, 0xd40000}, ++ {"default-mac", 0xf00000, 0x00200}, ++ {"pin", 0xf00200, 0x00200}, ++ {"device-id", 0xf00400, 0x00100}, ++ {"product-info", 0xf00500, 0x0fb00}, ++ {"soft-version", 0xf10000, 0x01000}, ++ {"extra-para", 0xf11000, 0x01000}, ++ {"support-list", 0xf12000, 0x0a000}, ++ {"profile", 0xf1c000, 0x04000}, ++ {"default-config", 0xf20000, 0x10000}, ++ {"user-config", 0xf30000, 0x40000}, ++ {"qos-db", 0xf70000, 0x40000}, ++ {"certificate", 0xfb0000, 0x10000}, ++ {"partition-table", 0xfc0000, 0x10000}, ++ {"log", 0xfd0000, 0x20000}, ++ {"radio", 0xff0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system" ++ }, ++ + /** Firmware layout for the RE450 */ + { + .id = "RE450", +@@ -888,7 +924,9 @@ static void build_image(const char *output, + parts[3] = read_file("os-image", kernel_image, false); + parts[4] = read_file("file-system", rootfs_image, add_jffs2_eof); + +- if (strcasecmp(info->id, "ARCHER-C25-V1") == 0) { ++ /* Some devices need the extra-para partition to accept the firmware */ ++ if (strcasecmp(info->id, "ARCHER-C25-V1") == 0 || ++ strcasecmp(info->id, "TLWR1043NV5") == 0) { + const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; + parts[5] = put_data("extra-para", mdat, 11); + } diff --git a/patches/lede/0045-ar71xx-add-support-for-TP-LINK-Archer-C7-v4.patch b/patches/lede/0045-ar71xx-add-support-for-TP-LINK-Archer-C7-v4.patch new file mode 100644 index 00000000..d876aa18 --- /dev/null +++ b/patches/lede/0045-ar71xx-add-support-for-TP-LINK-Archer-C7-v4.patch @@ -0,0 +1,533 @@ +From: Felix Fietkau +Date: Tue, 25 Jul 2017 13:32:47 +0200 +Subject: ar71xx: add support for TP-LINK Archer C7 v4 + +TP-Link Archer C7 v4 is a dual-band AC1750 router, based on Qualcomm/Atheros +QCA9561+QCA9888. + +Specification: + +- 775/650/258 MHz (CPU/DDR/AHB) +- 128 MB of RAM (DDR2) +- 16 MB of FLASH (SPI NOR) +- 3T3R 2.4 GHz +- 3T3R 5 GHz +- 5x 10/100/1000 Mbps Ethernet +- 7x LED, 2x button +- UART header on PCB + +Flash instruction: +1. Upload lede-ar71xx-generic-archer-c7-v4-squashfs-factory.bin via Web interface + +Flash instruction using TFTP recovery: +1. Set PC to fixed ip address 192.168.0.66 +2. Download lede-ar71xx-generic-archer-c7-v4-squashfs-factory.bin +and rename it to ArcherC7v4_tp_recovery.bin +3. Start a tftp server with the file tp_recovery.bin in its root directory +4. Turn off the router +5. Press and hold Reset button +6. Turn on router with the reset button pressed and wait ~15 seconds +7. Release the reset button and after a short time +the firmware should be transferred from the tftp server +8. Wait ~30 second to complete recovery. + +Flash instruction under U-Boot, using UART: + +1. tftp 0x81000000 lede-ar71xx-...-sysupgrade.bin +2. erase 0x9f040000 +$filesize +3. cp.b $fileaddr 0x9f040000 $filesize +4. reset + +Signed-off-by: Felix Fietkau + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index e67b5e38561e841b88e486341950c52e1d454322..44b1c2837e8392596eed14b4bc0d761042109715 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -53,7 +53,8 @@ ap121f) + ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" + ;; +-archer-c25-v1) ++archer-c25-v1|\ ++archer-c7-v4) + ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" +@@ -61,6 +62,12 @@ archer-c25-v1) + ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" + ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" ++ case "$board" in ++ archer-c7-v4) ++ ucidef_set_led_usbdev "usb1" "USB1" "$board:green:usb1" "1-1" ++ ucidef_set_led_usbdev "usb2" "USB2" "$board:green:usb2" "2-1" ++ ;; ++ esac + ;; + arduino-yun) + ucidef_set_led_wlan "wlan" "WLAN" "arduino:blue:wlan" "phy0tpt" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 454abe6a5005621967dd96e0282e7bce2a0b127e..86ac949bca12561536ce2c8adb190eb004c162e4 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -386,6 +386,7 @@ ar71xx_setup_interfaces() + ucidef_set_interface_wan "eth0" + ucidef_set_interface_raw "wlan" "wlan0" "dhcp" + ;; ++ archer-c7-v4|\ + tl-wdr4300|\ + tl-wr1041n-v2) + ucidef_add_switch "switch0" \ +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 61db387c9ecefd7090c25a5f5d75fdbf65a44d65..97372bed0ea2fadfab10f22916a1e0d6a9c65725 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -51,6 +51,7 @@ get_status_led() { + status_led="ap135:green:status" + ;; + archer-c25-v1|\ ++ archer-c7-v4|\ + mr12|\ + mr16|\ + nbg6616|\ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index fc9eb005623fc029f839d7ce14788ffba32e42e5..be818b78638b741fff963c222bab7c395996c608 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -98,6 +98,7 @@ case "$FIRMWARE" in + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) + ;; ++ archer-c7-v4|\ + archer-c25-v1|\ + tl-wdr6500-v2) + ath10kcal_extract "art" 20480 2116 +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 8f8158bac8a28db4f4f15ce5c37f48a21084dc03..c32894d95b6b09b4b8b59ba64057c23e71b9f656 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -469,6 +469,9 @@ ar71xx_board_detect() { + *"Archer C5") + name="archer-c5" + ;; ++ *"Archer C7 v4") ++ name="archer-c7-v4" ++ ;; + *"Archer C7") + name="archer-c7" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 774e3c8964ef724d1efbae56434aeaa9f1c298a4..d6650e7719d268e1a500638b7eda2e15b9251aea 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -215,6 +215,7 @@ platform_check_image() { + ap132|\ + ap90q|\ + archer-c25-v1|\ ++ archer-c7-v4|\ + bullet-m|\ + c-55|\ + carambola2|\ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 7ad5419f51ec9909d8b59f33178221a7d81ec184..0a25294c40b5e2d3be825554ec7246a50b9c029b 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1247,6 +1247,7 @@ config ATH79_MACH_ARCHER_C25_V1 + config ATH79_MACH_ARCHER_C7 + bool "TP-LINK Archer C5/C7/TL-WDR4900 v2 board support" + select SOC_QCA955X ++ select SOC_QCA956X + select ATH79_DEV_AP9X_PCI if PCI + select ATH79_DEV_ETH + select ATH79_DEV_GPIO_BUTTONS +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index 3365a43ce16fc77b3212b39b92081efe678e8803..a0c73550eb0d5bf07ee731171be9e5ef9ff073e7 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -58,6 +58,7 @@ obj-$(CONFIG_ATH79_MACH_AP90Q) += mach-ap90q.o + obj-$(CONFIG_ATH79_MACH_AP96) += mach-ap96.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C25_V1) += mach-archer-c25-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7-v4.o + obj-$(CONFIG_ATH79_MACH_ARDUINO_YUN) += mach-arduino-yun.o + obj-$(CONFIG_ATH79_MACH_AW_NR580) += mach-aw-nr580.o + obj-$(CONFIG_ATH79_MACH_BHR_4GRV2) += mach-bhr-4grv2.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +new file mode 100644 +index 0000000000000000000000000000000000000000..64955c79945c0b2c28d5a93be6e45662200e60ed +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +@@ -0,0 +1,260 @@ ++ ++/* ++ * Atheros ARCHER_C7 reference board support ++ * ++ * Copyright (c) 2017 Felix Fietkau ++ * Copyright (c) 2014 The Linux Foundation. All rights reserved. ++ * Copyright (c) 2012 Gabor Juhos ++ * ++ * Permission to use, copy, modify, and/or distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++ ++#define ARCHER_C7_GPIO_SHIFT_OE 1 ++#define ARCHER_C7_GPIO_SHIFT_SER 14 ++#define ARCHER_C7_GPIO_SHIFT_SRCLK 15 ++#define ARCHER_C7_GPIO_SHIFT_RCLK 16 ++#define ARCHER_C7_GPIO_SHIFT_SRCLR 21 ++ ++#define ARCHER_C7_GPIO_BTN_RESET 5 ++#define ARCHER_C7_GPIO_BTN_WPS_WIFI 2 ++ ++#define ARCHER_C7_GPIO_LED_WLAN5 9 ++#define ARCHER_C7_GPIO_LED_POWER 6 ++#define ARCHER_C7_GPIO_LED_USB1 7 ++#define ARCHER_C7_GPIO_LED_USB2 8 ++ ++#define ARCHER_C7_74HC_GPIO_BASE QCA956X_GPIO_COUNT ++#define ARCHER_C7_GPIO_LED_WPS (ARCHER_C7_74HC_GPIO_BASE + 0) ++#define ARCHER_C7_GPIO_LED_LAN1 (ARCHER_C7_74HC_GPIO_BASE + 1) ++#define ARCHER_C7_GPIO_LED_LAN2 (ARCHER_C7_74HC_GPIO_BASE + 2) ++#define ARCHER_C7_GPIO_LED_LAN3 (ARCHER_C7_74HC_GPIO_BASE + 3) ++#define ARCHER_C7_GPIO_LED_LAN4 (ARCHER_C7_74HC_GPIO_BASE + 4) ++#define ARCHER_C7_GPIO_LED_WAN_GREEN (ARCHER_C7_74HC_GPIO_BASE + 5) ++#define ARCHER_C7_GPIO_LED_WAN_AMBER (ARCHER_C7_74HC_GPIO_BASE + 6) ++#define ARCHER_C7_GPIO_LED_WLAN2 (ARCHER_C7_74HC_GPIO_BASE + 7) ++ ++#define ARCHER_C7_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define ARCHER_C7_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C7_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C7_MAC0_OFFSET 0 ++#define ARCHER_C7_MAC1_OFFSET 6 ++#define ARCHER_C7_WMAC_CALDATA_OFFSET 0x1000 ++ ++#define ARCHER_C7_GPIO_MDC 3 ++#define ARCHER_C7_GPIO_MDIO 4 ++ ++static struct spi_gpio_platform_data archer_c7_v4_spi_data = { ++ .sck = ARCHER_C7_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C7_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c7_v4_ssr_initdata __initdata = 0xff; ++ ++static struct gen_74x164_chip_platform_data archer_c7_v4_ssr_data = { ++ .base = ARCHER_C7_74HC_GPIO_BASE, ++ .num_registers = 1, ++ .init_data = &archer_c7_v4_ssr_initdata, ++}; ++ ++static struct platform_device archer_c7_v4_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c7_v4_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c7_v4_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c7_v4_ssr_data, ++ .controller_data = (void *) ARCHER_C7_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static struct gpio_led archer_c7_v4_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c7-v4:green:power", ++ .gpio = ARCHER_C7_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wps", ++ .gpio = ARCHER_C7_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wlan2g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wlan5g", ++ .gpio = ARCHER_C7_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan1", ++ .gpio = ARCHER_C7_GPIO_LED_LAN1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan2", ++ .gpio = ARCHER_C7_GPIO_LED_LAN2, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan3", ++ .gpio = ARCHER_C7_GPIO_LED_LAN3, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:lan4", ++ .gpio = ARCHER_C7_GPIO_LED_LAN4, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:amber:wan", ++ .gpio = ARCHER_C7_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:usb1", ++ .gpio = ARCHER_C7_GPIO_LED_USB1, ++ .active_low = 1, ++ }, { ++ .name = "archer-c7-v4:green:usb2", ++ .gpio = ARCHER_C7_GPIO_LED_USB2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c7_v4_gpio_keys[] __initdata = { ++ { ++ .desc = "WPS and WIFI button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_WPS_WIFI, ++ .active_low = 1, ++ }, ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C7_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C7_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++}; ++ ++static struct ar8327_pad_cfg archer_c7_v4_ar8337_pad0_cfg = { ++ .mode = AR8327_PAD_MAC_SGMII, ++ .sgmii_delay_en = true, ++}; ++ ++static struct ar8327_platform_data archer_c7_v4_ar8337_data = { ++ .pad0_cfg = &archer_c7_v4_ar8337_pad0_cfg, ++ .port0_cfg = { ++ .force_link = 1, ++ .speed = AR8327_PORT_SPEED_1000, ++ .duplex = 1, ++ .txpause = 1, ++ .rxpause = 1, ++ }, ++}; ++ ++static struct mdio_board_info archer_c7_v4_mdio0_info[] = { ++ { ++ .bus_id = "ag71xx-mdio.0", ++ .phy_addr = 0, ++ .platform_data = &archer_c7_v4_ar8337_data, ++ }, ++}; ++ ++ ++static void __init archer_c7_v4_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *mac = (u8 *) KSEG1ADDR(0x1ff00008); ++ ++ ath79_register_m25p80(NULL); ++ ++ spi_register_board_info(archer_c7_v4_spi_info, ++ ARRAY_SIZE(archer_c7_v4_spi_info)); ++ ++ platform_device_register(&archer_c7_v4_spi_device); ++ ++ gpio_request_one(ARCHER_C7_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ ++ gpio_request_one(ARCHER_C7_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c7_v4_leds_gpio), ++ archer_c7_v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C7_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c7_v4_gpio_keys), ++ archer_c7_v4_gpio_keys); ++ ++ ath79_register_usb(); ++ ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDC, QCA956X_GPIO_OUT_MUX_GE0_MDC); ++ ath79_gpio_output_select(ARCHER_C7_GPIO_MDIO, QCA956X_GPIO_OUT_MUX_GE0_MDO); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ mdiobus_register_board_info(archer_c7_v4_mdio0_info, ++ ARRAY_SIZE(archer_c7_v4_mdio0_info)); ++ ++ ath79_register_wmac(art + ARCHER_C7_WMAC_CALDATA_OFFSET, mac); ++ ath79_register_pci(); ++ ++ /* GMAC0 is connected to an AR8337 switch */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; ++ ath79_eth0_data.speed = SPEED_1000; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; ++ ath79_register_eth(0); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C7_V4, "ARCHER-C7-V4", "TP-LINK Archer C7 v4", ++ archer_c7_v4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 9cb4a7f2e1df641232289721b676a9b0149c76e5..e4623fd08836d59ad4e79e96f02e75e502a55ca6 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -44,6 +44,7 @@ enum ath79_mach_type { + ATH79_MACH_ARCHER_C5, /* TP-LINK Archer C5 board */ + ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */ + ATH79_MACH_ARCHER_C7_V2, /* TP-LINK Archer C7 V2 board */ ++ ATH79_MACH_ARCHER_C7_V4, /* TP-LINK Archer C7 V4 board */ + ATH79_MACH_ARDUINO_YUN, /* Yun */ + ATH79_MACH_AW_NR580, /* AzureWave AW-NR580 */ + ATH79_MACH_BHR_4GRV2, /* Buffalo BHR-4GRV2 */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 5be7cbfbd4ab7d73d679d52d2581459250e04302..27d6c73454aef96e5da47033ec664d2caffca1d5 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -298,6 +298,22 @@ define Device/archer-c7-v2 + IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU + endef + ++define Device/archer-c7-v4 ++ DEVICE_TITLE := TP-LINK Archer C7 v4 ++ DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca988x ++ BOARDNAME := ARCHER-C7-V4 ++ TPLINK_BOARD_NAME := ARCHER-C7-V4 ++ IMAGE_SIZE := 15104k ++ LOADER_TYPE := elf ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade | \ ++ append-metadata | check-size $$$$(IMAGE_SIZE) ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ MTDPARTS := spi0.0:128k(factory-uboot)ro,128k(u-boot)ro,1536k(kernel),13568k(rootfs),960k(config)ro,64k(art)ro,15104k@0x40000(firmware) ++ SUPPORTED_DEVICES := archer-c7-v4 ++endef ++ + define Device/archer-c7-v2-il + $(Device/tplink-16mlzma) + DEVICE_TITLE := TP-LINK Archer C7 v2 IL +@@ -316,7 +332,7 @@ define Device/tl-wdr7500-v3 + DEVICE_PROFILE := ARCHERC7 + TPLINK_HWID := 0x75000003 + endef +-TARGET_DEVICES += archer-c5-v1 archer-c7-v1 archer-c7-v2 archer-c7-v2-il tl-wdr7500-v3 ++TARGET_DEVICES += archer-c5-v1 archer-c7-v1 archer-c7-v2 archer-c7-v2-il archer-c7-v4 tl-wdr7500-v3 + + define Device/tl-mr10u-v1 + $(Device/tplink-4mlzma) +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 478d5d8e9b43bbe37694732c138048c8fe8d807c..fec830c23ce6707755ddefc849f195872be1e877 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -376,6 +376,49 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "file-system" + }, + ++ /** Firmware layout for the C7 */ ++ { ++ .id = "ARCHER-C7-V4", ++ .support_list = ++ "SupportList:\n" ++ "{product_name:Archer C7,product_ver:4.0.0,special_id:45550000}\n" ++ "{product_name:Archer C7,product_ver:4.0.0,special_id:55530000}\n" ++ "{product_name:Archer C7,product_ver:4.0.0,special_id:43410000}\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ ++ /** ++ We use a bigger os-image partition than the stock images (and thus ++ smaller file-system), as our kernel doesn't fit in the stock firmware's ++ 1MB os-image. ++ */ ++ .partitions = { ++ {"factory-boot", 0x00000, 0x20000}, ++ {"fs-uboot", 0x20000, 0x20000}, ++ {"os-image", 0x40000, 0x180000}, /* Stock: base 0x40000 size 0x120000 */ ++ {"file-system", 0x1c0000, 0xd40000}, /* Stock: base 0x160000 size 0xda0000 */ ++ {"default-mac", 0xf00000, 0x00200}, ++ {"pin", 0xf00200, 0x00200}, ++ {"device-id", 0xf00400, 0x00100}, ++ {"product-info", 0xf00500, 0x0fb00}, ++ {"soft-version", 0xf10000, 0x00100}, ++ {"extra-para", 0xf11000, 0x01000}, ++ {"support-list", 0xf12000, 0x0a000}, ++ {"profile", 0xf1c000, 0x04000}, ++ {"default-config", 0xf20000, 0x10000}, ++ {"user-config", 0xf30000, 0x40000}, ++ {"qos-db", 0xf70000, 0x40000}, ++ {"certificate", 0xfb0000, 0x10000}, ++ {"partition-table", 0xfc0000, 0x10000}, ++ {"log", 0xfd0000, 0x20000}, ++ {"radio", 0xff0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system", ++ }, ++ + /** Firmware layout for the C9 */ + { + .id = "ARCHERC9", +@@ -929,6 +972,9 @@ static void build_image(const char *output, + strcasecmp(info->id, "TLWR1043NV5") == 0) { + const char mdat[11] = {0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; + parts[5] = put_data("extra-para", mdat, 11); ++ } else if (strcasecmp(info->id, "ARCHER-C7-V4") == 0) { ++ const char mdat[11] = {0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x01, 0x00, 0x00}; ++ parts[5] = put_data("extra-para", mdat, 11); + } + + size_t len; diff --git a/patches/lede/0046-ar71xx-fix-TP-Link-Archer-C7-v4-switch-LEDs.patch b/patches/lede/0046-ar71xx-fix-TP-Link-Archer-C7-v4-switch-LEDs.patch new file mode 100644 index 00000000..cad39e97 --- /dev/null +++ b/patches/lede/0046-ar71xx-fix-TP-Link-Archer-C7-v4-switch-LEDs.patch @@ -0,0 +1,72 @@ +From: David Bauer +Date: Sat, 16 Dec 2017 15:43:02 +0100 +Subject: ar71xx: fix TP-Link Archer C7 v4 switch LEDs + +This fixes wrong switch LEDs on TP-Link Archer C7 v4. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 44b1c2837e8392596eed14b4bc0d761042109715..47b90d9cb2f81936aed22cdf7d1f6d870d23c16e 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -53,8 +53,7 @@ ap121f) + ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" + ;; +-archer-c25-v1|\ +-archer-c7-v4) ++archer-c25-v1) + ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" +@@ -62,12 +61,6 @@ archer-c7-v4) + ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" + ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" +- case "$board" in +- archer-c7-v4) +- ucidef_set_led_usbdev "usb1" "USB1" "$board:green:usb1" "1-1" +- ucidef_set_led_usbdev "usb2" "USB2" "$board:green:usb2" "2-1" +- ;; +- esac + ;; + arduino-yun) + ucidef_set_led_wlan "wlan" "WLAN" "arduino:blue:wlan" "phy0tpt" +@@ -635,6 +628,17 @@ archer-c7) + ucidef_set_led_wlan "wlan2g" "WLAN2G" "tp-link:blue:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "tp-link:blue:wlan5g" "phy0tpt" + ;; ++archer-c7-v4) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ucidef_set_led_switch "wan" "WAN" "$board:green:wan" "switch0" "0x02" ++ ucidef_set_led_switch "lan1" "LAN1" "$board:green:lan1" "switch0" "0x04" ++ ucidef_set_led_switch "lan2" "LAN2" "$board:green:lan2" "switch0" "0x08" ++ ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x10" ++ ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x20" ++ ucidef_set_led_usbdev "usb1" "USB1" "$board:green:usb1" "1-1" ++ ucidef_set_led_usbdev "usb2" "USB2" "$board:green:usb2" "2-1" ++ ;; + tl-wpa8630) + ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth0" + ucidef_set_led_netdev "wlan" "WLAN" "$board:green:wlan" "wlan1" +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +index 64955c79945c0b2c28d5a93be6e45662200e60ed..9688b015356cb766c5966be2190e1aae29420d8d 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c7-v4.c +@@ -58,10 +58,10 @@ + + #define ARCHER_C7_74HC_GPIO_BASE QCA956X_GPIO_COUNT + #define ARCHER_C7_GPIO_LED_WPS (ARCHER_C7_74HC_GPIO_BASE + 0) +-#define ARCHER_C7_GPIO_LED_LAN1 (ARCHER_C7_74HC_GPIO_BASE + 1) +-#define ARCHER_C7_GPIO_LED_LAN2 (ARCHER_C7_74HC_GPIO_BASE + 2) +-#define ARCHER_C7_GPIO_LED_LAN3 (ARCHER_C7_74HC_GPIO_BASE + 3) +-#define ARCHER_C7_GPIO_LED_LAN4 (ARCHER_C7_74HC_GPIO_BASE + 4) ++#define ARCHER_C7_GPIO_LED_LAN4 (ARCHER_C7_74HC_GPIO_BASE + 1) ++#define ARCHER_C7_GPIO_LED_LAN3 (ARCHER_C7_74HC_GPIO_BASE + 2) ++#define ARCHER_C7_GPIO_LED_LAN2 (ARCHER_C7_74HC_GPIO_BASE + 3) ++#define ARCHER_C7_GPIO_LED_LAN1 (ARCHER_C7_74HC_GPIO_BASE + 4) + #define ARCHER_C7_GPIO_LED_WAN_GREEN (ARCHER_C7_74HC_GPIO_BASE + 5) + #define ARCHER_C7_GPIO_LED_WAN_AMBER (ARCHER_C7_74HC_GPIO_BASE + 6) + #define ARCHER_C7_GPIO_LED_WLAN2 (ARCHER_C7_74HC_GPIO_BASE + 7) diff --git a/patches/lede/0047-ar71xx-fix-Archer-C7-5GHz-MAC-address.patch b/patches/lede/0047-ar71xx-fix-Archer-C7-5GHz-MAC-address.patch new file mode 100644 index 00000000..39c9e18f --- /dev/null +++ b/patches/lede/0047-ar71xx-fix-Archer-C7-5GHz-MAC-address.patch @@ -0,0 +1,36 @@ +From: David Bauer +Date: Tue, 19 Dec 2017 02:32:47 +0100 +Subject: ar71xx: fix Archer C7 5GHz MAC-address + +The TP-Link firmware uses (primary_mac-1) as MAC-address +for the 5GHz WiFi. This applies the same behaviour to LEDE. + +Currently, the MAC-address is retrieved from eth1, which +does not exist on the Archer C7 v4. As a result from this, +every C7 v4 with LEDE carries the same MAC-Address on the 5GHz WiFi. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index be818b78638b741fff963c222bab7c395996c608..697fcb68d246aa445ce029440643ad5950e48f6d 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -53,6 +53,10 @@ board=$(ar71xx_board_name) + case "$FIRMWARE" in + "ath10k/cal-pci-0000:00:00.0.bin") + case $board in ++ archer-c7-v4) ++ ath10kcal_extract "art" 20480 2116 ++ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -1) ++ ;; + cf-e380ac-v1|\ + cf-e380ac-v2|\ + dlan-pro-1200-ac|\ +@@ -98,7 +102,6 @@ case "$FIRMWARE" in + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) + ;; +- archer-c7-v4|\ + archer-c25-v1|\ + tl-wdr6500-v2) + ath10kcal_extract "art" 20480 2116 diff --git a/patches/lede/0048-ebtables-Use-flock-for-concurrent-option.patch b/patches/lede/0048-ebtables-Use-flock-for-concurrent-option.patch new file mode 100644 index 00000000..e95dd2ff --- /dev/null +++ b/patches/lede/0048-ebtables-Use-flock-for-concurrent-option.patch @@ -0,0 +1,146 @@ +From: Sven Eckelmann +Date: Wed, 20 Dec 2017 16:55:17 +0100 +Subject: ebtables: Use flock() for --concurrent option + +The previous locking mechanism was not atomic, hence it was possible +that a killed ebtables process would leave the lock file in place which +in turn made future ebtables processes wait indefinitely for the lock to +become free. + +Fix this by using flock(). This also simplifies code quite a bit because +there is no need for a custom signal handler or an __exit routine +anymore. + +diff --git a/package/network/utils/ebtables/patches/300-fix-concurrent.patch b/package/network/utils/ebtables/patches/300-fix-concurrent.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..1a99162bf51cd175e26d49e7ee5277b8b8645f48 +--- /dev/null ++++ b/package/network/utils/ebtables/patches/300-fix-concurrent.patch +@@ -0,0 +1,127 @@ ++From 6a826591878db3fa9e2a94b87a3d5edd8e0fc442 Mon Sep 17 00:00:00 2001 ++From: Phil Sutter ++Date: Fri, 6 Oct 2017 12:48:50 +0200 ++Subject: Use flock() for --concurrent option ++ ++The previous locking mechanism was not atomic, hence it was possible ++that a killed ebtables process would leave the lock file in place which ++in turn made future ebtables processes wait indefinitely for the lock to ++become free. ++ ++Fix this by using flock(). This also simplifies code quite a bit because ++there is no need for a custom signal handler or an __exit routine ++anymore. ++ ++Signed-off-by: Phil Sutter ++Signed-off-by: Pablo Neira Ayuso ++ ++Origin: upstream, https://git.netfilter.org/ebtables/commit/?id=6a826591878db3fa9e2a94b87a3d5edd8e0fc442 ++--- ++ ebtables.c | 8 -------- ++ libebtc.c | 49 +++++-------------------------------------------- ++ 2 files changed, 5 insertions(+), 52 deletions(-) ++ ++diff --git a/ebtables.c b/ebtables.c ++index 62f1ba8..f7dfccf 100644 ++--- a/ebtables.c +++++ b/ebtables.c ++@@ -528,12 +528,6 @@ void ebt_early_init_once() ++ ebt_iterate_targets(merge_target); ++ } ++ ++-/* signal handler, installed when the option --concurrent is specified. */ ++-static void sighandler(int signum) ++-{ ++- exit(-1); ++-} ++- ++ /* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */ ++ int do_command(int argc, char *argv[], int exec_style, ++ struct ebt_u_replace *replace_) ++@@ -1047,8 +1041,6 @@ big_iface_length: ++ strcpy(replace->filename, optarg); ++ break; ++ case 13 : /* concurrent */ ++- signal(SIGINT, sighandler); ++- signal(SIGTERM, sighandler); ++ use_lockfd = 1; ++ break; ++ case 1 : ++diff --git a/libebtc.c b/libebtc.c ++index 74830ec..c0ff8cc 100644 ++--- a/libebtc.c +++++ b/libebtc.c ++@@ -31,6 +31,7 @@ ++ #include "include/ethernetdb.h" ++ #include ++ #include +++#include ++ #include ++ #include ++ #include ++@@ -137,58 +138,18 @@ void ebt_list_extensions() ++ #define LOCKDIR "/var/lib/ebtables" ++ #define LOCKFILE LOCKDIR"/lock" ++ #endif ++-static int lockfd = -1, locked; ++ int use_lockfd; ++ /* Returns 0 on success, -1 when the file is locked by another process ++ * or -2 on any other error. */ ++ static int lock_file() ++ { ++- int try = 0; ++- int ret = 0; ++- sigset_t sigset; ++- ++-tryagain: ++- /* the SIGINT handler will call unlock_file. To make sure the state ++- * of the variable locked is correct, we need to temporarily mask the ++- * SIGINT interrupt. */ ++- sigemptyset(&sigset); ++- sigaddset(&sigset, SIGINT); ++- sigprocmask(SIG_BLOCK, &sigset, NULL); ++- lockfd = open(LOCKFILE, O_CREAT | O_EXCL | O_WRONLY, 00600); ++- if (lockfd < 0) { ++- if (errno == EEXIST) ++- ret = -1; ++- else if (try == 1) ++- ret = -2; ++- else { ++- if (mkdir(LOCKDIR, 00700)) ++- ret = -2; ++- else { ++- try = 1; ++- goto tryagain; ++- } ++- } ++- } else { ++- close(lockfd); ++- locked = 1; ++- } ++- sigprocmask(SIG_UNBLOCK, &sigset, NULL); ++- return ret; ++-} +++ int fd = open(LOCKFILE, O_CREAT, 00600); ++ ++-void unlock_file() ++-{ ++- if (locked) { ++- remove(LOCKFILE); ++- locked = 0; ++- } +++ if (fd < 0) +++ return -2; +++ return flock(fd, LOCK_EX); ++ } ++ ++-void __attribute__ ((destructor)) onexit() ++-{ ++- if (use_lockfd) ++- unlock_file(); ++-} ++ /* Get the table from the kernel or from a binary file ++ * init: 1 = ask the kernel for the initial contents of a table, i.e. the ++ * way it looks when the table is insmod'ed ++-- ++cgit v1.1 ++ diff --git a/patches/lede/0049-ar71xx-add-support-to-TP-Link-Archer-C59v1-and-C60v1.patch b/patches/lede/0049-ar71xx-add-support-to-TP-Link-Archer-C59v1-and-C60v1.patch new file mode 100644 index 00000000..a31ef5b8 --- /dev/null +++ b/patches/lede/0049-ar71xx-add-support-to-TP-Link-Archer-C59v1-and-C60v1.patch @@ -0,0 +1,757 @@ +From: Henryk Heisig +Date: Tue, 27 Dec 2016 22:41:41 +0100 +Subject: ar71xx: add support to TP-Link Archer C59v1 and C60v1 + +TP-Link Archer C59v1 is a dual-band AC1350 router, based on Qualcomm/Atheros +QCA9561+QCA9886. + +Specification: + +- 775/650/258 MHz (CPU/DDR/AHB) +- 128 MB of RAM (DDR2) +- 16 MB of FLASH (SPI NOR) +- 3T3R 2.4 GHz +- 2T2R 5 GHz +- 5x 10/100 Mbps Ethernet +- USB 2.0 port +- 8x LED (controled by 74HC595), 3x button +- UART header on PCB + +TP-Link Archer C60v1 is a dual-band AC1350 router, based on Qualcomm/Atheros +QCA9561+QCA9886. + +Specification: + +- 775/650/258 MHz (CPU/DDR/AHB) +- 64 MB of RAM (DDR2) +- 8 MB of FLASH (SPI NOR) +- 3T3R 2.4 GHz +- 2T2R 5 GHz +- 5x 10/100 Mbps Ethernet +- 7x LED, 2x button +- UART header on PCB + +Currently not working: +- Port LAN1 on C59, LAN4 on C60 +- WiFi 5GHz (missing ath10k firmware for QCA9886 chip) +- Update from oficial web interface ( tplink-saveloader not support "product-info") + +Flash instruction: +1. Set PC to fixed ip address 192.168.0.66 +2. Download lede-ar71xx-generic-archer-cXX-v1-squashfs-factory.bin +and rename it to tp_recovery.bin +3. Start a tftp server with the file tp_recovery.bin in its root directory +4. Turn off the router +5. Press and hold Reset button +6. Turn on router with the reset button pressed and wait ~15 seconds +7. Release the reset button and after a short time +the firmware should be transferred from the tftp server +8. Wait ~30 second to complete recovery. + +Flash instruction under U-Boot, using UART: + +1. tftp 0x81000000 lede-ar71xx-...-sysupgrade.bin +2. erase 0x9f020000 +$filesize +3. cp.b $fileaddr 0x9f020000 $filesize +4. reset + +Signed-off-by: Henryk Heisig +[Jo-Philipp Wich: remove duplicate ATH79_MACH_ARCHER_C59/C60_V1 entries] +Signed-off-by: Jo-Philipp Wich + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 47b90d9cb2f81936aed22cdf7d1f6d870d23c16e..8552cde564b3fbed9425f42d5331f95fe5c3aaa8 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -62,6 +62,19 @@ archer-c25-v1) + ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" + ;; ++archer-c59-v1|\ ++archer-c60-v1) ++ ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x3C" ++ ucidef_set_led_switch "wan" "WAN" "$board:green:wan" "switch0" "0x02" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" ++ ++ case "$board" in ++ archer-c59-v1) ++ ucidef_set_led_usbdev "usb" "USB" "$board:green:usb" "1-1" ++ ;; ++ esac ++ ;; + arduino-yun) + ucidef_set_led_wlan "wlan" "WLAN" "arduino:blue:wlan" "phy0tpt" + ucidef_set_led_usbdev "usb" "USB" "arduino:white:usb" "1-1.1" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 86ac949bca12561536ce2c8adb190eb004c162e4..3abe1114ee31c79abb125b85119876c3d75bb7c0 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -205,6 +205,11 @@ ar71xx_setup_interfaces() + ucidef_add_switch "switch0" \ + "0@eth1" "2:lan" "3:lan" "4:lan" "5:lan" "6@eth0" "1:wan" + ;; ++ archer-c59-v1|\ ++ archer-c60-v1) ++ ucidef_add_switch "switch0" \ ++ "0@eth0" "2:lan:4" "3:lan:3" "4:lan:2" "5:lan:1" "1:wan" ++ ;; + arduino-yun|\ + dir-505-a1|\ + tl-wa801nd-v3) +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 97372bed0ea2fadfab10f22916a1e0d6a9c65725..3aa1f054d4f791545a8b6644f7bd24f64ed546a3 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -52,6 +52,8 @@ get_status_led() { + ;; + archer-c25-v1|\ + archer-c7-v4|\ ++ archer-c59-v1|\ ++ archer-c60-v1|\ + mr12|\ + mr16|\ + nbg6616|\ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 697fcb68d246aa445ce029440643ad5950e48f6d..6c62f391e1aac2f052d3397fc25f8bddcca581dd 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -103,6 +103,8 @@ case "$FIRMWARE" in + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) -2) + ;; + archer-c25-v1|\ ++ archer-c59-v1|\ ++ archer-c60-v1|\ + tl-wdr6500-v2) + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -2) +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index c32894d95b6b09b4b8b59ba64057c23e71b9f656..d8e23d97e2cc20f8ba7b3b2fc516ce398c43a19b 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -472,6 +472,12 @@ ar71xx_board_detect() { + *"Archer C7 v4") + name="archer-c7-v4" + ;; ++ *"Archer C59 v1") ++ name="archer-c59-v1" ++ ;; ++ *"Archer C60 v1") ++ name="archer-c60-v1" ++ ;; + *"Archer C7") + name="archer-c7" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index d6650e7719d268e1a500638b7eda2e15b9251aea..f4ac73e40e1acb800433a0b1348c8264a4639c30 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -216,6 +216,8 @@ platform_check_image() { + ap90q|\ + archer-c25-v1|\ + archer-c7-v4|\ ++ archer-c59-v1|\ ++ archer-c60-v1|\ + bullet-m|\ + c-55|\ + carambola2|\ +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index 6da3c323d300705a29355cdccff09fce1ce1bad7..e335ef9b7dfe8f0250b4362542ea2518eac34cb4 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -52,6 +52,8 @@ CONFIG_ATH79_MACH_AP152=y + CONFIG_ATH79_MACH_AP90Q=y + CONFIG_ATH79_MACH_AP96=y + CONFIG_ATH79_MACH_ARCHER_C25_V1=y ++CONFIG_ATH79_MACH_ARCHER_C59_V1=y ++CONFIG_ATH79_MACH_ARCHER_C60_V1=y + CONFIG_ATH79_MACH_ARCHER_C7=y + CONFIG_ATH79_MACH_ARDUINO_YUN=y + CONFIG_ATH79_MACH_AW_NR580=y +@@ -273,6 +275,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y + CONFIG_GENERIC_TIME_VSYSCALL=y + CONFIG_GPIOLIB=y + CONFIG_GPIOLIB_IRQCHIP=y ++CONFIG_GPIO_74X164=y + CONFIG_GPIO_DEVRES=y + CONFIG_GPIO_74X164=y + # CONFIG_GPIO_LATCH is not set +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 0a25294c40b5e2d3be825554ec7246a50b9c029b..468d9b333e43814cbadec8d85a20ab94e5cd6d01 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1244,6 +1244,27 @@ config ATH79_MACH_ARCHER_C25_V1 + select ATH79_DEV_M25P80 + select ATH79_DEV_WMAC + ++config ATH79_MACH_ARCHER_C59_V1 ++ bool "TP-LINK Archer C59 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ ++config ATH79_MACH_ARCHER_C60_V1 ++ bool "TP-LINK Archer C60 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ + config ATH79_MACH_ARCHER_C7 + bool "TP-LINK Archer C5/C7/TL-WDR4900 v2 board support" + select SOC_QCA955X +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index a0c73550eb0d5bf07ee731171be9e5ef9ff073e7..fbe7fcb0aebb6577b96c27088a158eb025f201cb 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -57,6 +57,8 @@ obj-$(CONFIG_ATH79_MACH_AP152) += mach-ap152.o + obj-$(CONFIG_ATH79_MACH_AP90Q) += mach-ap90q.o + obj-$(CONFIG_ATH79_MACH_AP96) += mach-ap96.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C25_V1) += mach-archer-c25-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C59_V1) += mach-archer-c59-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C60_V1) += mach-archer-c60-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7-v4.o + obj-$(CONFIG_ATH79_MACH_ARDUINO_YUN) += mach-arduino-yun.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +new file mode 100644 +index 0000000000000000000000000000000000000000..28353aa77b05078b895ab48cf6b1ae53abe98ce2 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +@@ -0,0 +1,223 @@ ++/* ++ * TP-Link Archer C59 v1 board support ++ * ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define ARCHER_C59_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C59_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C59_V1_GPIO_BTN_RESET 21 ++#define ARCHER_C59_V1_GPIO_BTN_RFKILL 2 ++#define ARCHER_C59_V1_GPIO_BTN_WPS 1 ++ ++#define ARCHER_C59_V1_GPIO_USB_POWER 22 ++ ++#define ARCHER_C59_GPIO_SHIFT_OE 16 ++#define ARCHER_C59_GPIO_SHIFT_SER 17 ++#define ARCHER_C59_GPIO_SHIFT_SRCLK 18 ++#define ARCHER_C59_GPIO_SHIFT_SRCLR 19 ++#define ARCHER_C59_GPIO_SHIFT_RCLK 20 ++ ++#define ARCHER_C59_74HC_GPIO_BASE QCA956X_GPIO_COUNT ++#define ARCHER_C59_74HC_GPIO_LED_POWER 23 ++#define ARCHER_C59_74HC_GPIO_LED_WLAN2 24 ++#define ARCHER_C59_74HC_GPIO_LED_WLAN5 25 ++#define ARCHER_C59_74HC_GPIO_LED_LAN 26 ++#define ARCHER_C59_74HC_GPIO_LED_WAN_GREEN 27 ++#define ARCHER_C59_74HC_GPIO_LED_WAN_AMBER 28 ++#define ARCHER_C59_74HC_GPIO_LED_WPS 29 ++#define ARCHER_C59_74HC_GPIO_LED_USB 30 ++ ++#define ARCHER_C59_V1_SSR_BIT_0 0 ++#define ARCHER_C59_V1_SSR_BIT_1 1 ++#define ARCHER_C59_V1_SSR_BIT_2 2 ++#define ARCHER_C59_V1_SSR_BIT_3 3 ++#define ARCHER_C59_V1_SSR_BIT_4 4 ++#define ARCHER_C59_V1_SSR_BIT_5 5 ++#define ARCHER_C59_V1_SSR_BIT_6 6 ++#define ARCHER_C59_V1_SSR_BIT_7 7 ++ ++#define ARCHER_C59_V1_WMAC_CALDATA_OFFSET 0x1000 ++#define ARCHER_C59_V1_PCI_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led archer_c59_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c59-v1:green:power", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wlan2g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wlan5g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:lan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:amber:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:wps", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c59-v1:green:usb", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_USB, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c59_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = ARCHER_C59_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C59_V1_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct spi_gpio_platform_data archer_c59_v1_spi_data = { ++ .sck = ARCHER_C59_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = ARCHER_C59_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 archer_c59_v1_ssr_initdata[] __initdata = { ++ BIT(ARCHER_C59_V1_SSR_BIT_7) | ++ BIT(ARCHER_C59_V1_SSR_BIT_6) | ++ BIT(ARCHER_C59_V1_SSR_BIT_5) | ++ BIT(ARCHER_C59_V1_SSR_BIT_4) | ++ BIT(ARCHER_C59_V1_SSR_BIT_3) | ++ BIT(ARCHER_C59_V1_SSR_BIT_2) | ++ BIT(ARCHER_C59_V1_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data archer_c59_v1_ssr_data = { ++ .base = ARCHER_C59_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(archer_c59_v1_ssr_initdata), ++ .init_data = archer_c59_v1_ssr_initdata, ++}; ++ ++static struct platform_device archer_c59_v1_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &archer_c59_v1_spi_data, ++ }, ++}; ++ ++static struct spi_board_info archer_c59_v1_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &archer_c59_v1_ssr_data, ++ .controller_data = (void *) ARCHER_C59_GPIO_SHIFT_RCLK, ++ }, ++}; ++ ++static void __init archer_c59_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f010008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ath79_register_m25p80(NULL); ++ spi_register_board_info(archer_c59_v1_spi_info, ++ ARRAY_SIZE(archer_c59_v1_spi_info)); ++ platform_device_register(&archer_c59_v1_spi_device); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c59_v1_leds_gpio), ++ archer_c59_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C59_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c59_v1_gpio_keys), ++ archer_c59_v1_gpio_keys); ++ ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_mask = BIT(4); ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C59_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(art + ARCHER_C59_V1_PCI_CALDATA_OFFSET, NULL); ++ ++ ++ ath79_register_usb(); ++ gpio_request_one(ARCHER_C59_V1_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ gpio_request_one(ARCHER_C59_GPIO_SHIFT_OE, ++ GPIOF_OUT_INIT_LOW | GPIOF_EXPORT_DIR_FIXED, ++ "LED control"); ++ gpio_request_one(ARCHER_C59_GPIO_SHIFT_SRCLR, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "LED reset"); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C59_V1, "ARCHER-C59-V1", ++ "TP-LINK Archer C59 v1", archer_c59_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +new file mode 100644 +index 0000000000000000000000000000000000000000..78186f02cda0a231afda4e53a1d6ff696ecb6b4a +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +@@ -0,0 +1,135 @@ ++/* ++ * TP-Link Archer C60 v1 board support ++ * ++ * Copyright (C) 2016 Henryk Heisig ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++#include "dev-m25p80.h" ++#include "machtypes.h" ++#include "pci.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++ ++#define ARCHER_C60_V1_GPIO_LED_LAN 2 ++#define ARCHER_C60_V1_GPIO_LED_POWER 16 ++#define ARCHER_C60_V1_GPIO_LED_WLAN2 17 ++#define ARCHER_C60_V1_GPIO_LED_WLAN5 18 ++#define ARCHER_C60_V1_GPIO_LED_WPS 19 ++#define ARCHER_C60_V1_GPIO_LED_WAN_GREEN 20 ++#define ARCHER_C60_V1_GPIO_LED_WAN_AMBER 22 ++ ++ ++#define ARCHER_C60_V1_KEYS_POLL_INTERVAL 20 ++#define ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL (3 * ARCHER_C60_V1_KEYS_POLL_INTERVAL) ++ ++#define ARCHER_C60_V1_GPIO_BTN_RESET 21 ++#define ARCHER_C60_V1_GPIO_BTN_RFKILL 1 ++ ++ ++ ++#define ARCHER_C60_V1_WMAC_CALDATA_OFFSET 0x1000 ++#define ARCHER_C60_V1_PCI_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led archer_c60_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c60-v1:green:power", ++ .gpio = ARCHER_C60_V1_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wlan2g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wlan5g", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:lan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:amber:wan", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c60-v1:green:wps", ++ .gpio = ARCHER_C60_V1_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button archer_c60_v1_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C60_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = ARCHER_C60_V1_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = ARCHER_C60_V1_GPIO_BTN_RFKILL, ++ .active_low = 1, ++ }, ++}; ++ ++static void __init archer_c60_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f010008); ++ u8 *art = (u8 *) KSEG1ADDR(0x1f7f0000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c60_v1_leds_gpio), ++ archer_c60_v1_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, ARCHER_C60_V1_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(archer_c60_v1_gpio_keys), ++ archer_c60_v1_gpio_keys); ++ ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ath79_register_mdio(1, 0x0); ++ ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_register_eth(1); ++ ++ ath79_register_wmac(art + ARCHER_C60_V1_WMAC_CALDATA_OFFSET, mac); ++ ap91_pci_init(art + ARCHER_C60_V1_PCI_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C60_V1, "ARCHER-C60-V1", ++ "TP-LINK Archer C60 v1", archer_c60_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index e4623fd08836d59ad4e79e96f02e75e502a55ca6..9fbf354e44992f4dff43df0fb0ea99c344801d97 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -42,6 +42,8 @@ enum ath79_mach_type { + ATH79_MACH_AP96, /* Atheros AP96 */ + ATH79_MACH_ARCHER_C25_V1, /* TP-LINK Archer C25 V1 board */ + ATH79_MACH_ARCHER_C5, /* TP-LINK Archer C5 board */ ++ ATH79_MACH_ARCHER_C59_V1, /* TP-LINK Archer C59 V1 board */ ++ ATH79_MACH_ARCHER_C60_V1, /* TP-LINK Archer C60 V1 board */ + ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */ + ATH79_MACH_ARCHER_C7_V2, /* TP-LINK Archer C7 V2 board */ + ATH79_MACH_ARCHER_C7_V4, /* TP-LINK Archer C7 V4 board */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 27d6c73454aef96e5da47033ec664d2caffca1d5..9e4aa8ea30aedba8050a77ebdcfc8f0034cc14d1 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -119,6 +119,36 @@ define Device/archer-c25-v1 + endef + TARGET_DEVICES += archer-c25-v1 + ++define Device/archer-c59-v1 ++ DEVICE_TITLE := TP-LINK Archer C59 v1 ++ DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k ++ BOARDNAME := ARCHER-C59-V1 ++ TPLINK_BOARD_NAME := ARCHER-C59-V1 ++ DEVICE_PROFILE := ARCHERC59V1 ++ IMAGE_SIZE := 14528k ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,1536k(kernel),12992k(rootfs),1664k(tplink)ro,64k(art)ro,14528k@0x20000(firmware) ++endef ++TARGET_DEVICES += archer-c59-v1 ++ ++define Device/archer-c60-v1 ++ DEVICE_TITLE := TP-LINK Archer C60 v1 ++ DEVICE_PACKAGES := kmod-ath10k ++ BOARDNAME := ARCHER-C60-V1 ++ TPLINK_BOARD_NAME := ARCHER-C60-V1 ++ DEVICE_PROFILE := ARCHERC60V1 ++ IMAGE_SIZE := 7936k ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,1344k(kernel),6592k(rootfs),64k(tplink)ro,64k(art)ro,7936k@0x20000(firmware) ++endef ++TARGET_DEVICES += archer-c60-v1 ++ + define Device/cpe510-520 + DEVICE_TITLE := TP-LINK CPE510/520 + DEVICE_PACKAGES := rssileds +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index f5af38a726f5ce33391223a4dbeb2fc0a8cac613..3f6884dcf44c83f9867e4e9936caa79c0abc5dc1 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -17,6 +17,8 @@ + # CONFIG_ATH79_MACH_AP90Q is not set + # CONFIG_ATH79_MACH_AP96 is not set + # CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C59_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C60_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set + # CONFIG_ATH79_MACH_ARDUINO_YUN is not set + # CONFIG_ATH79_MACH_AW_NR580 is not set +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index 5c18f5d594d625f91ff10e21ddc5af2b3b4d768f..a50099aca12aafdcb27f4f2b77ca2a5ce4b4d6f2 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -10,6 +10,8 @@ + # CONFIG_ATH79_MACH_AP147 is not set + # CONFIG_ATH79_MACH_AP96 is not set + # CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C59_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C60_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set + # CONFIG_ATH79_MACH_AW_NR580 is not set + # CONFIG_ATH79_MACH_CAP324 is not set +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index fec830c23ce6707755ddefc849f195872be1e877..aeebf8e0bbdc3ec53c42d5cc01a3ffe892b46804 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -376,6 +376,79 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "file-system" + }, + ++ /** Firmware layout for the C59v1 */ ++ { ++ .id = "ARCHER-C59-V1", ++ .vendor = "", ++ .support_list = ++ "SupportList:\r\n" ++ "{product_name:Archer C59,product_ver:1.0.0,special_id:00000000}\r\n" ++ "{product_name:Archer C59,product_ver:1.0.0,special_id:45550000}\r\n" ++ "{product_name:Archer C59,product_ver:1.0.0,special_id:55530000}\r\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ ++ .partitions = { ++ {"fs-uboot", 0x00000, 0x10000}, ++ {"default-mac", 0x10000, 0x00200}, ++ {"pin", 0x10200, 0x00200}, ++ {"device-id", 0x10400, 0x00100}, ++ {"product-info", 0x10500, 0x0fb00}, ++ {"os-image", 0x20000, 0x180000}, ++ {"file-system", 0x1a0000, 0xcb0000}, ++ {"partition-table", 0xe50000, 0x10000}, ++ {"soft-version", 0xe60000, 0x10000}, ++ {"support-list", 0xe70000, 0x10000}, ++ {"profile", 0xe80000, 0x10000}, ++ {"default-config", 0xe90000, 0x10000}, ++ {"user-config", 0xea0000, 0x40000}, ++ {"usb-config", 0xee0000, 0x10000}, ++ {"certificate", 0xef0000, 0x10000}, ++ {"qos-db", 0xf00000, 0x40000}, ++ {"log", 0xfe0000, 0x10000}, ++ {"radio", 0xff0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system", ++ }, ++ ++ /** Firmware layout for the C60v1 */ ++ { ++ .id = "ARCHER-C60-V1", ++ .vendor = "", ++ .support_list = ++ "SupportList:\r\n" ++ "{product_name:Archer C60,product_ver:1.0.0,special_id:00000000}\r\n" ++ "{product_name:Archer C60,product_ver:1.0.0,special_id:45550000}\r\n" ++ "{product_name:Archer C60,product_ver:1.0.0,special_id:55530000}\r\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ ++ .partitions = { ++ {"fs-uboot", 0x00000, 0x10000}, ++ {"default-mac", 0x10000, 0x00200}, ++ {"pin", 0x10200, 0x00200}, ++ {"product-info", 0x10400, 0x00100}, ++ {"partition-table", 0x10500, 0x00800}, ++ {"soft-version", 0x11300, 0x00200}, ++ {"support-list", 0x11500, 0x00100}, ++ {"device-id", 0x11600, 0x00100}, ++ {"profile", 0x11700, 0x03900}, ++ {"default-config", 0x15000, 0x04000}, ++ {"user-config", 0x19000, 0x04000}, ++ {"os-image", 0x20000, 0x150000}, ++ {"file-system", 0x170000, 0x678000}, ++ {"certyficate", 0x7e8000, 0x08000}, ++ {"radio", 0x7f0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system", ++ }, ++ + /** Firmware layout for the C7 */ + { + .id = "ARCHER-C7-V4", diff --git a/patches/lede/0050-ar71xx-fix-lan-ports-on-archer-C59-and-C60.patch b/patches/lede/0050-ar71xx-fix-lan-ports-on-archer-C59-and-C60.patch new file mode 100644 index 00000000..df97d40c --- /dev/null +++ b/patches/lede/0050-ar71xx-fix-lan-ports-on-archer-C59-and-C60.patch @@ -0,0 +1,128 @@ +From: Henryk Heisig +Date: Thu, 16 Feb 2017 15:22:49 +0100 +Subject: ar71xx: fix lan ports on archer C59 and C60 + +Signed-off-by: Henryk Heisig + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 8552cde564b3fbed9425f42d5331f95fe5c3aaa8..5c6b47d0249c979934d61078e16759fc22aa41c7 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -64,8 +64,8 @@ archer-c25-v1) + ;; + archer-c59-v1|\ + archer-c60-v1) +- ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x3C" +- ucidef_set_led_switch "wan" "WAN" "$board:green:wan" "switch0" "0x02" ++ ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x1E" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan2g" "phy1tpt" + ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:green:wlan5g" "phy0tpt" + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 3abe1114ee31c79abb125b85119876c3d75bb7c0..933ed22815ee076c98a83173aad143c010c9a131 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -206,9 +206,15 @@ ar71xx_setup_interfaces() + "0@eth1" "2:lan" "3:lan" "4:lan" "5:lan" "6@eth0" "1:wan" + ;; + archer-c59-v1|\ ++ rb-450g) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_add_switch "switch0" \ ++ "0@eth1" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" ++ ;; + archer-c60-v1) ++ ucidef_set_interfaces_lan_wan "eth1.1" "eth0" + ucidef_add_switch "switch0" \ +- "0@eth0" "2:lan:4" "3:lan:3" "4:lan:2" "5:lan:1" "1:wan" ++ "0@eth1" "1:lan:1" "2:lan:2" "3:lan:3" "4:lan:4" + ;; + arduino-yun|\ + dir-505-a1|\ +@@ -370,11 +376,6 @@ ar71xx_setup_interfaces() + ucidef_add_switch "switch0" \ + "0:lan:4" "1:lan:3" "2:lan:2" "3:lan:1" "5@eth1" + ;; +- rb-450g) +- ucidef_set_interfaces_lan_wan "eth1" "eth0" +- ucidef_add_switch "switch0" \ +- "0@eth1" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" +- ;; + routerstation-pro) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ucidef_add_switch "switch0" \ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +index 28353aa77b05078b895ab48cf6b1ae53abe98ce2..d55f9b9f75b38159ed7209aa5acd73ff31088b51 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +@@ -194,19 +194,33 @@ static void __init archer_c59_v1_setup(void) + ARRAY_SIZE(archer_c59_v1_gpio_keys), + archer_c59_v1_gpio_keys); + ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ++ ath79_register_mdio(0, 0x0); + ath79_register_mdio(1, 0x0); + +- ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 1); + ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + ath79_eth1_data.speed = SPEED_1000; + ath79_eth1_data.duplex = DUPLEX_FULL; +- ath79_eth1_data.phy_mask = BIT(4); ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; + ath79_register_eth(1); + + ath79_register_wmac(art + ARCHER_C59_V1_WMAC_CALDATA_OFFSET, mac); + ap91_pci_init(art + ARCHER_C59_V1_PCI_CALDATA_OFFSET, NULL); + +- + ath79_register_usb(); + gpio_request_one(ARCHER_C59_V1_GPIO_USB_POWER, + GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +index 78186f02cda0a231afda4e53a1d6ff696ecb6b4a..4d83fa737b9650935b4f7f985d58f471c38cd9da 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c60-v1.c +@@ -116,15 +116,25 @@ static void __init archer_c60_v1_setup(void) + ARRAY_SIZE(archer_c60_v1_gpio_keys), + archer_c60_v1_gpio_keys); + +- ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | +- QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ath79_register_mdio(0, 0x0); + ath79_register_mdio(1, 0x0); + +- ath79_init_mac(ath79_eth1_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_init_mac(ath79_eth1_data.mac_addr, mac, 1); + ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + ath79_eth1_data.speed = SPEED_1000; + ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; + ath79_register_eth(1); + + ath79_register_wmac(art + ARCHER_C60_V1_WMAC_CALDATA_OFFSET, mac); diff --git a/patches/lede/0051-ar71xx-add-support-for-TP-Link-Archer-C58-v1.patch b/patches/lede/0051-ar71xx-add-support-for-TP-Link-Archer-C58-v1.patch new file mode 100644 index 00000000..3bf6a3a3 --- /dev/null +++ b/patches/lede/0051-ar71xx-add-support-for-TP-Link-Archer-C58-v1.patch @@ -0,0 +1,411 @@ +From: Henryk Heisig +Date: Fri, 16 Jun 2017 15:26:30 +0200 +Subject: ar71xx: add support for TP-Link Archer C58 v1 + +TP-Link Archer C58 v1 is a dual-band AC1350 router, based on Qualcomm +QCA9561 + QCA9886. It looks like Archer C59 v1 without USB port. + +Specification: + +- 775/650/258 MHz (CPU/DDR/AHB) +- 64 MB of RAM (DDR2) +- 8 MB of FLASH (SPI NOR) +- 3T3R 2.4 GHz +- 2T2R 5 GHz +- 5x 10/100 Mbps Ethernet +- 6x LED, 3x button +- UART header on PCB, RX, TX at TP4+5 (backside) + +QCA9886 wlan needs pre_cal_data file and enable ieee80211 phy hotplug to +patch macaddress. + +Flash instruction: + +Use "factory" image directly in vendor GUI. + +Recovery method: + +1. Set PC to fixed ip address 192.168.0.66/24. +2. Download "lede-ar71xx-generic-archer-c58-v1-squashfs-factory.bin" and + rename it to "tp_recovery.bin". +3. Start a tftp server with the file "tp_recovery.bin" in its root + directory. +4. Turn off the router. +5. Press and hold Reset button. +6. Turn on router with the reset button pressed and wait ~15 seconds. +7. Release the reset button and after a short time the firmware should + be transferred from the tftp server. +8. Wait ~30 second to complete recovery. + +Flash instruction under U-Boot, using UART: + +tftp 0x81000000 lede-ar71xx-...-sysupgrade.bin +erase 0x9f020000 +$filesize +cp.b $fileaddr 0x9f020000 $filesize +reset + +This commit is based on GitHub PR#1112 + +Signed-off-by: Henryk Heisig + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 5c6b47d0249c979934d61078e16759fc22aa41c7..f9483e9a706fbd98ce6a42e968bc0d31e9da5c84 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -62,6 +62,7 @@ archer-c25-v1) + ucidef_set_led_switch "lan3" "LAN3" "$board:green:lan3" "switch0" "0x04" + ucidef_set_led_switch "lan4" "LAN4" "$board:green:lan4" "switch0" "0x02" + ;; ++archer-c58-v1|\ + archer-c59-v1|\ + archer-c60-v1) + ucidef_set_led_switch "lan" "LAN" "$board:green:lan" "switch0" "0x1E" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 933ed22815ee076c98a83173aad143c010c9a131..57bc912aa5ede22a3fad4af6a1deb00c33f17cf8 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -205,6 +205,7 @@ ar71xx_setup_interfaces() + ucidef_add_switch "switch0" \ + "0@eth1" "2:lan" "3:lan" "4:lan" "5:lan" "6@eth0" "1:wan" + ;; ++ archer-c58-v1|\ + archer-c59-v1|\ + rb-450g) + ucidef_set_interfaces_lan_wan "eth1.1" "eth0" +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 3aa1f054d4f791545a8b6644f7bd24f64ed546a3..382500b75ee6dc1fe1126fb3121f4ae205c901d4 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -52,6 +52,7 @@ get_status_led() { + ;; + archer-c25-v1|\ + archer-c7-v4|\ ++ archer-c58-v1|\ + archer-c59-v1|\ + archer-c60-v1|\ + mr12|\ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 6c62f391e1aac2f052d3397fc25f8bddcca581dd..4ef5ba983d3fadc5e7842f707fff641a3c0cea8f 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -140,6 +140,13 @@ case "$FIRMWARE" in + ;; + esac + ;; ++"ath10k/pre-cal-pci-0000:00:00.0.bin") ++ case $board in ++ archer-c58-v1) ++ ath10kcal_extract "art" 20480 12064 ++ ;; ++ esac ++ ;; + *) + exit 1 + ;; +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +new file mode 100644 +index 0000000000000000000000000000000000000000..7d2eca546d76b771b12026788510f73a293a9a93 +--- /dev/null ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +@@ -0,0 +1,21 @@ ++#!/bin/ash ++ ++[ "$ACTION" == "add" ] || exit 0 ++ ++PHYNBR=${DEVPATH##*/phy} ++ ++[ -n $PHYNBR ] || exit 0 ++ ++. /lib/ar71xx.sh ++. /lib/functions/system.sh ++ ++board=$(ar71xx_board_name) ++ ++case "$board" in ++ archer-c58-v1) ++ echo $(macaddr_add $(mtd_get_mac_binary mac 8) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress ++ ;; ++ *) ++ ;; ++esac ++ +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index d8e23d97e2cc20f8ba7b3b2fc516ce398c43a19b..59ede17653bbb1994ce9fa734c86c877aedf67e4 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -472,6 +472,9 @@ ar71xx_board_detect() { + *"Archer C7 v4") + name="archer-c7-v4" + ;; ++ *"Archer C58 v1") ++ name="archer-c58-v1" ++ ;; + *"Archer C59 v1") + name="archer-c59-v1" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index f4ac73e40e1acb800433a0b1348c8264a4639c30..5e8a06a7ae70ec349693c09deedbfce41a52cfc2 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -216,6 +216,7 @@ platform_check_image() { + ap90q|\ + archer-c25-v1|\ + archer-c7-v4|\ ++ archer-c58-v1|\ + archer-c59-v1|\ + archer-c60-v1|\ + bullet-m|\ +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index e335ef9b7dfe8f0250b4362542ea2518eac34cb4..b84e1cb584f3afce016d0685fb2397962ee85645 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -52,6 +52,7 @@ CONFIG_ATH79_MACH_AP152=y + CONFIG_ATH79_MACH_AP90Q=y + CONFIG_ATH79_MACH_AP96=y + CONFIG_ATH79_MACH_ARCHER_C25_V1=y ++CONFIG_ATH79_MACH_ARCHER_C58_V1=y + CONFIG_ATH79_MACH_ARCHER_C59_V1=y + CONFIG_ATH79_MACH_ARCHER_C60_V1=y + CONFIG_ATH79_MACH_ARCHER_C7=y +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 468d9b333e43814cbadec8d85a20ab94e5cd6d01..4c9012acc6b4c40d88ffc8752086cac86b9b9c92 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1244,6 +1244,16 @@ config ATH79_MACH_ARCHER_C25_V1 + select ATH79_DEV_M25P80 + select ATH79_DEV_WMAC + ++config ATH79_MACH_ARCHER_C58_V1 ++ bool "TP-LINK Archer C58 v1 support" ++ select SOC_QCA956X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_WMAC ++ + config ATH79_MACH_ARCHER_C59_V1 + bool "TP-LINK Archer C59 v1 support" + select SOC_QCA956X +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index fbe7fcb0aebb6577b96c27088a158eb025f201cb..8408894669dc5f14f05701359073ef233a1b89f0 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -57,6 +57,7 @@ obj-$(CONFIG_ATH79_MACH_AP152) += mach-ap152.o + obj-$(CONFIG_ATH79_MACH_AP90Q) += mach-ap90q.o + obj-$(CONFIG_ATH79_MACH_AP96) += mach-ap96.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C25_V1) += mach-archer-c25-v1.o ++obj-$(CONFIG_ATH79_MACH_ARCHER_C58_V1) += mach-archer-c59-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C59_V1) += mach-archer-c59-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C60_V1) += mach-archer-c60-v1.o + obj-$(CONFIG_ATH79_MACH_ARCHER_C7) += mach-archer-c7.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +index d55f9b9f75b38159ed7209aa5acd73ff31088b51..f385d4a5a3148b83ee01007145e0eda2c0ef670f 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +@@ -1,7 +1,7 @@ + /* +- * TP-Link Archer C59 v1 board support ++ * TP-Link Archer C58/C59 v1 board support + * +- * Copyright (C) 2016 Henryk Heisig ++ * Copyright (C) 2017 Henryk Heisig + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published +@@ -65,6 +65,44 @@ + #define ARCHER_C59_V1_WMAC_CALDATA_OFFSET 0x1000 + #define ARCHER_C59_V1_PCI_CALDATA_OFFSET 0x5000 + ++static struct gpio_led archer_c58_v1_leds_gpio[] __initdata = { ++ { ++ .name = "archer-c58-v1:green:power", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wlan2g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN2, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wlan5g", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WLAN5, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:lan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:amber:wan", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WAN_AMBER, ++ .active_low = 1, ++ }, ++ { ++ .name = "archer-c58-v1:green:wps", ++ .gpio = ARCHER_C59_74HC_GPIO_LED_WPS, ++ .active_low = 1, ++ }, ++}; ++ + static struct gpio_led archer_c59_v1_leds_gpio[] __initdata = { + { + .name = "archer-c59-v1:green:power", +@@ -177,7 +215,7 @@ static struct spi_board_info archer_c59_v1_spi_info[] = { + }, + }; + +-static void __init archer_c59_v1_setup(void) ++static void __init archer_c5x_v1_setup(void) + { + u8 *mac = (u8 *) KSEG1ADDR(0x1f010008); + u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); +@@ -187,9 +225,6 @@ static void __init archer_c59_v1_setup(void) + ARRAY_SIZE(archer_c59_v1_spi_info)); + platform_device_register(&archer_c59_v1_spi_device); + +- ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c59_v1_leds_gpio), +- archer_c59_v1_leds_gpio); +- + ath79_register_gpio_keys_polled(-1, ARCHER_C59_V1_KEYS_POLL_INTERVAL, + ARRAY_SIZE(archer_c59_v1_gpio_keys), + archer_c59_v1_gpio_keys); +@@ -233,5 +268,22 @@ static void __init archer_c59_v1_setup(void) + "LED reset"); + } + ++static void __init archer_c58_v1_setup(void) ++{ ++ archer_c5x_v1_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c58_v1_leds_gpio), ++ archer_c58_v1_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_ARCHER_C58_V1, "ARCHER-C58-V1", ++ "TP-LINK Archer C58 v1", archer_c58_v1_setup); ++ ++static void __init archer_c59_v1_setup(void) ++{ ++ archer_c5x_v1_setup(); ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(archer_c59_v1_leds_gpio), ++ archer_c59_v1_leds_gpio); ++} ++ + MIPS_MACHINE(ATH79_MACH_ARCHER_C59_V1, "ARCHER-C59-V1", + "TP-LINK Archer C59 v1", archer_c59_v1_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 9fbf354e44992f4dff43df0fb0ea99c344801d97..72c1e38c74707aba8fbd3aebc36f35becabd4987 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -42,6 +42,7 @@ enum ath79_mach_type { + ATH79_MACH_AP96, /* Atheros AP96 */ + ATH79_MACH_ARCHER_C25_V1, /* TP-LINK Archer C25 V1 board */ + ATH79_MACH_ARCHER_C5, /* TP-LINK Archer C5 board */ ++ ATH79_MACH_ARCHER_C58_V1, /* TP-LINK Archer C58 V1 board */ + ATH79_MACH_ARCHER_C59_V1, /* TP-LINK Archer C59 V1 board */ + ATH79_MACH_ARCHER_C60_V1, /* TP-LINK Archer C60 V1 board */ + ATH79_MACH_ARCHER_C7, /* TP-LINK Archer C7 board */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 9e4aa8ea30aedba8050a77ebdcfc8f0034cc14d1..557bcdab2237a03957313cc3cda471a9fe3a3706 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -119,6 +119,21 @@ define Device/archer-c25-v1 + endef + TARGET_DEVICES += archer-c25-v1 + ++define Device/archer-c58-v1 ++ DEVICE_TITLE := TP-LINK Archer C58 v1 ++ DEVICE_PACKAGES := kmod-ath10k ++ BOARDNAME := ARCHER-C58-V1 ++ TPLINK_BOARD_NAME := ARCHER-C58-V1 ++ DEVICE_PROFILE := ARCHERC58V1 ++ IMAGE_SIZE := 7936k ++ KERNEL := kernel-bin | patch-cmdline | lzma | uImageArcher lzma ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,1344k(kernel),6592k(rootfs),64k(tplink)ro,64k(art)ro,7936k@0x20000(firmware) ++endef ++TARGET_DEVICES += archer-c58-v1 ++ + define Device/archer-c59-v1 + DEVICE_TITLE := TP-LINK Archer C59 v1 + DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index 3f6884dcf44c83f9867e4e9936caa79c0abc5dc1..23e862762600f0724a37fe1a390d4d09639c472c 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -17,6 +17,7 @@ + # CONFIG_ATH79_MACH_AP90Q is not set + # CONFIG_ATH79_MACH_AP96 is not set + # CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C58_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C59_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C60_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index a50099aca12aafdcb27f4f2b77ca2a5ce4b4d6f2..c11ccfe29795d013776870cf21fb6ca8d907af1b 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -10,6 +10,7 @@ + # CONFIG_ATH79_MACH_AP147 is not set + # CONFIG_ATH79_MACH_AP96 is not set + # CONFIG_ATH79_MACH_ARCHER_C25_V1 is not set ++# CONFIG_ATH79_MACH_ARCHER_C58_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C59_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C60_V1 is not set + # CONFIG_ATH79_MACH_ARCHER_C7 is not set +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index aeebf8e0bbdc3ec53c42d5cc01a3ffe892b46804..67e2c4475bbd468bd20915767a481711ae872a3a 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -376,6 +376,41 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "file-system" + }, + ++ /** Firmware layout for the C58v1 */ ++ { ++ .id = "ARCHER-C58-V1", ++ .vendor = "", ++ .support_list = ++ "SupportList:\r\n" ++ "{product_name:Archer C58,product_ver:1.0.0,special_id:00000000}\r\n" ++ "{product_name:Archer C58,product_ver:1.0.0,special_id:45550000}\r\n" ++ "{product_name:Archer C58,product_ver:1.0.0,special_id:55530000}\r\n", ++ .support_trail = '\x00', ++ .soft_ver = "soft_ver:1.0.0\n", ++ ++ .partitions = { ++ {"fs-uboot", 0x00000, 0x10000}, ++ {"default-mac", 0x10000, 0x00200}, ++ {"pin", 0x10200, 0x00200}, ++ {"product-info", 0x10400, 0x00100}, ++ {"partition-table", 0x10500, 0x00800}, ++ {"soft-version", 0x11300, 0x00200}, ++ {"support-list", 0x11500, 0x00100}, ++ {"device-id", 0x11600, 0x00100}, ++ {"profile", 0x11700, 0x03900}, ++ {"default-config", 0x15000, 0x04000}, ++ {"user-config", 0x19000, 0x04000}, ++ {"os-image", 0x20000, 0x150000}, ++ {"file-system", 0x170000, 0x678000}, ++ {"certyficate", 0x7e8000, 0x08000}, ++ {"radio", 0x7f0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "file-system", ++ }, ++ + /** Firmware layout for the C59v1 */ + { + .id = "ARCHER-C59-V1", diff --git a/patches/lede/0052-ath10k-firmware-update-repository.patch b/patches/lede/0052-ath10k-firmware-update-repository.patch new file mode 100644 index 00000000..8dbaffaa --- /dev/null +++ b/patches/lede/0052-ath10k-firmware-update-repository.patch @@ -0,0 +1,21 @@ +From: David Bauer +Date: Thu, 11 Jan 2018 21:17:15 +0100 +Subject: ath10k-firmware: update repository + +diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile +index 8bf5729fff16677ef6449498f1df3cda19272583..81dce0eb7aeee20e2ed3be4cc6699bf867487a96 100644 +--- a/package/firmware/ath10k-firmware/Makefile ++++ b/package/firmware/ath10k-firmware/Makefile +@@ -8,9 +8,9 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=ath10k-firmware +-PKG_SOURCE_DATE:=2017-01-11 +-PKG_SOURCE_VERSION:=ab432c60437931a165f0aff1a6e3371f358b75dd +-PKG_MIRROR_HASH:=e3188ecd4d7470d3cdde89fefa6258f9ec4f404b23558d1474e5014679b28101 ++PKG_SOURCE_DATE:=2017-03-29 ++PKG_SOURCE_VERSION:=956e2609b7e42c8c710bba10ef925a5be1be5137 ++PKG_MIRROR_HASH:=25f724ff38c830281b3efba4a4ddffaae0c4bd8fea0f4c1061591229ff05535b + PKG_RELEASE:=1 + + PKG_SOURCE_PROTO:=git diff --git a/patches/lede/0053-ath10k-firmware-add-qca9888-firmware.patch b/patches/lede/0053-ath10k-firmware-add-qca9888-firmware.patch new file mode 100644 index 00000000..66b337f3 --- /dev/null +++ b/patches/lede/0053-ath10k-firmware-add-qca9888-firmware.patch @@ -0,0 +1,53 @@ +From: John Crispin +Date: Mon, 8 May 2017 08:51:46 +0200 +Subject: ath10k-firmware: add qca9888 firmware + +the firmware files for qca9888 were previously not packaged. add the meta +information for doing so. + +Signed-off-by: John Crispin + +diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile +index 81dce0eb7aeee20e2ed3be4cc6699bf867487a96..aac8ee2b271678b03f58a6cb68beae6d53467dc1 100644 +--- a/package/firmware/ath10k-firmware/Makefile ++++ b/package/firmware/ath10k-firmware/Makefile +@@ -32,6 +32,11 @@ $(Package/ath10k-firmware-default) + TITLE:=ath10k firmware for QCA9887 devices + endef + ++define Package/ath10k-firmware-qca9888 ++$(Package/ath10k-firmware-default) ++ TITLE:=ath10k firmware for QCA9888 devices ++endef ++ + define Package/ath10k-firmware-qca9887-ct + $(Package/ath10k-firmware-default) + TITLE:=ath10k-CT firmware for QCA9887 devices +@@ -240,6 +245,19 @@ define Package/ath10k-firmware-qca9887/install + $(1)/lib/firmware/ath10k/QCA9887/hw1.0/board.bin + endef + ++define Package/ath10k-firmware-qca9888/install ++ $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA9888/hw2.0 ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ ++ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ ++ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin ++ $(INSTALL_DATA) \ ++ $(PKG_BUILD_DIR)/QCA9888/hw2.0/firmware-5.bin_10.4-3.2-00072 \ ++ $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin ++endef ++ + define Package/ath10k-firmware-qca988x/install + $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 + $(INSTALL_DATA) \ +@@ -328,6 +346,7 @@ define Package/ath10k-firmware-qca9984-ct/install + endef + + $(eval $(call BuildPackage,ath10k-firmware-qca9887)) ++$(eval $(call BuildPackage,ath10k-firmware-qca9888)) + $(eval $(call BuildPackage,ath10k-firmware-qca988x)) + $(eval $(call BuildPackage,ath10k-firmware-qca99x0)) + $(eval $(call BuildPackage,ath10k-firmware-qca6174)) diff --git a/patches/lede/0054-ar71xx-fix-board.bin-used-by-QCA9886-in-Archer-C58-C59-C60.patch b/patches/lede/0054-ar71xx-fix-board.bin-used-by-QCA9886-in-Archer-C58-C59-C60.patch new file mode 100644 index 00000000..e0062d5a --- /dev/null +++ b/patches/lede/0054-ar71xx-fix-board.bin-used-by-QCA9886-in-Archer-C58-C59-C60.patch @@ -0,0 +1,20 @@ +From: Henryk Heisig +Date: Thu, 29 Jun 2017 15:38:22 +0200 +Subject: ar71xx: fix board.bin used by QCA9886 in Archer C58/C59/C60 + +Signed-off-by: Henryk Heisig +(cherry picked from commit e917e51bf91fc7cb5085bda5e67d62520801f9cc) + +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 4ef5ba983d3fadc5e7842f707fff641a3c0cea8f..8efe348498d4aaf5ae660a29073fc75ae7c9d72e 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -144,6 +144,8 @@ case "$FIRMWARE" in + case $board in + archer-c58-v1) + ath10kcal_extract "art" 20480 12064 ++ ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ ++ /lib/firmware/ath10k/QCA9888/hw2.0/board.bin + ;; + esac + ;; diff --git a/patches/lede/0055-ar71xx-Archer-C58-C59-C60-fix-qca9886-wireless-interface.patch b/patches/lede/0055-ar71xx-Archer-C58-C59-C60-fix-qca9886-wireless-interface.patch new file mode 100644 index 00000000..e1a2a3b3 --- /dev/null +++ b/patches/lede/0055-ar71xx-Archer-C58-C59-C60-fix-qca9886-wireless-interface.patch @@ -0,0 +1,71 @@ +From: Henryk Heisig +Date: Thu, 29 Jun 2017 15:20:31 +0200 +Subject: ar71xx: Archer C58/C59/C60 fix qca9886 wireless interface + +This commit fix 5GHz wireless interface used in Archer C58/C59/C60v1 +and set correctly MAC address on this interface. + +Signed-off-by: Henryk Heisig +(cherry picked from commit 34958c826915cf864833ed8ba6e5b49d44c6cb41) + +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 8efe348498d4aaf5ae660a29073fc75ae7c9d72e..65251284bba605afda8709c4799060e7a5554193 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -142,7 +142,9 @@ case "$FIRMWARE" in + ;; + "ath10k/pre-cal-pci-0000:00:00.0.bin") + case $board in +- archer-c58-v1) ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c60-v1) + ath10kcal_extract "art" 20480 12064 + ln -sf /lib/firmware/ath10k/pre-cal-pci-0000\:00\:00.0.bin \ + /lib/firmware/ath10k/QCA9888/hw2.0/board.bin +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +index 7d2eca546d76b771b12026788510f73a293a9a93..669b208231e43fe86e998c7202c133c86ae0bf8d 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/ieee80211/10_fix_wifi_mac +@@ -12,7 +12,9 @@ PHYNBR=${DEVPATH##*/phy} + board=$(ar71xx_board_name) + + case "$board" in +- archer-c58-v1) ++ archer-c58-v1|\ ++ archer-c59-v1|\ ++ archer-c60-v1) + echo $(macaddr_add $(mtd_get_mac_binary mac 8) $(($PHYNBR - 1)) ) > /sys${DEVPATH}/macaddress + ;; + *) +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 557bcdab2237a03957313cc3cda471a9fe3a3706..ed45866fcbe8d35af663799a91b09b5c8fd613bc 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -121,7 +121,7 @@ TARGET_DEVICES += archer-c25-v1 + + define Device/archer-c58-v1 + DEVICE_TITLE := TP-LINK Archer C58 v1 +- DEVICE_PACKAGES := kmod-ath10k ++ DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca9888 + BOARDNAME := ARCHER-C58-V1 + TPLINK_BOARD_NAME := ARCHER-C58-V1 + DEVICE_PROFILE := ARCHERC58V1 +@@ -136,7 +136,7 @@ TARGET_DEVICES += archer-c58-v1 + + define Device/archer-c59-v1 + DEVICE_TITLE := TP-LINK Archer C59 v1 +- DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k ++ DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-ledtrig-usbport kmod-ath10k ath10k-firmware-qca9888 + BOARDNAME := ARCHER-C59-V1 + TPLINK_BOARD_NAME := ARCHER-C59-V1 + DEVICE_PROFILE := ARCHERC59V1 +@@ -151,7 +151,7 @@ TARGET_DEVICES += archer-c59-v1 + + define Device/archer-c60-v1 + DEVICE_TITLE := TP-LINK Archer C60 v1 +- DEVICE_PACKAGES := kmod-ath10k ++ DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca9888 + BOARDNAME := ARCHER-C60-V1 + TPLINK_BOARD_NAME := ARCHER-C60-V1 + DEVICE_PROFILE := ARCHERC60V1 diff --git a/patches/lede/0056-ath10k-firmware-qca9888-firmware-remove-board.bin.patch b/patches/lede/0056-ath10k-firmware-qca9888-firmware-remove-board.bin.patch new file mode 100644 index 00000000..777d91dc --- /dev/null +++ b/patches/lede/0056-ath10k-firmware-qca9888-firmware-remove-board.bin.patch @@ -0,0 +1,20 @@ +From: Henryk Heisig +Date: Mon, 3 Jul 2017 23:59:54 +0200 +Subject: ath10k-firmware: qca9888 firmware: remove board.bin + +Signed-off-by: Henryk Heisig + +diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile +index aac8ee2b271678b03f58a6cb68beae6d53467dc1..e8cc4b91c3f59f09e4281c7b36048dc66bd04f3b 100644 +--- a/package/firmware/ath10k-firmware/Makefile ++++ b/package/firmware/ath10k-firmware/Makefile +@@ -250,9 +250,6 @@ define Package/ath10k-firmware-qca9888/install + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board-2.bin +- $(INSTALL_DATA) \ +- $(PKG_BUILD_DIR)/QCA9888/hw2.0/board-2.bin \ +- $(1)/lib/firmware/ath10k/QCA9888/hw2.0/board.bin + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/QCA9888/hw2.0/firmware-5.bin_10.4-3.2-00072 \ + $(1)/lib/firmware/ath10k/QCA9888/hw2.0/firmware-5.bin diff --git a/patches/lede/0057-ar71xx-C58-C59-fix-LAN1-working-incorrectly.patch b/patches/lede/0057-ar71xx-C58-C59-fix-LAN1-working-incorrectly.patch new file mode 100644 index 00000000..6cdb1140 --- /dev/null +++ b/patches/lede/0057-ar71xx-C58-C59-fix-LAN1-working-incorrectly.patch @@ -0,0 +1,22 @@ +From: David Bauer +Date: Mon, 27 Nov 2017 04:19:38 +0100 +Subject: ar71xx: C58/C59 fix LAN1 working incorrectly + +This commit fixes LAN Port 1 not transferring data in case no +other LAN Port has active link-state on TP-Link Archer C58/C59. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +index f385d4a5a3148b83ee01007145e0eda2c0ef670f..129aa53f304dd1a118ace9a2749855cb36f66cfc 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-archer-c59-v1.c +@@ -249,7 +249,7 @@ static void __init archer_c5x_v1_setup(void) + ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; + ath79_eth1_data.speed = SPEED_1000; + ath79_eth1_data.duplex = DUPLEX_FULL; +- ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy_poll_mask |= BIT(0); + ath79_switch_data.phy4_mii_en = 1; + ath79_register_eth(1); + diff --git a/patches/lede/0058-ar71xx-omit-VLAN-from-Archer-C58-C59-LAN-interface.patch b/patches/lede/0058-ar71xx-omit-VLAN-from-Archer-C58-C59-LAN-interface.patch new file mode 100644 index 00000000..044a5556 --- /dev/null +++ b/patches/lede/0058-ar71xx-omit-VLAN-from-Archer-C58-C59-LAN-interface.patch @@ -0,0 +1,17 @@ +From: David Bauer +Date: Thu, 11 Jan 2018 21:23:30 +0100 +Subject: ar71xx: omit VLAN from Archer C58/C59 LAN interface + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 57bc912aa5ede22a3fad4af6a1deb00c33f17cf8..1690172b5dfac1e1aa278c38c27ba64cfd61ade0 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -208,7 +208,7 @@ ar71xx_setup_interfaces() + archer-c58-v1|\ + archer-c59-v1|\ + rb-450g) +- ucidef_set_interfaces_lan_wan "eth1.1" "eth0" ++ ucidef_set_interfaces_lan_wan "eth1" "eth0" + ucidef_add_switch "switch0" \ + "0@eth1" "1:lan:1" "2:lan:4" "3:lan:3" "4:lan:2" + ;; diff --git a/patches/lede/0059-ar71xx-increase-kernel-partition-size-for-some-TP-Link-boards.patch b/patches/lede/0059-ar71xx-increase-kernel-partition-size-for-some-TP-Link-boards.patch new file mode 100644 index 00000000..aad94373 --- /dev/null +++ b/patches/lede/0059-ar71xx-increase-kernel-partition-size-for-some-TP-Link-boards.patch @@ -0,0 +1,64 @@ +From: Henryk Heisig +Date: Fri, 27 Oct 2017 00:23:17 +0200 +Subject: ar71xx: increase kernel partition size for some TP-Link boards + +This patch increases kernel partition size and re-enables image +generation for below TP-Link boards: + +- archer-c58-v1 +- archer-c60-v1 +- tl-wr902ac-v1 +- tl-wr942n-v1 + +Signed-off-by: Henryk Heisig +[commit message and title reworded] +Signed-off-by: Piotr Dymacz + +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index ed45866fcbe8d35af663799a91b09b5c8fd613bc..be7e846c88f9ebbb8a4e4840e690d7864386bf64 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -130,7 +130,7 @@ define Device/archer-c58-v1 + IMAGES := sysupgrade.bin factory.bin + IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory +- MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,1344k(kernel),6592k(rootfs),64k(tplink)ro,64k(art)ro,7936k@0x20000(firmware) ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,7936k(firmware),64k(tplink)ro,64k(art)ro + endef + TARGET_DEVICES += archer-c58-v1 + +@@ -160,7 +160,7 @@ define Device/archer-c60-v1 + IMAGES := sysupgrade.bin factory.bin + IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory +- MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,1344k(kernel),6592k(rootfs),64k(tplink)ro,64k(art)ro,7936k@0x20000(firmware) ++ MTDPARTS := spi0.0:64k(u-boot)ro,64k(mac)ro,7936k(firmware),64k(tplink)ro,64k(art)ro + endef + TARGET_DEVICES += archer-c60-v1 + +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 67e2c4475bbd468bd20915767a481711ae872a3a..11ff2e56e19ec3780f988baf7257810530165b23 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -400,8 +400,8 @@ static struct device_info boards[] = { + {"profile", 0x11700, 0x03900}, + {"default-config", 0x15000, 0x04000}, + {"user-config", 0x19000, 0x04000}, +- {"os-image", 0x20000, 0x150000}, +- {"file-system", 0x170000, 0x678000}, ++ {"os-image", 0x20000, 0x180000}, ++ {"file-system", 0x1a0000, 0x648000}, + {"certyficate", 0x7e8000, 0x08000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} +@@ -473,8 +473,8 @@ static struct device_info boards[] = { + {"profile", 0x11700, 0x03900}, + {"default-config", 0x15000, 0x04000}, + {"user-config", 0x19000, 0x04000}, +- {"os-image", 0x20000, 0x150000}, +- {"file-system", 0x170000, 0x678000}, ++ {"os-image", 0x20000, 0x180000}, ++ {"file-system", 0x1a0000, 0x648000}, + {"certyficate", 0x7e8000, 0x08000}, + {"radio", 0x7f0000, 0x10000}, + {NULL, 0, 0} diff --git a/patches/lede/0060-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch b/patches/lede/0060-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch new file mode 100644 index 00000000..e31f4d05 --- /dev/null +++ b/patches/lede/0060-ar71xx-add-unaligned-access-hacks-for-VXLAN.patch @@ -0,0 +1,130 @@ +From: Matthias Schiffer +Date: Wed, 24 Jan 2018 21:34:54 +0100 +Subject: ar71xx: add unaligned access hacks for VXLAN + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch +index f766850aebcbd53e6b0e94e654068afe8f5a81c4..d0cc7c52c06522ab2cad5bc3c14f06ad1530fc20 100644 +--- a/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch ++++ b/target/linux/ar71xx/patches-4.4/910-unaligned_access_hacks.patch +@@ -929,3 +929,119 @@ + }; + if (skb->ip_summed != CHECKSUM_PARTIAL) { + *sum = csum_fold(csum_partial(diff, sizeof(diff), ++--- a/drivers/net/vxlan.c +++++ b/drivers/net/vxlan.c ++@@ -1759,8 +1759,8 @@ static int vxlan6_xmit_skb(struct dst_en ++ } ++ ++ vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); ++- vxh->vx_flags = htonl(VXLAN_HF_VNI); ++- vxh->vx_vni = vni; +++ net_hdr_word(&vxh->vx_flags) = htonl(VXLAN_HF_VNI); +++ net_hdr_word(&vxh->vx_vni) = vni; ++ ++ if (type & SKB_GSO_TUNNEL_REMCSUM) { ++ u32 data = (skb_checksum_start_offset(skb) - hdrlen) >> ++@@ -1769,8 +1769,8 @@ static int vxlan6_xmit_skb(struct dst_en ++ if (skb->csum_offset == offsetof(struct udphdr, check)) ++ data |= VXLAN_RCO_UDP; ++ ++- vxh->vx_vni |= htonl(data); ++- vxh->vx_flags |= htonl(VXLAN_HF_RCO); +++ net_hdr_word(&vxh->vx_vni) |= htonl(data); +++ net_hdr_word(&vxh->vx_flags) |= htonl(VXLAN_HF_RCO); ++ ++ if (!skb_is_gso(skb)) { ++ skb->ip_summed = CHECKSUM_NONE; ++@@ -1838,8 +1838,8 @@ static int vxlan_xmit_skb(struct rtable ++ return PTR_ERR(skb); ++ ++ vxh = (struct vxlanhdr *) __skb_push(skb, sizeof(*vxh)); ++- vxh->vx_flags = htonl(VXLAN_HF_VNI); ++- vxh->vx_vni = vni; +++ net_hdr_word(&vxh->vx_flags) = htonl(VXLAN_HF_VNI); +++ net_hdr_word(&vxh->vx_vni) = vni; ++ ++ if (type & SKB_GSO_TUNNEL_REMCSUM) { ++ u32 data = (skb_checksum_start_offset(skb) - hdrlen) >> ++@@ -1848,8 +1848,8 @@ static int vxlan_xmit_skb(struct rtable ++ if (skb->csum_offset == offsetof(struct udphdr, check)) ++ data |= VXLAN_RCO_UDP; ++ ++- vxh->vx_vni |= htonl(data); ++- vxh->vx_flags |= htonl(VXLAN_HF_RCO); +++ net_hdr_word(&vxh->vx_vni) |= htonl(data); +++ net_hdr_word(&vxh->vx_flags) |= htonl(VXLAN_HF_RCO); ++ ++ if (!skb_is_gso(skb)) { ++ skb->ip_summed = CHECKSUM_NONE; ++--- a/include/linux/etherdevice.h +++++ b/include/linux/etherdevice.h ++@@ -409,7 +409,7 @@ static inline bool is_etherdev_addr(cons ++ * @b: Pointer to Ethernet header ++ * ++ * Compare two Ethernet headers, returns 0 if equal. ++- * This assumes that the network header (i.e., IP header) is 4-byte +++ * This assumes that the network header (i.e., IP header) is 2-byte ++ * aligned OR the platform can handle unaligned access. This is the ++ * case for all packets coming into netif_receive_skb or similar ++ * entry points. ++@@ -432,11 +432,12 @@ static inline unsigned long compare_ethe ++ fold |= *(unsigned long *)(a + 6) ^ *(unsigned long *)(b + 6); ++ return fold; ++ #else ++- u32 *a32 = (u32 *)((u8 *)a + 2); ++- u32 *b32 = (u32 *)((u8 *)b + 2); +++ const u16 *a16 = a; +++ const u16 *b16 = b; ++ ++- return (*(u16 *)a ^ *(u16 *)b) | (a32[0] ^ b32[0]) | ++- (a32[1] ^ b32[1]) | (a32[2] ^ b32[2]); +++ return (a16[0] ^ b16[0]) | (a16[1] ^ b16[1]) | (a16[2] ^ b16[2]) | +++ (a16[3] ^ b16[3]) | (a16[4] ^ b16[4]) | (a16[5] ^ b16[5]) | +++ (a16[6] ^ b16[6]); ++ #endif ++ } ++ ++--- a/net/ipv4/tcp_offload.c +++++ b/net/ipv4/tcp_offload.c ++@@ -221,7 +221,7 @@ struct sk_buff **tcp_gro_receive(struct ++ ++ th2 = tcp_hdr(p); ++ ++- if (*(u32 *)&th->source ^ *(u32 *)&th2->source) { +++ if (net_hdr_word(&th->source) ^ net_hdr_word(&th2->source)) { ++ NAPI_GRO_CB(p)->same_flow = 0; ++ continue; ++ } ++@@ -239,8 +239,8 @@ found: ++ ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH)); ++ flush |= (__force int)(th->ack_seq ^ th2->ack_seq); ++ for (i = sizeof(*th); i < thlen; i += 4) ++- flush |= *(u32 *)((u8 *)th + i) ^ ++- *(u32 *)((u8 *)th2 + i); +++ flush |= net_hdr_word((u8 *)th + i) ^ +++ net_hdr_word((u8 *)th2 + i); ++ ++ mss = skb_shinfo(p)->gso_size; ++ ++--- a/net/ipv6/netfilter/ip6table_mangle.c +++++ b/net/ipv6/netfilter/ip6table_mangle.c ++@@ -55,7 +55,7 @@ ip6t_mangle_out(struct sk_buff *skb, con ++ hop_limit = ipv6_hdr(skb)->hop_limit; ++ ++ /* flowlabel and prio (includes version, which shouldn't change either */ ++- flowlabel = *((u_int32_t *)ipv6_hdr(skb)); +++ flowlabel = net_hdr_word(ipv6_hdr(skb)); ++ ++ ret = ip6t_do_table(skb, state, state->net->ipv6.ip6table_mangle); ++ ++@@ -64,7 +64,7 @@ ip6t_mangle_out(struct sk_buff *skb, con ++ !ipv6_addr_equal(&ipv6_hdr(skb)->daddr, &daddr) || ++ skb->mark != mark || ++ ipv6_hdr(skb)->hop_limit != hop_limit || ++- flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) { +++ flowlabel != net_hdr_word(ipv6_hdr(skb)))) { ++ err = ip6_route_me_harder(state->net, skb); ++ if (err < 0) ++ ret = NF_DROP_ERR(err); diff --git a/patches/lede/0061-netifd-system-linux-VXLAN-add-options-to-enable-and-disable-UDP-checksums.patch b/patches/lede/0061-netifd-system-linux-VXLAN-add-options-to-enable-and-disable-UDP-checksums.patch new file mode 100644 index 00000000..887a6e74 --- /dev/null +++ b/patches/lede/0061-netifd-system-linux-VXLAN-add-options-to-enable-and-disable-UDP-checksums.patch @@ -0,0 +1,75 @@ +From: Matthias Schiffer +Date: Wed, 24 Jan 2018 20:53:32 +0100 +Subject: netifd: system-linux: VXLAN: add options to enable and disable UDP checksums + +diff --git a/package/network/config/netifd/patches/0002-system-linux-VXLAN-add-options-to-enable-and-disable.patch b/package/network/config/netifd/patches/0002-system-linux-VXLAN-add-options-to-enable-and-disable.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..67a8bb864be37fa97dfcce4dd841bacafefcd0fc +--- /dev/null ++++ b/package/network/config/netifd/patches/0002-system-linux-VXLAN-add-options-to-enable-and-disable.patch +@@ -0,0 +1,65 @@ ++From af3cadb6a46ba93e8a729e71d82b176275931e62 Mon Sep 17 00:00:00 2001 ++Message-Id: ++From: Matthias Schiffer ++Date: Wed, 24 Jan 2018 13:21:44 +0100 ++Subject: [PATCH] system-linux: VXLAN: add options to enable and disable UDP ++ checksums ++ ++Signed-off-by: Matthias Schiffer ++--- ++ system-linux.c | 11 +++++++++++ ++ system.c | 2 ++ ++ system.h | 2 ++ ++ 3 files changed, 15 insertions(+) ++ ++diff --git a/system-linux.c b/system-linux.c ++index 32d6ffc..0277886 100644 ++--- a/system-linux.c +++++ b/system-linux.c ++@@ -2841,6 +2841,17 @@ static int system_add_vxlan(const char *name, const unsigned int link, struct bl ++ } ++ nla_put_u16(msg, IFLA_VXLAN_PORT, htons(port)); ++ +++ if ((cur = tb_data[VXLAN_DATA_ATTR_RXCSUM])) { +++ bool rxcsum = blobmsg_get_bool(cur); +++ nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, !rxcsum); +++ } +++ +++ if ((cur = tb_data[VXLAN_DATA_ATTR_TXCSUM])) { +++ bool txcsum = blobmsg_get_bool(cur); +++ nla_put_u8(msg, IFLA_VXLAN_UDP_CSUM, txcsum); +++ nla_put_u8(msg, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, !txcsum); +++ } +++ ++ if ((cur = tb[TUNNEL_ATTR_TOS])) { ++ char *str = blobmsg_get_string(cur); ++ unsigned tos = 1; ++diff --git a/system.c b/system.c ++index 5555272..e236e96 100644 ++--- a/system.c +++++ b/system.c ++@@ -36,6 +36,8 @@ static const struct blobmsg_policy vxlan_data_attrs[__VXLAN_DATA_ATTR_MAX] = { ++ [VXLAN_DATA_ATTR_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 }, ++ [VXLAN_DATA_ATTR_PORT] = { .name = "port", .type = BLOBMSG_TYPE_INT32 }, ++ [VXLAN_DATA_ATTR_MACADDR] = { .name = "macaddr", .type = BLOBMSG_TYPE_STRING }, +++ [VXLAN_DATA_ATTR_RXCSUM] = { .name = "rxcsum", .type = BLOBMSG_TYPE_BOOL }, +++ [VXLAN_DATA_ATTR_TXCSUM] = { .name = "txcsum", .type = BLOBMSG_TYPE_BOOL }, ++ }; ++ ++ const struct uci_blob_param_list vxlan_data_attr_list = { ++diff --git a/system.h b/system.h ++index 61c72c2..371a524 100644 ++--- a/system.h +++++ b/system.h ++@@ -41,6 +41,8 @@ enum vxlan_data { ++ VXLAN_DATA_ATTR_ID, ++ VXLAN_DATA_ATTR_PORT, ++ VXLAN_DATA_ATTR_MACADDR, +++ VXLAN_DATA_ATTR_RXCSUM, +++ VXLAN_DATA_ATTR_TXCSUM, ++ __VXLAN_DATA_ATTR_MAX ++ }; ++ ++-- ++2.16.1 ++ diff --git a/patches/lede/0062-vxlan-add-options-to-enable-and-disable-UDP-checksums.patch b/patches/lede/0062-vxlan-add-options-to-enable-and-disable-UDP-checksums.patch new file mode 100644 index 00000000..123177c6 --- /dev/null +++ b/patches/lede/0062-vxlan-add-options-to-enable-and-disable-UDP-checksums.patch @@ -0,0 +1,43 @@ +From: Matthias Schiffer +Date: Wed, 24 Jan 2018 13:51:45 +0100 +Subject: vxlan: add options to enable and disable UDP checksums + +Signed-off-by: Matthias Schiffer + +diff --git a/package/network/config/vxlan/Makefile b/package/network/config/vxlan/Makefile +index a471d4e90cbe30c1d1dd01dbf7553995d8c0485e..aeceb9cd884e517b2f274925637b62a538bfa70e 100644 +--- a/package/network/config/vxlan/Makefile ++++ b/package/network/config/vxlan/Makefile +@@ -1,7 +1,7 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=vxlan +-PKG_VERSION:=1 ++PKG_VERSION:=2 + PKG_LICENSE:=GPL-2.0 + + include $(INCLUDE_DIR)/package.mk +diff --git a/package/network/config/vxlan/files/vxlan.sh b/package/network/config/vxlan/files/vxlan.sh +index 27ccd8f12759f69c7c226cac0c923335b8ccc6a8..d055d41edc59f50c0c132849bbcd0235edeef5b9 100755 +--- a/package/network/config/vxlan/files/vxlan.sh ++++ b/package/network/config/vxlan/files/vxlan.sh +@@ -15,8 +15,8 @@ vxlan_generic_setup() { + + local link="$cfg" + +- local port vid ttl tos mtu macaddr zone +- json_get_vars port vid ttl tos mtu macaddr zone ++ local port vid ttl tos mtu macaddr zone rxcsum txcsum ++ json_get_vars port vid ttl tos mtu macaddr zone rxcsum txcsum + + + proto_init_update "$link" 1 +@@ -36,6 +36,8 @@ vxlan_generic_setup() { + [ -n "$port" ] && json_add_int port "$port" + [ -n "$vid" ] && json_add_int id "$vid" + [ -n "$macaddr" ] && json_add_string macaddr "$macaddr" ++ [ -n "$rxcsum" ] && json_add_boolean rxcsum "$rxcsum" ++ [ -n "$txcsum" ] && json_add_boolean txcsum "$txcsum" + json_close_object + + proto_close_tunnel diff --git a/patches/lede/0063-ramips-mtd-spi-nor-add-support-for-switching-between-3-byte-and-4-byte-addressing-on-w25q256-flash.patch b/patches/lede/0063-ramips-mtd-spi-nor-add-support-for-switching-between-3-byte-and-4-byte-addressing-on-w25q256-flash.patch new file mode 100644 index 00000000..db75be88 --- /dev/null +++ b/patches/lede/0063-ramips-mtd-spi-nor-add-support-for-switching-between-3-byte-and-4-byte-addressing-on-w25q256-flash.patch @@ -0,0 +1,456 @@ +From: Vincent Wiemann +Date: Sat, 6 Jan 2018 04:33:09 +0100 +Subject: ramips: mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash + +CAUTION! NEEDS TESTING! +Tries to backport switching between 3-byte and 4-byte addressing on w25q256 flash from Lede master (62ede4f78389c313a8004e79330a7d055eda2f7d) by Felix Fietkau. + +Applied patches: +mtd: spi-nor: rename SPINOR_OP_* macros of the 4-byte address op codes +mtd: spi-nor: add a stateless method to support memory size above 128Mib +mtd: spi-nor: add w25q256 3b-mode-switch +mtd: add chunked read-io to m25p80 + +On some devices the flash chip needs to be in 3-byte addressing mode during +reboot, otherwise the boot loader will fail to start. +This mode however does not allow regular reads/writes onto the upper 16M +half. W25Q256 has separate read commands for reading from >16M, however +it does not have any separate write commands. +This patch changes the code to leave the chip in 3-byte mode most of the +time and only switch during erase/write cycles that go to >16M +addresses. + +Signed-off-by: Vincent Wiemann (me@bibbl.com) + +diff --git a/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..5399f547e4edd0eb1cfee8c1ec5b35e69c692ee9 +--- /dev/null ++++ b/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch +@@ -0,0 +1,399 @@ ++--- a/drivers/mtd/devices/serial_flash_cmds.h +++++ b/drivers/mtd/devices/serial_flash_cmds.h ++@@ -18,19 +18,12 @@ ++ #define SPINOR_OP_RDVCR 0x85 ++ ++ /* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */ ++-#define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */ ++-#define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O READ */ ++- ++ #define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */ ++ #define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */ ++ #define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */ ++ #define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */ ++ #define SPINOR_OP_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */ ++ ++-/* READ commands with 32-bit addressing */ ++-#define SPINOR_OP_READ4_1_2_2 0xbc ++-#define SPINOR_OP_READ4_1_4_4 0xec ++- ++ /* Configuration flags */ ++ #define FLASH_FLAG_SINGLE 0x000000ff ++ #define FLASH_FLAG_READ_WRITE 0x00000001 ++--- a/drivers/mtd/devices/st_spi_fsm.c +++++ b/drivers/mtd/devices/st_spi_fsm.c ++@@ -507,13 +507,13 @@ static struct seq_rw_config n25q_read3_c ++ * - 'FAST' variants configured for 8 dummy cycles (see note above.) ++ */ ++ static struct seq_rw_config n25q_read4_configs[] = { ++- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0}, ++- {0x00, 0, 0, 0, 0, 0x00, 0, 0}, +++ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0}, +++ {0x00, 0, 0, 0, 0, 0x00, 0, 0}, ++ }; ++ ++ /* ++@@ -553,13 +553,13 @@ static int stfsm_mx25_en_32bit_addr_seq( ++ * entering a state that is incompatible with the SPIBoot Controller. ++ */ ++ static struct seq_rw_config stfsm_s25fl_read4_configs[] = { ++- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4}, ++- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0}, ++- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8}, ++- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0}, ++- {0x00, 0, 0, 0, 0, 0x00, 0, 0}, +++ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 2, 4}, +++ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 4, 0}, +++ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8}, +++ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0}, +++ {0x00, 0, 0, 0, 0, 0x00, 0, 0}, ++ }; ++ ++ static struct seq_rw_config stfsm_s25fl_write4_configs[] = { ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -69,6 +69,14 @@ struct flash_info { ++ #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ ++ #define USE_FSR 0x80 /* use flag status register */ ++ #define SPI_NOR_HAS_LOCK 0x100 /* Flash supports lock/unlock via SR */ +++#define SPI_NOR_4B_OPCODES 0x200 /* +++ * Use dedicated 4byte address op codes +++ * to support memory size above 128Mib. +++ */ +++#define SPI_NOR_4B_READ_OP 0x400 /* +++ * Like SPI_NOR_4B_OPCODES, but for read +++ * op code only. +++ */ ++ }; ++ ++ #define JEDEC_MFR(info) ((info)->id[0]) ++@@ -182,6 +190,89 @@ static inline struct spi_nor *mtd_to_spi ++ return mtd->priv; ++ } ++ +++ +++static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size) +++{ +++ size_t i; +++ +++ for (i = 0; i < size; i++) +++ if (table[i][0] == opcode) +++ return table[i][1]; +++ +++ /* No conversion found, keep input op code. */ +++ return opcode; +++} +++ +++static inline u8 spi_nor_convert_3to4_read(u8 opcode) +++{ +++ static const u8 spi_nor_3to4_read[][2] = { +++ { SPINOR_OP_READ, SPINOR_OP_READ_4B }, +++ { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B }, +++ { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B }, +++ { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B }, +++ { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B }, +++ { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B }, +++ }; +++ +++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_read, +++ ARRAY_SIZE(spi_nor_3to4_read)); +++} +++ +++static inline u8 spi_nor_convert_3to4_program(u8 opcode) +++{ +++ static const u8 spi_nor_3to4_program[][2] = { +++ { SPINOR_OP_PP, SPINOR_OP_PP_4B }, +++ { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B }, +++ { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B }, +++ }; +++ +++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_program, +++ ARRAY_SIZE(spi_nor_3to4_program)); +++} +++ +++static inline u8 spi_nor_convert_3to4_erase(u8 opcode) +++{ +++ static const u8 spi_nor_3to4_erase[][2] = { +++ { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B }, +++ { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B }, +++ { SPINOR_OP_SE, SPINOR_OP_SE_4B }, +++ }; +++ +++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase, +++ ARRAY_SIZE(spi_nor_3to4_erase)); +++} +++ +++static void spi_nor_set_4byte_read(struct spi_nor *nor, +++ const struct flash_info *info) +++{ +++ nor->addr_width = 3; +++ nor->ext_addr = 0; +++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); +++ nor->flags |= SNOR_F_4B_EXT_ADDR; +++} +++ +++ +++ +++static void spi_nor_set_4byte_opcodes(struct spi_nor *nor, +++ const struct flash_info *info) +++{ +++ /* Do some manufacturer fixups first */ +++ switch (JEDEC_MFR(info)) { +++ case SNOR_MFR_SPANSION: +++ /* No small sector erase for 4-byte command set */ +++ nor->erase_opcode = SPINOR_OP_SE; +++ nor->mtd.erasesize = info->sector_size; +++ break; +++ +++ default: +++ break; +++ } +++ +++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode); +++ nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode); +++ nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode); +++} +++ ++ /* Enable/disable 4-byte addressing mode. */ ++ static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, ++ int enable) ++@@ -313,6 +404,36 @@ static void spi_nor_unlock_and_unprep(st ++ mutex_unlock(&nor->lock); ++ } ++ +++static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr) +++{ +++ bool ext_addr; +++ int ret; +++ u8 cmd; +++ +++ if (!(nor->flags & SNOR_F_4B_EXT_ADDR)) +++ return 0; +++ +++ ext_addr = !!(addr & 0xff000000); +++ if (nor->ext_addr == ext_addr) +++ return 0; +++ +++ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; +++ write_enable(nor); +++ ret = nor->write_reg(nor, cmd, NULL, 0); +++ if (ret) +++ return ret; +++ +++ cmd = 0; +++ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1); +++ if (ret) +++ return ret; +++ +++ nor->addr_width = 3 + ext_addr; +++ nor->ext_addr = ext_addr; +++ write_disable(nor); +++ return 0; +++} +++ ++ /* ++ * Erase an address range on the nor chip. The address range may extend ++ * one or more erase sectors. Return an error is there is a problem erasing. ++@@ -338,6 +459,10 @@ static int spi_nor_erase(struct mtd_info ++ if (ret) ++ return ret; ++ +++ ret = spi_nor_check_ext_addr(nor, addr + len); +++ if (ret) +++ return ret; +++ ++ /* whole-chip erase? */ ++ if (len == mtd->size) { ++ unsigned long timeout; ++@@ -396,6 +521,7 @@ static int spi_nor_erase(struct mtd_info ++ return ret; ++ ++ erase_err: +++ spi_nor_check_ext_addr(nor, 0); ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); ++ instr->state = MTD_ERASE_FAILED; ++ return ret; ++@@ -585,7 +711,9 @@ static int spi_nor_lock(struct mtd_info ++ if (ret) ++ return ret; ++ +++ spi_nor_check_ext_addr(nor, ofs + len); ++ ret = nor->flash_lock(nor, ofs, len); +++ spi_nor_check_ext_addr(nor, 0); ++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); ++ return ret; ++@@ -600,7 +728,9 @@ static int spi_nor_unlock(struct mtd_inf ++ if (ret) ++ return ret; ++ +++ spi_nor_check_ext_addr(nor, ofs + len); ++ ret = nor->flash_unlock(nor, ofs, len); +++ spi_nor_check_ext_addr(nor, 0); ++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); ++ return ret; ++@@ -851,7 +981,7 @@ static const struct flash_info spi_nor_i ++ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, ++ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, ++- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, +++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_READ_OP) }, ++ ++ /* Catalyst / On Semiconductor -- non-JEDEC */ ++ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, ++@@ -898,8 +1028,23 @@ static int spi_nor_read(struct mtd_info ++ if (ret) ++ return ret; ++ +++ if (nor->flags & SNOR_F_4B_EXT_ADDR) +++ nor->addr_width = 4; +++ ++ ret = nor->read(nor, from, len, retlen, buf); ++ +++ if (nor->flags & SNOR_F_4B_EXT_ADDR) { +++ u8 val = 0; +++ +++ if ((from + len) & 0xff000000) { +++ write_enable(nor); +++ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1); +++ write_disable(nor); +++ } +++ +++ nor->addr_width = 3; +++ } +++ ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); ++ return ret; ++ } ++@@ -988,6 +1133,10 @@ static int spi_nor_write(struct mtd_info ++ if (ret) ++ return ret; ++ +++ ret = spi_nor_check_ext_addr(nor, to + len); +++ if (ret < 0) +++ return ret; +++ ++ write_enable(nor); ++ ++ page_offset = to & (nor->page_size - 1); ++@@ -1018,6 +1167,7 @@ static int spi_nor_write(struct mtd_info ++ ++ ret = spi_nor_wait_till_ready(nor); ++ write_err: +++ spi_nor_check_ext_addr(nor, 0); ++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); ++ return ret; ++ } ++@@ -1366,27 +1516,12 @@ int spi_nor_scan(struct spi_nor *nor, co ++ else if (mtd->size > 0x1000000) { ++ /* enable 4-byte addressing if the device exceeds 16MiB */ ++ nor->addr_width = 4; ++- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { ++- /* Dedicated 4-byte command set */ ++- switch (nor->flash_read) { ++- case SPI_NOR_QUAD: ++- nor->read_opcode = SPINOR_OP_READ4_1_1_4; ++- break; ++- case SPI_NOR_DUAL: ++- nor->read_opcode = SPINOR_OP_READ4_1_1_2; ++- break; ++- case SPI_NOR_FAST: ++- nor->read_opcode = SPINOR_OP_READ4_FAST; ++- break; ++- case SPI_NOR_NORMAL: ++- nor->read_opcode = SPINOR_OP_READ4; ++- break; ++- } ++- nor->program_opcode = SPINOR_OP_PP_4B; ++- /* No small sector erase for 4-byte command set */ ++- nor->erase_opcode = SPINOR_OP_SE_4B; ++- mtd->erasesize = info->sector_size; ++- } else +++ if (info->flags & SPI_NOR_4B_READ_OP) +++ spi_nor_set_4byte_read(nor, info); +++ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION || +++ info->flags & SPI_NOR_4B_OPCODES) +++ spi_nor_set_4byte_opcodes(nor, info); +++ else ++ set_4byte(nor, info, 1); ++ } else { ++ nor->addr_width = 3; ++--- a/include/linux/mtd/spi-nor.h +++++ b/include/linux/mtd/spi-nor.h ++@@ -42,9 +42,13 @@ ++ #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ ++ #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ ++ #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ ++-#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ ++-#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ +++#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */ +++#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */ +++#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */ +++#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */ ++ #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ +++#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */ +++#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */ ++ #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ ++ #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ ++ #define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */ ++@@ -55,11 +59,17 @@ ++ #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ ++ ++ /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ ++-#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ ++-#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ ++-#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ ++-#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ +++#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */ +++#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */ +++#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */ +++#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */ +++#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */ +++#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */ ++ #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ +++#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */ +++#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */ +++#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */ +++#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */ ++ #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ ++ ++ /* Used for SST flashes only. */ ++@@ -70,6 +80,7 @@ ++ /* Used for Macronix and Winbond flashes. */ ++ #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ ++ #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ +++#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */ ++ ++ /* Used for Spansion flashes only. */ ++ #define SPINOR_OP_BRWR 0x17 /* Bank register write */ ++@@ -117,6 +128,7 @@ enum spi_nor_ops { ++ enum spi_nor_option_flags { ++ SNOR_F_USE_FSR = BIT(0), ++ SNOR_F_SST = BIT(1), +++ SNOR_F_4B_EXT_ADDR = BIT(5), ++ }; ++ ++ /** ++@@ -166,6 +178,7 @@ struct spi_nor { ++ enum read_mode flash_read; ++ bool sst_write_second; ++ u32 flags; +++ u8 ext_addr; ++ u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; ++ ++ int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); +diff --git a/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..b6111abad7063951c07688c66854fa743daeb6c6 +--- /dev/null ++++ b/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch +@@ -0,0 +1,21 @@ ++--- a/drivers/mtd/spi-nor/spi-nor.c +++++ b/drivers/mtd/spi-nor/spi-nor.c ++@@ -1176,6 +1176,7 @@ static int spi_nor_chunked_write(struct ++ size_t *_retlen, const u_char *_buf) ++ { ++ struct spi_nor *nor = mtd_to_spi_nor(mtd); +++ u32 addr_width = nor->addr_width + !!(nor->flags & SNOR_F_4B_EXT_ADDR); ++ int chunk_size; ++ int retlen = 0; ++ int ret; ++@@ -1184,8 +1185,8 @@ static int spi_nor_chunked_write(struct ++ if (!chunk_size) ++ chunk_size = _len; ++ ++- if (nor->addr_width > 3) ++- chunk_size -= nor->addr_width - 3; +++ if (addr_width > 3) +++ chunk_size -= addr_width - 3; ++ ++ while (retlen < _len) { ++ size_t len = min_t(int, chunk_size, _len - retlen); diff --git a/patches/lede/0064-ramips-prepare-ZBT-WG3526-for-hardware-variants.patch b/patches/lede/0064-ramips-prepare-ZBT-WG3526-for-hardware-variants.patch new file mode 100644 index 00000000..00b54070 --- /dev/null +++ b/patches/lede/0064-ramips-prepare-ZBT-WG3526-for-hardware-variants.patch @@ -0,0 +1,99 @@ +From: Mathias Kresin +Date: Fri, 7 Apr 2017 23:52:27 +0200 +Subject: ramips: prepare ZBT-WG3526 for hardware variants + +The ZBT-WG3526 is available with 16 or 32 MByte of flash. Rename the +current supported 16MByte version to indicate which flash size variant +is supported. + +Signed-off-by: Mathias Kresin + +Conflicts (Resolved): + target/linux/ramips/image/mt7621.mk + +Signed-off-by: Vincent Wiemann + +further adjustments for backport to lede-17.01 branch + +Signed-off-by: Andreas Ziegler + +diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh +index b1091f66b2897a19bd01d4a26a1b3647656fa62b..8e27a79fc1744d6bed9db8d930207c418899cab1 100755 +--- a/target/linux/ramips/base-files/lib/ramips.sh ++++ b/target/linux/ramips/base-files/lib/ramips.sh +@@ -637,8 +637,8 @@ ramips_board_detect() { + *"ZBT-WG2626") + name="zbt-wg2626" + ;; +- *"ZBT-WG3526") +- name="zbt-wg3526" ++ *"ZBT-WG3526 (16M)") ++ name="zbt-wg3526-16M" + ;; + *"ZBT-WR8305RT") + name="zbt-wr8305rt" +diff --git a/target/linux/ramips/dts/ZBT-WG3526-16M.dts b/target/linux/ramips/dts/ZBT-WG3526-16M.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..fb644502071d6641194c66baf552035937f35669 +--- /dev/null ++++ b/target/linux/ramips/dts/ZBT-WG3526-16M.dts +@@ -0,0 +1,15 @@ ++/dts-v1/; ++ ++#include "ZBT-WG3526.dtsi" ++ ++/ { ++ model = "ZBT-WG3526 (16M)"; ++}; ++ ++&firmware { ++ reg = <0x50000 0xfb0000>; ++}; ++ ++&status_led { ++ label = "zbt-wg3526:green:status"; ++}; +diff --git a/target/linux/ramips/dts/ZBT-WG3526.dts b/target/linux/ramips/dts/ZBT-WG3526.dts +deleted file mode 100644 +index c361bdd827bffdc24405b1a1b191403ebeec46d0..0000000000000000000000000000000000000000 +--- a/target/linux/ramips/dts/ZBT-WG3526.dts ++++ /dev/null +@@ -1,15 +0,0 @@ +-/dts-v1/; +- +-#include "ZBT-WG3526.dtsi" +- +-/ { +- model = "ZBT-WG3526"; +-}; +- +-&firmware { +- reg = <0x50000 0xfb0000>; +-}; +- +-&status_led { +- label = "zbt-wg3526:green:status"; +-}; +diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk +index 8218bea84410536151a216cd2cc0300369ad977a..cabc86b28eb040f0d1e58d917e6edc4a97e80db7 100644 +--- a/target/linux/ramips/image/mt7621.mk ++++ b/target/linux/ramips/image/mt7621.mk +@@ -226,13 +226,14 @@ define Device/zbt-wg2626 + endef + TARGET_DEVICES += zbt-wg2626 + +-define Device/zbt-wg3526 +- DTS := ZBT-WG3526 ++define Device/zbt-wg3526-16M ++ DTS := ZBT-WG3526-16M + IMAGE_SIZE := $(ralink_default_fw_size_16M) +- DEVICE_TITLE := ZBT WG3526 ++ SUPPORTED_DEVICES += zbt-wg3526 ++ DEVICE_TITLE := ZBT WG3526 (16MB flash) + DEVICE_PACKAGES := kmod-usb3 kmod-usb-ledtrig-usbport kmod-ata-core kmod-ata-ahci + endef +-TARGET_DEVICES += zbt-wg3526 ++TARGET_DEVICES += zbt-wg3526-16M + + # FIXME: is this still needed? + define Image/Prepare diff --git a/patches/lede/0065-ramips-rename-Digineo-AC1200-Pro-to-ZBT-WG3526-32MB.patch b/patches/lede/0065-ramips-rename-Digineo-AC1200-Pro-to-ZBT-WG3526-32MB.patch new file mode 100644 index 00000000..e87812e7 --- /dev/null +++ b/patches/lede/0065-ramips-rename-Digineo-AC1200-Pro-to-ZBT-WG3526-32MB.patch @@ -0,0 +1,193 @@ +From: Mathias Kresin +Date: Sat, 1 Apr 2017 10:46:44 +0200 +Subject: ramips: rename Digineo AC1200 Pro to ZBT-WG3526 32MB + +The Digineo AC1200 Pro is the 32MB flash variant of the ZBT-WG3526 with +unpopulated/exposed sdhci slot. Rename to board to the OEM/ODM name and +add the sdhci kernel module to use it for multiple clones. + +Signed-off-by: Mathias Kresin + +Conflicts (Resolved): + target/linux/ramips/base-files/etc/diag.sh + +Signed-off-by: Vincent Wiemann + +further adjustments for backport to lede-17.01 branch + +Signed-off-by: Andreas Ziegler + +diff --git a/target/linux/ramips/base-files/etc/board.d/02_network b/target/linux/ramips/base-files/etc/board.d/02_network +index 5a4042339c6761703578e014612062ac78babd9d..b9c8fe774fedab34267a8635033b9235d9d6c3aa 100755 +--- a/target/linux/ramips/base-files/etc/board.d/02_network ++++ b/target/linux/ramips/base-files/etc/board.d/02_network +@@ -70,7 +70,6 @@ ramips_setup_interfaces() + ucidef_set_interface_lan "eth0.2" + ;; + 3g-6200n|\ +- ac1200pro|\ + ai-br100|\ + d240|\ + db-wrt01|\ +diff --git a/target/linux/ramips/base-files/etc/diag.sh b/target/linux/ramips/base-files/etc/diag.sh +index 9dbd6c4141d7facef2108cbb5cf3a7057522c88e..c4f521954c74635c61f42558f0d9b71f0f671c22 100644 +--- a/target/linux/ramips/base-files/etc/diag.sh ++++ b/target/linux/ramips/base-files/etc/diag.sh +@@ -59,7 +59,10 @@ get_status_led() { + wn3000rpv3) + status_led="$board:red:power" + ;; +- ac1200pro|\ ++ ai-br100|\ ++ ht-tm02) ++ status_led="$board:blue:wlan" ++ ;; + all0239-3g|\ + dcs-930|\ + dir-300-b1|\ +@@ -85,10 +88,6 @@ get_status_led() { + zbt-wg3526) + status_led="$board:green:status" + ;; +- ai-br100|\ +- ht-tm02) +- status_led="$board:blue:wlan" +- ;; + atp-52b|\ + ip2202) + status_led="$board:green:run" +diff --git a/target/linux/ramips/base-files/lib/ramips.sh b/target/linux/ramips/base-files/lib/ramips.sh +index 8e27a79fc1744d6bed9db8d930207c418899cab1..b9279a5a1e9baf55ca7f59dbb22ac0b0b7b01db4 100755 +--- a/target/linux/ramips/base-files/lib/ramips.sh ++++ b/target/linux/ramips/base-files/lib/ramips.sh +@@ -130,9 +130,6 @@ ramips_board_detect() { + *"DCS-930L B1") + name="dcs-930l-b1" + ;; +- *"Digineo AC1200 Pro") +- name="ac1200pro" +- ;; + *"DIR-300 B1") + name="dir-300-b1" + ;; +@@ -640,6 +637,9 @@ ramips_board_detect() { + *"ZBT-WG3526 (16M)") + name="zbt-wg3526-16M" + ;; ++ *"ZBT-WG3526 (32M)") ++ name="zbt-wg3526-32M" ++ ;; + *"ZBT-WR8305RT") + name="zbt-wr8305rt" + ;; +diff --git a/target/linux/ramips/base-files/lib/upgrade/platform.sh b/target/linux/ramips/base-files/lib/upgrade/platform.sh +index d3efc2dd37ed855a1c0e966e448b67ae73324d5f..a45275077df8fa317c38adc8f0ab12fd4b0ecb83 100755 +--- a/target/linux/ramips/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ramips/base-files/lib/upgrade/platform.sh +@@ -17,7 +17,6 @@ platform_check_image() { + 3g150b|\ + 3g300m|\ + a5-v11|\ +- ac1200pro|\ + ai-br100|\ + air3gii|\ + all0239-3g|\ +diff --git a/target/linux/ramips/dts/AC1200pro.dts b/target/linux/ramips/dts/AC1200pro.dts +deleted file mode 100644 +index fbec81844025cf2a6544dec8dfeca02fce89fdc1..0000000000000000000000000000000000000000 +--- a/target/linux/ramips/dts/AC1200pro.dts ++++ /dev/null +@@ -1,15 +0,0 @@ +-/dts-v1/; +- +-#include "ZBT-WG3526.dtsi" +- +-/ { +- model = "Digineo AC1200 Pro"; +-}; +- +-&firmware { +- reg = <0x50000 0x1fb0000>; +-}; +- +-&status_led { +- label = "ac1200pro:green:status"; +-}; +diff --git a/target/linux/ramips/dts/ZBT-WG3526-16M.dts b/target/linux/ramips/dts/ZBT-WG3526-16M.dts +index fb644502071d6641194c66baf552035937f35669..1e2f1525028f69468257cd8af8d5bad0319bc551 100644 +--- a/target/linux/ramips/dts/ZBT-WG3526-16M.dts ++++ b/target/linux/ramips/dts/ZBT-WG3526-16M.dts +@@ -9,7 +9,3 @@ + &firmware { + reg = <0x50000 0xfb0000>; + }; +- +-&status_led { +- label = "zbt-wg3526:green:status"; +-}; +diff --git a/target/linux/ramips/dts/ZBT-WG3526-32M.dts b/target/linux/ramips/dts/ZBT-WG3526-32M.dts +new file mode 100644 +index 0000000000000000000000000000000000000000..99a4b45824ba4ee6c1a1c81615291c8efde1a7ac +--- /dev/null ++++ b/target/linux/ramips/dts/ZBT-WG3526-32M.dts +@@ -0,0 +1,11 @@ ++/dts-v1/; ++ ++#include "ZBT-WG3526.dtsi" ++ ++/ { ++ model = "ZBT-WG3526 (32M)"; ++}; ++ ++&firmware { ++ reg = <0x50000 0x1fb0000>; ++}; +diff --git a/target/linux/ramips/dts/ZBT-WG3526.dtsi b/target/linux/ramips/dts/ZBT-WG3526.dtsi +index 582e42083920c465588f14e59e10eafe735640fb..5e195fb8120d3a66f19acf83c9f76bb4b1ec3e7e 100644 +--- a/target/linux/ramips/dts/ZBT-WG3526.dtsi ++++ b/target/linux/ramips/dts/ZBT-WG3526.dtsi +@@ -35,7 +35,8 @@ + gpio-leds { + compatible = "gpio-leds"; + +- status_led: status { ++ status { ++ label = "zbt-wg3526:green:status"; + gpios = <&gpio0 24 1>; + }; + }; +diff --git a/target/linux/ramips/image/mt7621.mk b/target/linux/ramips/image/mt7621.mk +index cabc86b28eb040f0d1e58d917e6edc4a97e80db7..aa84d78b9e42259cbee7de6c052fa7ab500a040a 100644 +--- a/target/linux/ramips/image/mt7621.mk ++++ b/target/linux/ramips/image/mt7621.mk +@@ -34,14 +34,6 @@ define Device/11acnas + endef + TARGET_DEVICES += 11acnas + +-define Device/ac1200pro +- DTS := AC1200pro +- IMAGE_SIZE := $(ralink_default_fw_size_32M) +- DEVICE_TITLE := Digineo AC1200 Pro +- DEVICE_PACKAGES := kmod-usb3 kmod-ata-core kmod-ata-ahci +-endef +-TARGET_DEVICES += ac1200pro +- + define Device/dir-860l-b1 + DTS := DIR-860L-B1 + BLOCKSIZE := 64k +@@ -235,6 +227,15 @@ define Device/zbt-wg3526-16M + endef + TARGET_DEVICES += zbt-wg3526-16M + ++define Device/zbt-wg3526-32M ++ DTS := ZBT-WG3526-32M ++ IMAGE_SIZE := $(ralink_default_fw_size_32M) ++ SUPPORTED_DEVICES += ac1200pro ++ DEVICE_TITLE := ZBT WG3526 (32MB flash) ++ DEVICE_PACKAGES := kmod-usb3 kmod-usb-ledtrig-usbport kmod-ata-core kmod-ata-ahci kmod-sdhci-mt7620 ++endef ++TARGET_DEVICES += zbt-wg3526-32M ++ + # FIXME: is this still needed? + define Image/Prepare + #define Build/Compile diff --git a/patches/lede/0066-kernel-bridge-ebtables-Avoid-resetting-limit-rule-state.patch b/patches/lede/0066-kernel-bridge-ebtables-Avoid-resetting-limit-rule-state.patch new file mode 100644 index 00000000..631637e8 --- /dev/null +++ b/patches/lede/0066-kernel-bridge-ebtables-Avoid-resetting-limit-rule-state.patch @@ -0,0 +1,63 @@ +From: Linus Lüssing +Date: Sun, 26 Nov 2017 05:19:21 +0100 +Subject: kernel: bridge: ebtables: Avoid resetting limit rule state + +Link: https://patchwork.ozlabs.org/patch/841210/ +Signed-off-by: Linus Lüssing + +diff --git a/target/linux/generic/patches-4.4/121-bridge-ebtables-Avoid-resetting-limit-rule-state.patch b/target/linux/generic/patches-4.4/121-bridge-ebtables-Avoid-resetting-limit-rule-state.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..417fdd75e543ebb6a3fdd56cb97fc83324eeb104 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/121-bridge-ebtables-Avoid-resetting-limit-rule-state.patch +@@ -0,0 +1,50 @@ ++From 535097827e437bfa1906ed3210e6504750f4342b Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Linus=20L=C3=BCssing?= ++Date: Sat, 25 Nov 2017 00:36:13 +0100 ++Subject: [PATCH] bridge: ebtables: Avoid resetting limit rule state ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++So far any changes with ebtables will reset the state of limit rules, ++leading to spikes in traffic. This is especially noticeable if changes ++are done frequently, for instance via a daemon. ++ ++This patch fixes this by bailing out from (re)setting if the limit ++rule was initialized before. ++ ++When sending packets every 250ms for 600s, with a ++"--limit 1/sec --limit-burst 50" rule and a command like this ++in the background: ++ ++$ ebtables -N VOIDCHAIN ++$ while true; do ebtables -F VOIDCHAIN; sleep 30; done ++ ++The results are: ++ ++Before: ~1600 packets ++After: 650 packets ++ ++Signed-off-by: Linus Lüssing ++--- ++ net/bridge/netfilter/ebt_limit.c | 4 ++++ ++ 1 file changed, 4 insertions(+) ++ ++diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c ++index 61a9f1be1263..f74b48633feb 100644 ++--- a/net/bridge/netfilter/ebt_limit.c +++++ b/net/bridge/netfilter/ebt_limit.c ++@@ -69,6 +69,10 @@ static int ebt_limit_mt_check(const struct xt_mtchk_param *par) ++ { ++ struct ebt_limit_info *info = par->matchinfo; ++ +++ /* Do not reset state on unrelated table changes */ +++ if (info->prev) +++ return 0; +++ ++ /* Check for overflow. */ ++ if (info->burst == 0 || ++ user2credits(info->avg * info->burst) < user2credits(info->avg)) { ++-- ++2.11.0 ++ diff --git a/patches/lede/0067-ebtables-add-support-for-ICMP-IGMP-type-matches.patch b/patches/lede/0067-ebtables-add-support-for-ICMP-IGMP-type-matches.patch new file mode 100644 index 00000000..c5b4de9a --- /dev/null +++ b/patches/lede/0067-ebtables-add-support-for-ICMP-IGMP-type-matches.patch @@ -0,0 +1,1183 @@ +From: Matthias Schiffer +Date: Sun, 4 Mar 2018 10:26:34 +0100 +Subject: ebtables: add support for ICMP/IGMP type matches + +Signed-off-by: Matthias Schiffer + +diff --git a/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch b/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..b6f42c6a4affc9bb04a6ac9269698e751a932f2a +--- /dev/null ++++ b/package/network/utils/ebtables/patches/301-0001-include-sync-linux-netfilter_bridge-ebt_ip.h-with-ke.patch +@@ -0,0 +1,56 @@ ++From 44fcc3392bb7d52df2ad52b8e9437255b8c29d5a Mon Sep 17 00:00:00 2001 ++Message-Id: <44fcc3392bb7d52df2ad52b8e9437255b8c29d5a.1520151963.git.mschiffer@universe-factory.net> ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sat, 3 Mar 2018 12:14:48 +0100 ++Subject: [PATCH ebtables 1/4] include: sync linux/netfilter_bridge/ebt_ip.h ++ with kernel ++ ++Signed-off-by: Matthias Schiffer ++--- ++ include/linux/netfilter_bridge/ebt_ip.h | 16 +++++++++++++--- ++ 1 file changed, 13 insertions(+), 3 deletions(-) ++ ++diff --git a/include/linux/netfilter_bridge/ebt_ip.h b/include/linux/netfilter_bridge/ebt_ip.h ++index c4bbc41b0ea4..46d6261370b0 100644 ++--- a/include/linux/netfilter_bridge/ebt_ip.h +++++ b/include/linux/netfilter_bridge/ebt_ip.h ++@@ -1,3 +1,4 @@ +++/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ ++ /* ++ * ebt_ip ++ * ++@@ -23,8 +24,10 @@ ++ #define EBT_IP_PROTO 0x08 ++ #define EBT_IP_SPORT 0x10 ++ #define EBT_IP_DPORT 0x20 +++#define EBT_IP_ICMP 0x40 +++#define EBT_IP_IGMP 0x80 ++ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ ++- EBT_IP_SPORT | EBT_IP_DPORT ) +++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP) ++ #define EBT_IP_MATCH "ip" ++ ++ /* the same values are used for the invflags */ ++@@ -37,8 +40,15 @@ struct ebt_ip_info { ++ __u8 protocol; ++ __u8 bitmask; ++ __u8 invflags; ++- __u16 sport[2]; ++- __u16 dport[2]; +++ union { +++ __u16 sport[2]; +++ __u8 icmp_type[2]; +++ __u8 igmp_type[2]; +++ }; +++ union { +++ __u16 dport[2]; +++ __u8 icmp_code[2]; +++ }; ++ }; ++ ++ #endif ++-- ++2.16.2 ++ +diff --git a/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch b/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..c3eaec4412fcaebffa84b409a0a66e2f714a0e8d +--- /dev/null ++++ b/package/network/utils/ebtables/patches/301-0002-Move-ICMP-type-handling-functions-from-ebt_ip6-to-us.patch +@@ -0,0 +1,465 @@ ++From e40c68fcf13e2244ab6c87844126167e998ccb56 Mon Sep 17 00:00:00 2001 ++Message-Id: ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sun, 4 Mar 2018 08:18:18 +0100 ++Subject: [PATCH ebtables 2/4] Move ICMP type handling functions from ebt_ip6 ++ to useful_functions.c ++ ++Allow using these functions for ebt_ip as well. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ extensions/ebt_ip6.c | 165 +++------------------------------------------------ ++ include/ebtables_u.h | 17 +++++- ++ useful_functions.c | 151 +++++++++++++++++++++++++++++++++++++++++++++- ++ 3 files changed, 174 insertions(+), 159 deletions(-) ++ ++diff --git a/extensions/ebt_ip6.c b/extensions/ebt_ip6.c ++index dd48547b0010..347797b4afe1 100644 ++--- a/extensions/ebt_ip6.c +++++ b/extensions/ebt_ip6.c ++@@ -11,9 +11,6 @@ ++ * ++ */ ++ ++-#include ++-#include ++-#include ++ #include ++ #include ++ #include ++@@ -51,13 +48,7 @@ static const struct option opts[] = ++ }; ++ ++ ++-struct icmpv6_names { ++- const char *name; ++- uint8_t type; ++- uint8_t code_min, code_max; ++-}; ++- ++-static const struct icmpv6_names icmpv6_codes[] = { +++static const struct ebt_icmp_names icmpv6_codes[] = { ++ { "destination-unreachable", 1, 0, 0xFF }, ++ { "no-route", 1, 0, 0 }, ++ { "communication-prohibited", 1, 1, 1 }, ++@@ -141,97 +132,6 @@ parse_port_range(const char *protocol, const char *portstring, uint16_t *ports) ++ free(buffer); ++ } ++ ++-static char* ++-parse_num(const char *str, long min, long max, long *num) ++-{ ++- char *end; ++- ++- errno = 0; ++- *num = strtol(str, &end, 10); ++- if (errno && (*num == LONG_MIN || *num == LONG_MAX)) { ++- ebt_print_error("Invalid number %s: %s", str, strerror(errno)); ++- return NULL; ++- } ++- if (min <= max) { ++- if (*num > max || *num < min) { ++- ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max); ++- return NULL; ++- } ++- } ++- if (*num == 0 && str == end) ++- return NULL; ++- return end; ++-} ++- ++-static char * ++-parse_range(const char *str, long min, long max, long num[]) ++-{ ++- char *next; ++- ++- next = parse_num(str, min, max, num); ++- if (next == NULL) ++- return NULL; ++- if (next && *next == ':') ++- next = parse_num(next+1, min, max, &num[1]); ++- else ++- num[1] = num[0]; ++- return next; ++-} ++- ++-static int ++-parse_icmpv6(const char *icmpv6type, uint8_t type[], uint8_t code[]) ++-{ ++- static const unsigned int limit = ARRAY_SIZE(icmpv6_codes); ++- unsigned int match = limit; ++- unsigned int i; ++- long number[2]; ++- ++- for (i = 0; i < limit; i++) { ++- if (strncasecmp(icmpv6_codes[i].name, icmpv6type, strlen(icmpv6type))) ++- continue; ++- if (match != limit) ++- ebt_print_error("Ambiguous ICMPv6 type `%s':" ++- " `%s' or `%s'?", ++- icmpv6type, icmpv6_codes[match].name, ++- icmpv6_codes[i].name); ++- match = i; ++- } ++- ++- if (match < limit) { ++- type[0] = type[1] = icmpv6_codes[match].type; ++- code[0] = icmpv6_codes[match].code_min; ++- code[1] = icmpv6_codes[match].code_max; ++- } else { ++- char *next = parse_range(icmpv6type, 0, 255, number); ++- if (!next) { ++- ebt_print_error("Unknown ICMPv6 type `%s'", ++- icmpv6type); ++- return -1; ++- } ++- type[0] = (uint8_t) number[0]; ++- type[1] = (uint8_t) number[1]; ++- switch (*next) { ++- case 0: ++- code[0] = 0; ++- code[1] = 255; ++- return 0; ++- case '/': ++- next = parse_range(next+1, 0, 255, number); ++- code[0] = (uint8_t) number[0]; ++- code[1] = (uint8_t) number[1]; ++- if (next == NULL) ++- return -1; ++- if (next && *next == 0) ++- return 0; ++- /* fallthrough */ ++- default: ++- ebt_print_error("unknown character %c", *next); ++- return -1; ++- } ++- } ++- return 0; ++-} ++- ++ static void print_port_range(uint16_t *ports) ++ { ++ if (ports[0] == ports[1]) ++@@ -240,58 +140,6 @@ static void print_port_range(uint16_t *ports) ++ printf("%d:%d ", ports[0], ports[1]); ++ } ++ ++-static void print_icmp_code(uint8_t *code) ++-{ ++- if (code[0] == code[1]) ++- printf("/%"PRIu8 " ", code[0]); ++- else ++- printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]); ++-} ++- ++-static void print_icmp_type(uint8_t *type, uint8_t *code) ++-{ ++- unsigned int i; ++- ++- if (type[0] != type[1]) { ++- printf("%"PRIu8 ":%" PRIu8, type[0], type[1]); ++- print_icmp_code(code); ++- return; ++- } ++- ++- for (i = 0; i < ARRAY_SIZE(icmpv6_codes); i++) { ++- if (icmpv6_codes[i].type != type[0]) ++- continue; ++- ++- if (icmpv6_codes[i].code_min == code[0] && ++- icmpv6_codes[i].code_max == code[1]) { ++- printf("%s ", icmpv6_codes[i].name); ++- return; ++- } ++- } ++- printf("%"PRIu8, type[0]); ++- print_icmp_code(code); ++-} ++- ++-static void print_icmpv6types(void) ++-{ ++- unsigned int i; ++- printf("Valid ICMPv6 Types:"); ++- ++- for (i=0; i < ARRAY_SIZE(icmpv6_codes); i++) { ++- if (i && icmpv6_codes[i].type == icmpv6_codes[i-1].type) { ++- if (icmpv6_codes[i].code_min == icmpv6_codes[i-1].code_min ++- && (icmpv6_codes[i].code_max ++- == icmpv6_codes[i-1].code_max)) ++- printf(" (%s)", icmpv6_codes[i].name); ++- else ++- printf("\n %s", icmpv6_codes[i].name); ++- } ++- else ++- printf("\n%s", icmpv6_codes[i].name); ++- } ++- printf("\n"); ++-} ++- ++ static void print_help() ++ { ++ printf( ++@@ -303,7 +151,9 @@ static void print_help() ++ "--ip6-sport [!] port[:port] : tcp/udp source port or port range\n" ++ "--ip6-dport [!] port[:port] : tcp/udp destination port or port range\n" ++ "--ip6-icmp-type [!] type[[:type]/code[:code]] : ipv6-icmp type/code or type/code range\n"); ++-print_icmpv6types(); +++ +++ printf("\nValid ICMPv6 Types:\n"); +++ ebt_print_icmp_types(icmpv6_codes, ARRAY_SIZE(icmpv6_codes)); ++ } ++ ++ static void init(struct ebt_entry_match *match) ++@@ -374,7 +224,9 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, ++ ipinfo->bitmask |= EBT_IP6_ICMP6; ++ if (ebt_check_inverse2(optarg)) ++ ipinfo->invflags |= EBT_IP6_ICMP6; ++- if (parse_icmpv6(optarg, ipinfo->icmpv6_type, ipinfo->icmpv6_code)) +++ if (ebt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes), +++ optarg, ipinfo->icmpv6_type, +++ ipinfo->icmpv6_code)) ++ return 0; ++ break; ++ ++@@ -493,7 +345,8 @@ static void print(const struct ebt_u_entry *entry, ++ printf("--ip6-icmp-type "); ++ if (ipinfo->invflags & EBT_IP6_ICMP6) ++ printf("! "); ++- print_icmp_type(ipinfo->icmpv6_type, ipinfo->icmpv6_code); +++ ebt_print_icmp_type(icmpv6_codes, ARRAY_SIZE(icmpv6_codes), +++ ipinfo->icmpv6_type, ipinfo->icmpv6_code); ++ } ++ } ++ ++diff --git a/include/ebtables_u.h b/include/ebtables_u.h ++index 35a5bcc54c86..17afa9487f5a 100644 ++--- a/include/ebtables_u.h +++++ b/include/ebtables_u.h ++@@ -222,6 +222,15 @@ struct ebt_u_target ++ struct ebt_u_target *next; ++ }; ++ +++ +++struct ebt_icmp_names { +++ const char *name; +++ uint8_t type; +++ uint8_t code_min, code_max; +++}; +++ +++ +++ ++ /* libebtc.c */ ++ ++ extern struct ebt_u_table *ebt_tables; ++@@ -300,11 +309,17 @@ void ebt_print_mac_and_mask(const unsigned char *mac, const unsigned char *mask) ++ int ebt_get_mac_and_mask(const char *from, unsigned char *to, unsigned char *mask); ++ void ebt_parse_ip_address(char *address, uint32_t *addr, uint32_t *msk); ++ char *ebt_mask_to_dotted(uint32_t mask); ++-void ebt_parse_ip6_address(char *address, struct in6_addr *addr, +++void ebt_parse_ip6_address(char *address, struct in6_addr *addr, ++ struct in6_addr *msk); ++ char *ebt_ip6_to_numeric(const struct in6_addr *addrp); ++ char *ebt_ip6_mask_to_string(const struct in6_addr *msk); ++ +++int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, +++ const char *icmptype, uint8_t type[], uint8_t code[]); +++void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes, +++ size_t n_codes, uint8_t *type, uint8_t *code); +++void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes, +++ size_t n_codes); ++ ++ int do_command(int argc, char *argv[], int exec_style, ++ struct ebt_u_replace *replace_); ++diff --git a/useful_functions.c b/useful_functions.c ++index d14cbe9dbdba..8f54bae83fae 100644 ++--- a/useful_functions.c +++++ b/useful_functions.c ++@@ -24,6 +24,9 @@ ++ */ ++ #include "include/ebtables_u.h" ++ #include "include/ethernetdb.h" +++#include +++#include +++#include ++ #include ++ #include ++ #include ++@@ -34,6 +37,7 @@ ++ #include ++ #include ++ +++ ++ const unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0}; ++ const unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0}; ++ const unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0}; ++@@ -188,7 +192,7 @@ static int undot_ip(char *ip, unsigned char *ip2) ++ return -1; ++ *q = '\0'; ++ onebyte = strtol(p, &end, 10); ++- if (*end != '\0' || onebyte > 255 || onebyte < 0) +++ if (*end != '\0' || onebyte > 255 || onebyte < 0) ++ return -1; ++ ip2[i] = (unsigned char)onebyte; ++ p = q + 1; ++@@ -275,7 +279,7 @@ char *ebt_mask_to_dotted(uint32_t mask) ++ *buf = '\0'; ++ else ++ /* Mask was not a decent combination of 1's and 0's */ ++- sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0], +++ sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0], ++ ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2], ++ ((unsigned char *)&mask)[3]); ++ ++@@ -424,3 +428,146 @@ char *ebt_ip6_mask_to_string(const struct in6_addr *msk) ++ sprintf(buf, "/%s", ebt_ip6_to_numeric(msk)); ++ return buf; ++ } +++ +++static char* +++parse_num(const char *str, long min, long max, long *num) +++{ +++ char *end; +++ +++ errno = 0; +++ *num = strtol(str, &end, 10); +++ if (errno && (*num == LONG_MIN || *num == LONG_MAX)) { +++ ebt_print_error("Invalid number %s: %s", str, strerror(errno)); +++ return NULL; +++ } +++ if (min <= max) { +++ if (*num > max || *num < min) { +++ ebt_print_error("Value %ld out of range (%ld, %ld)", *num, min, max); +++ return NULL; +++ } +++ } +++ if (*num == 0 && str == end) +++ return NULL; +++ return end; +++} +++ +++static char * +++parse_range(const char *str, long min, long max, long num[]) +++{ +++ char *next; +++ +++ next = parse_num(str, min, max, num); +++ if (next == NULL) +++ return NULL; +++ if (next && *next == ':') +++ next = parse_num(next+1, min, max, &num[1]); +++ else +++ num[1] = num[0]; +++ return next; +++} +++ +++int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, +++ const char *icmptype, uint8_t type[], uint8_t code[]) +++{ +++ unsigned int match = n_codes; +++ unsigned int i; +++ long number[2]; +++ +++ for (i = 0; i < n_codes; i++) { +++ if (strncasecmp(icmp_codes[i].name, icmptype, strlen(icmptype))) +++ continue; +++ if (match != n_codes) +++ ebt_print_error("Ambiguous ICMP type `%s':" +++ " `%s' or `%s'?", +++ icmptype, icmp_codes[match].name, +++ icmp_codes[i].name); +++ match = i; +++ } +++ +++ if (match < n_codes) { +++ type[0] = type[1] = icmp_codes[match].type; +++ code[0] = icmp_codes[match].code_min; +++ code[1] = icmp_codes[match].code_max; +++ } else { +++ char *next = parse_range(icmptype, 0, 255, number); +++ if (!next) { +++ ebt_print_error("Unknown ICMP type `%s'", +++ icmptype); +++ return -1; +++ } +++ type[0] = (uint8_t) number[0]; +++ type[1] = (uint8_t) number[1]; +++ switch (*next) { +++ case 0: +++ code[0] = 0; +++ code[1] = 255; +++ return 0; +++ case '/': +++ next = parse_range(next+1, 0, 255, number); +++ code[0] = (uint8_t) number[0]; +++ code[1] = (uint8_t) number[1]; +++ if (next == NULL) +++ return -1; +++ if (next && *next == 0) +++ return 0; +++ /* fallthrough */ +++ default: +++ ebt_print_error("unknown character %c", *next); +++ return -1; +++ } +++ } +++ return 0; +++} +++ +++static void print_icmp_code(uint8_t *code) +++{ +++ if (code[0] == code[1]) +++ printf("/%"PRIu8 " ", code[0]); +++ else +++ printf("/%"PRIu8":%"PRIu8 " ", code[0], code[1]); +++} +++ +++void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes, +++ size_t n_codes, uint8_t *type, uint8_t *code) +++{ +++ unsigned int i; +++ +++ if (type[0] != type[1]) { +++ printf("%"PRIu8 ":%" PRIu8, type[0], type[1]); +++ print_icmp_code(code); +++ return; +++ } +++ +++ for (i = 0; i < n_codes; i++) { +++ if (icmp_codes[i].type != type[0]) +++ continue; +++ +++ if (icmp_codes[i].code_min == code[0] && +++ icmp_codes[i].code_max == code[1]) { +++ printf("%s ", icmp_codes[i].name); +++ return; +++ } +++ } +++ printf("%"PRIu8, type[0]); +++ print_icmp_code(code); +++} +++ +++void ebt_print_icmp_types(const struct ebt_icmp_names *icmp_codes, +++ size_t n_codes) +++{ +++ unsigned int i; +++ +++ for (i = 0; i < n_codes; i++) { +++ if (i && icmp_codes[i].type == icmp_codes[i-1].type) { +++ if (icmp_codes[i].code_min == icmp_codes[i-1].code_min +++ && (icmp_codes[i].code_max +++ == icmp_codes[i-1].code_max)) +++ printf(" (%s)", icmp_codes[i].name); +++ else +++ printf("\n %s", icmp_codes[i].name); +++ } +++ else +++ printf("\n%s", icmp_codes[i].name); +++ } +++ printf("\n"); +++} ++-- ++2.16.2 ++ +diff --git a/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch b/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..2c83168933d88535747f0bc18d3ebbe03c6b1f30 +--- /dev/null ++++ b/package/network/utils/ebtables/patches/301-0003-ebt_ip-add-support-for-matching-ICMP-type-and-code.patch +@@ -0,0 +1,182 @@ ++From 76bc7b4ede217228e782a6d4dfaa67f772a08441 Mon Sep 17 00:00:00 2001 ++Message-Id: <76bc7b4ede217228e782a6d4dfaa67f772a08441.1520151963.git.mschiffer@universe-factory.net> ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sat, 3 Mar 2018 12:42:46 +0100 ++Subject: [PATCH ebtables 3/4] ebt_ip: add support for matching ICMP type and ++ code ++ ++We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP ++matches in the same way. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ extensions/ebt_ip.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++-- ++ 1 file changed, 94 insertions(+), 2 deletions(-) ++ ++diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c ++index 59559feffa50..42660d4564fb 100644 ++--- a/extensions/ebt_ip.c +++++ b/extensions/ebt_ip.c ++@@ -24,6 +24,7 @@ ++ #define IP_PROTO '4' ++ #define IP_SPORT '5' ++ #define IP_DPORT '6' +++#define IP_ICMP '7' ++ ++ static const struct option opts[] = ++ { ++@@ -38,9 +39,64 @@ static const struct option opts[] = ++ { "ip-sport" , required_argument, 0, IP_SPORT }, ++ { "ip-destination-port" , required_argument, 0, IP_DPORT }, ++ { "ip-dport" , required_argument, 0, IP_DPORT }, +++ { "ip-icmp-type" , required_argument, 0, IP_ICMP }, ++ { 0 } ++ }; ++ +++static const struct ebt_icmp_names icmp_codes[] = { +++ { "echo-reply", 0, 0, 0xFF }, +++ /* Alias */ { "pong", 0, 0, 0xFF }, +++ +++ { "destination-unreachable", 3, 0, 0xFF }, +++ { "network-unreachable", 3, 0, 0 }, +++ { "host-unreachable", 3, 1, 1 }, +++ { "protocol-unreachable", 3, 2, 2 }, +++ { "port-unreachable", 3, 3, 3 }, +++ { "fragmentation-needed", 3, 4, 4 }, +++ { "source-route-failed", 3, 5, 5 }, +++ { "network-unknown", 3, 6, 6 }, +++ { "host-unknown", 3, 7, 7 }, +++ { "network-prohibited", 3, 9, 9 }, +++ { "host-prohibited", 3, 10, 10 }, +++ { "TOS-network-unreachable", 3, 11, 11 }, +++ { "TOS-host-unreachable", 3, 12, 12 }, +++ { "communication-prohibited", 3, 13, 13 }, +++ { "host-precedence-violation", 3, 14, 14 }, +++ { "precedence-cutoff", 3, 15, 15 }, +++ +++ { "source-quench", 4, 0, 0xFF }, +++ +++ { "redirect", 5, 0, 0xFF }, +++ { "network-redirect", 5, 0, 0 }, +++ { "host-redirect", 5, 1, 1 }, +++ { "TOS-network-redirect", 5, 2, 2 }, +++ { "TOS-host-redirect", 5, 3, 3 }, +++ +++ { "echo-request", 8, 0, 0xFF }, +++ /* Alias */ { "ping", 8, 0, 0xFF }, +++ +++ { "router-advertisement", 9, 0, 0xFF }, +++ +++ { "router-solicitation", 10, 0, 0xFF }, +++ +++ { "time-exceeded", 11, 0, 0xFF }, +++ /* Alias */ { "ttl-exceeded", 11, 0, 0xFF }, +++ { "ttl-zero-during-transit", 11, 0, 0 }, +++ { "ttl-zero-during-reassembly", 11, 1, 1 }, +++ +++ { "parameter-problem", 12, 0, 0xFF }, +++ { "ip-header-bad", 12, 0, 0 }, +++ { "required-option-missing", 12, 1, 1 }, +++ +++ { "timestamp-request", 13, 0, 0xFF }, +++ +++ { "timestamp-reply", 14, 0, 0xFF }, +++ +++ { "address-mask-request", 17, 0, 0xFF }, +++ +++ { "address-mask-reply", 18, 0, 0xFF } +++}; +++ ++ /* put the mask into 4 bytes */ ++ /* transform a protocol and service name into a port number */ ++ static uint16_t parse_port(const char *protocol, const char *name) ++@@ -105,7 +161,11 @@ static void print_help() ++ "--ip-tos [!] tos : ip tos specification\n" ++ "--ip-proto [!] protocol : ip protocol specification\n" ++ "--ip-sport [!] port[:port] : tcp/udp source port or port range\n" ++-"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n"); +++"--ip-dport [!] port[:port] : tcp/udp destination port or port range\n" +++"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"); +++ +++ printf("\nValid ICMP Types:\n"); +++ ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes)); ++ } ++ ++ static void init(struct ebt_entry_match *match) ++@@ -122,6 +182,7 @@ static void init(struct ebt_entry_match *match) ++ #define OPT_PROTO 0x08 ++ #define OPT_SPORT 0x10 ++ #define OPT_DPORT 0x20 +++#define OPT_ICMP 0x40 ++ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, ++ unsigned int *flags, struct ebt_entry_match **match) ++ { ++@@ -170,6 +231,16 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, ++ parse_port_range(NULL, optarg, ipinfo->dport); ++ break; ++ +++ case IP_ICMP: +++ ebt_check_option2(flags, OPT_ICMP); +++ ipinfo->bitmask |= EBT_IP_ICMP; +++ if (ebt_check_inverse2(optarg)) +++ ipinfo->invflags |= EBT_IP_ICMP; +++ if (ebt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes), optarg, +++ ipinfo->icmp_type, ipinfo->icmp_code)) +++ return 0; +++ break; +++ ++ case IP_myTOS: ++ ebt_check_option2(flags, OPT_TOS); ++ if (ebt_check_inverse2(optarg)) ++@@ -219,10 +290,17 @@ static void final_check(const struct ebt_u_entry *entry, ++ (ipinfo->protocol!=IPPROTO_TCP && ++ ipinfo->protocol!=IPPROTO_UDP && ++ ipinfo->protocol!=IPPROTO_SCTP && ++- ipinfo->protocol!=IPPROTO_DCCP))) +++ ipinfo->protocol!=IPPROTO_DCCP))) { ++ ebt_print_error("For port filtering the IP protocol must be " ++ "either 6 (tcp), 17 (udp), 33 (dccp) or " ++ "132 (sctp)"); +++ } else if ((ipinfo->bitmask & EBT_IP_ICMP) && +++ (!(ipinfo->bitmask & EBT_IP_PROTO) || +++ ipinfo->invflags & EBT_IP_PROTO || +++ ipinfo->protocol != IPPROTO_ICMP)) { +++ ebt_print_error("For ICMP filtering the IP protocol must be " +++ "1 (icmp)"); +++ } ++ } ++ ++ static void print(const struct ebt_u_entry *entry, ++@@ -280,6 +358,13 @@ static void print(const struct ebt_u_entry *entry, ++ printf("! "); ++ print_port_range(ipinfo->dport); ++ } +++ if (ipinfo->bitmask & EBT_IP_ICMP) { +++ printf("--ip-icmp-type "); +++ if (ipinfo->invflags & EBT_IP_ICMP) +++ printf("! "); +++ ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes), +++ ipinfo->icmp_type, ipinfo->icmp_code); +++ } ++ } ++ ++ static int compare(const struct ebt_entry_match *m1, ++@@ -322,6 +407,13 @@ static int compare(const struct ebt_entry_match *m1, ++ ipinfo1->dport[1] != ipinfo2->dport[1]) ++ return 0; ++ } +++ if (ipinfo1->bitmask & EBT_IP_ICMP) { +++ if (ipinfo1->icmp_type[0] != ipinfo2->icmp_type[0] || +++ ipinfo1->icmp_type[1] != ipinfo2->icmp_type[1] || +++ ipinfo1->icmp_code[0] != ipinfo2->icmp_code[0] || +++ ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1]) +++ return 0; +++ } ++ return 1; ++ } ++ ++-- ++2.16.2 ++ +diff --git a/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch b/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..1a7fe6d2ffcd0baf620dd36d6d3ba200f8b823e9 +--- /dev/null ++++ b/package/network/utils/ebtables/patches/301-0004-ebt_ip-add-support-for-matching-IGMP-type.patch +@@ -0,0 +1,207 @@ ++From b20e495bdf0c5eec3244cf7f98bae24316ffc3ab Mon Sep 17 00:00:00 2001 ++Message-Id: ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sat, 3 Mar 2018 13:50:23 +0100 ++Subject: [PATCH ebtables 4/4] ebt_ip: add support for matching IGMP type ++ ++We already have ICMPv6 type/code matches (which can be used to distinguish ++different types of MLD packets). Add support for IPv4 IGMP matches in the ++same way. ++ ++To reuse as much code as possible, the ICMP type/code handling functions ++are extended to allow passing a NULL code range. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ extensions/ebt_ip.c | 44 +++++++++++++++++++++++++++++++++++++++++++- ++ useful_functions.c | 35 ++++++++++++++++++++++------------- ++ 2 files changed, 65 insertions(+), 14 deletions(-) ++ ++diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c ++index 42660d4564fb..1ffdb95f156d 100644 ++--- a/extensions/ebt_ip.c +++++ b/extensions/ebt_ip.c ++@@ -25,6 +25,7 @@ ++ #define IP_SPORT '5' ++ #define IP_DPORT '6' ++ #define IP_ICMP '7' +++#define IP_IGMP '8' ++ ++ static const struct option opts[] = ++ { ++@@ -40,6 +41,7 @@ static const struct option opts[] = ++ { "ip-destination-port" , required_argument, 0, IP_DPORT }, ++ { "ip-dport" , required_argument, 0, IP_DPORT }, ++ { "ip-icmp-type" , required_argument, 0, IP_ICMP }, +++ { "ip-igmp-type" , required_argument, 0, IP_IGMP }, ++ { 0 } ++ }; ++ ++@@ -97,6 +99,14 @@ static const struct ebt_icmp_names icmp_codes[] = { ++ { "address-mask-reply", 18, 0, 0xFF } ++ }; ++ +++static const struct ebt_icmp_names igmp_types[] = { +++ { "membership-query", 0x11 }, +++ { "membership-report-v1", 0x12 }, +++ { "membership-report-v2", 0x16 }, +++ { "leave-group", 0x17 }, +++ { "membership-report-v3", 0x22 }, +++}; +++ ++ /* put the mask into 4 bytes */ ++ /* transform a protocol and service name into a port number */ ++ static uint16_t parse_port(const char *protocol, const char *name) ++@@ -162,10 +172,13 @@ static void print_help() ++ "--ip-proto [!] protocol : ip protocol specification\n" ++ "--ip-sport [!] port[:port] : tcp/udp source port or port range\n" ++ "--ip-dport [!] port[:port] : tcp/udp destination port or port range\n" ++-"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n"); +++"--ip-icmp-type [!] type[[:type]/code[:code]] : icmp type/code or type/code range\n" +++"--ip-igmp-type [!] type[:type] : igmp type or type range\n"); ++ ++ printf("\nValid ICMP Types:\n"); ++ ebt_print_icmp_types(icmp_codes, ARRAY_SIZE(icmp_codes)); +++ printf("\nValid IGMP Types:\n"); +++ ebt_print_icmp_types(igmp_types, ARRAY_SIZE(igmp_types)); ++ } ++ ++ static void init(struct ebt_entry_match *match) ++@@ -183,6 +196,7 @@ static void init(struct ebt_entry_match *match) ++ #define OPT_SPORT 0x10 ++ #define OPT_DPORT 0x20 ++ #define OPT_ICMP 0x40 +++#define OPT_IGMP 0x80 ++ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, ++ unsigned int *flags, struct ebt_entry_match **match) ++ { ++@@ -241,6 +255,16 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, ++ return 0; ++ break; ++ +++ case IP_IGMP: +++ ebt_check_option2(flags, OPT_IGMP); +++ ipinfo->bitmask |= EBT_IP_IGMP; +++ if (ebt_check_inverse2(optarg)) +++ ipinfo->invflags |= EBT_IP_IGMP; +++ if (ebt_parse_icmp(igmp_types, ARRAY_SIZE(igmp_types), optarg, +++ ipinfo->igmp_type, NULL)) +++ return 0; +++ break; +++ ++ case IP_myTOS: ++ ebt_check_option2(flags, OPT_TOS); ++ if (ebt_check_inverse2(optarg)) ++@@ -300,6 +324,12 @@ static void final_check(const struct ebt_u_entry *entry, ++ ipinfo->protocol != IPPROTO_ICMP)) { ++ ebt_print_error("For ICMP filtering the IP protocol must be " ++ "1 (icmp)"); +++ } else if ((ipinfo->bitmask & EBT_IP_IGMP) && +++ (!(ipinfo->bitmask & EBT_IP_PROTO) || +++ ipinfo->invflags & EBT_IP_PROTO || +++ ipinfo->protocol != IPPROTO_IGMP)) { +++ ebt_print_error("For IGMP filtering the IP protocol must be " +++ "2 (igmp)"); ++ } ++ } ++ ++@@ -365,6 +395,13 @@ static void print(const struct ebt_u_entry *entry, ++ ebt_print_icmp_type(icmp_codes, ARRAY_SIZE(icmp_codes), ++ ipinfo->icmp_type, ipinfo->icmp_code); ++ } +++ if (ipinfo->bitmask & EBT_IP_IGMP) { +++ printf("--ip-igmp-type "); +++ if (ipinfo->invflags & EBT_IP_IGMP) +++ printf("! "); +++ ebt_print_icmp_type(igmp_types, ARRAY_SIZE(igmp_types), +++ ipinfo->igmp_type, NULL); +++ } ++ } ++ ++ static int compare(const struct ebt_entry_match *m1, ++@@ -414,6 +451,11 @@ static int compare(const struct ebt_entry_match *m1, ++ ipinfo1->icmp_code[1] != ipinfo2->icmp_code[1]) ++ return 0; ++ } +++ if (ipinfo1->bitmask & EBT_IP_IGMP) { +++ if (ipinfo1->igmp_type[0] != ipinfo2->igmp_type[0] || +++ ipinfo1->igmp_type[1] != ipinfo2->igmp_type[1]) +++ return 0; +++ } ++ return 1; ++ } ++ ++diff --git a/useful_functions.c b/useful_functions.c ++index 8f54bae83fae..8a34f820f230 100644 ++--- a/useful_functions.c +++++ b/useful_functions.c ++@@ -486,8 +486,10 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, ++ ++ if (match < n_codes) { ++ type[0] = type[1] = icmp_codes[match].type; ++- code[0] = icmp_codes[match].code_min; ++- code[1] = icmp_codes[match].code_max; +++ if (code) { +++ code[0] = icmp_codes[match].code_min; +++ code[1] = icmp_codes[match].code_max; +++ } ++ } else { ++ char *next = parse_range(icmptype, 0, 255, number); ++ if (!next) { ++@@ -499,17 +501,21 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, ++ type[1] = (uint8_t) number[1]; ++ switch (*next) { ++ case 0: ++- code[0] = 0; ++- code[1] = 255; +++ if (code) { +++ code[0] = 0; +++ code[1] = 255; +++ } ++ return 0; ++ case '/': ++- next = parse_range(next+1, 0, 255, number); ++- code[0] = (uint8_t) number[0]; ++- code[1] = (uint8_t) number[1]; ++- if (next == NULL) ++- return -1; ++- if (next && *next == 0) ++- return 0; +++ if (code) { +++ next = parse_range(next+1, 0, 255, number); +++ code[0] = (uint8_t) number[0]; +++ code[1] = (uint8_t) number[1]; +++ if (next == NULL) +++ return -1; +++ if (next && *next == 0) +++ return 0; +++ } ++ /* fallthrough */ ++ default: ++ ebt_print_error("unknown character %c", *next); ++@@ -521,6 +527,9 @@ int ebt_parse_icmp(const struct ebt_icmp_names *icmp_codes, size_t n_codes, ++ ++ static void print_icmp_code(uint8_t *code) ++ { +++ if (!code) +++ return; +++ ++ if (code[0] == code[1]) ++ printf("/%"PRIu8 " ", code[0]); ++ else ++@@ -542,8 +551,8 @@ void ebt_print_icmp_type(const struct ebt_icmp_names *icmp_codes, ++ if (icmp_codes[i].type != type[0]) ++ continue; ++ ++- if (icmp_codes[i].code_min == code[0] && ++- icmp_codes[i].code_max == code[1]) { +++ if (!code || (icmp_codes[i].code_min == code[0] && +++ icmp_codes[i].code_max == code[1])) { ++ printf("%s ", icmp_codes[i].name); ++ return; ++ } ++-- ++2.16.2 ++ +diff --git a/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch b/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..1f3d1a2fea50154238c03707b0d7a96db8d1f5d9 +--- /dev/null ++++ b/target/linux/generic/patches-4.4/614-0001-ebtables-add-support-for-matching-ICMP-type-and-code.patch +@@ -0,0 +1,139 @@ ++From 4f8fa78149e0921c8efdc1adc5e12686ffe7667f Mon Sep 17 00:00:00 2001 ++Message-Id: <4f8fa78149e0921c8efdc1adc5e12686ffe7667f.1520150717.git.mschiffer@universe-factory.net> ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sat, 3 Mar 2018 11:55:21 +0100 ++Subject: [PATCH nf-next 1/2] ebtables: add support for matching ICMP type and ++ code ++ ++We already have ICMPv6 type/code matches. This adds support for IPv4 ICMP ++matches in the same way. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ include/uapi/linux/netfilter_bridge/ebt_ip.h | 13 +++++++-- ++ net/bridge/netfilter/ebt_ip.c | 43 +++++++++++++++++++++------- ++ 2 files changed, 43 insertions(+), 13 deletions(-) ++ ++--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h +++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h ++@@ -23,8 +23,9 @@ ++ #define EBT_IP_PROTO 0x08 ++ #define EBT_IP_SPORT 0x10 ++ #define EBT_IP_DPORT 0x20 +++#define EBT_IP_ICMP 0x40 ++ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ ++- EBT_IP_SPORT | EBT_IP_DPORT ) +++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP) ++ #define EBT_IP_MATCH "ip" ++ ++ /* the same values are used for the invflags */ ++@@ -37,8 +38,14 @@ struct ebt_ip_info { ++ __u8 protocol; ++ __u8 bitmask; ++ __u8 invflags; ++- __u16 sport[2]; ++- __u16 dport[2]; +++ union { +++ __u16 sport[2]; +++ __u8 icmp_type[2]; +++ }; +++ union { +++ __u16 dport[2]; +++ __u8 icmp_code[2]; +++ }; ++ }; ++ ++ #endif ++--- a/net/bridge/netfilter/ebt_ip.c +++++ b/net/bridge/netfilter/ebt_ip.c ++@@ -19,9 +19,15 @@ ++ #include ++ #include ++ ++-struct tcpudphdr { ++- __be16 src; ++- __be16 dst; +++union pkthdr { +++ struct { +++ __be16 src; +++ __be16 dst; +++ } tcpudphdr; +++ struct { +++ u8 type; +++ u8 code; +++ } icmphdr; ++ }; ++ ++ static bool ++@@ -30,8 +36,8 @@ ebt_ip_mt(const struct sk_buff *skb, str ++ const struct ebt_ip_info *info = par->matchinfo; ++ const struct iphdr *ih; ++ struct iphdr _iph; ++- const struct tcpudphdr *pptr; ++- struct tcpudphdr _ports; +++ const union pkthdr *pptr; +++ union pkthdr _pkthdr; ++ ++ ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); ++ if (ih == NULL) ++@@ -50,29 +56,38 @@ ebt_ip_mt(const struct sk_buff *skb, str ++ if (info->bitmask & EBT_IP_PROTO) { ++ if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) ++ return false; ++- if (!(info->bitmask & EBT_IP_DPORT) && ++- !(info->bitmask & EBT_IP_SPORT)) +++ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | +++ EBT_IP_ICMP))) ++ return true; ++ if (ntohs(ih->frag_off) & IP_OFFSET) ++ return false; +++ +++ /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */ ++ pptr = skb_header_pointer(skb, ih->ihl*4, ++- sizeof(_ports), &_ports); +++ sizeof(_pkthdr), &_pkthdr); ++ if (pptr == NULL) ++ return false; ++ if (info->bitmask & EBT_IP_DPORT) { ++- u32 dst = ntohs(pptr->dst); +++ u32 dst = ntohs(pptr->tcpudphdr.dst); ++ if (FWINV(dst < info->dport[0] || ++ dst > info->dport[1], ++ EBT_IP_DPORT)) ++ return false; ++ } ++ if (info->bitmask & EBT_IP_SPORT) { ++- u32 src = ntohs(pptr->src); +++ u32 src = ntohs(pptr->tcpudphdr.src); ++ if (FWINV(src < info->sport[0] || ++ src > info->sport[1], ++ EBT_IP_SPORT)) ++ return false; ++ } +++ if ((info->bitmask & EBT_IP_ICMP) && +++ FWINV(pptr->icmphdr.type < info->icmp_type[0] || +++ pptr->icmphdr.type > info->icmp_type[1] || +++ pptr->icmphdr.code < info->icmp_code[0] || +++ pptr->icmphdr.code > info->icmp_code[1], +++ EBT_IP_ICMP)) +++ return false; ++ } ++ return true; ++ } ++@@ -101,6 +116,14 @@ static int ebt_ip_mt_check(const struct ++ return -EINVAL; ++ if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) ++ return -EINVAL; +++ if (info->bitmask & EBT_IP_ICMP) { +++ if ((info->invflags & EBT_IP_PROTO) || +++ info->protocol != IPPROTO_ICMP) +++ return -EINVAL; +++ if (info->icmp_type[0] > info->icmp_type[1] || +++ info->icmp_code[0] > info->icmp_code[1]) +++ return -EINVAL; +++ } ++ return 0; ++ } ++ +diff --git a/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch b/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..3c8760dbebefddb9bb6a0b9bb724210c573d854c +--- /dev/null ++++ b/target/linux/generic/patches-4.4/614-0002-ebtables-add-support-for-matching-IGMP-type.patch +@@ -0,0 +1,92 @@ ++From 68c6d1b60803e9690f2a6168b80a92ae45c6578b Mon Sep 17 00:00:00 2001 ++Message-Id: <68c6d1b60803e9690f2a6168b80a92ae45c6578b.1520150717.git.mschiffer@universe-factory.net> ++In-Reply-To: ++References: ++From: Matthias Schiffer ++Date: Sat, 3 Mar 2018 12:02:21 +0100 ++Subject: [PATCH nf-next 2/2] ebtables: add support for matching IGMP type ++ ++We already have ICMPv6 type/code matches (which can be used to distinguish ++different types of MLD packets). Add support for IPv4 IGMP matches in the ++same way. ++ ++Signed-off-by: Matthias Schiffer ++--- ++ include/uapi/linux/netfilter_bridge/ebt_ip.h | 4 +++- ++ net/bridge/netfilter/ebt_ip.c | 19 +++++++++++++++++-- ++ 2 files changed, 20 insertions(+), 3 deletions(-) ++ ++--- a/include/uapi/linux/netfilter_bridge/ebt_ip.h +++++ b/include/uapi/linux/netfilter_bridge/ebt_ip.h ++@@ -24,8 +24,9 @@ ++ #define EBT_IP_SPORT 0x10 ++ #define EBT_IP_DPORT 0x20 ++ #define EBT_IP_ICMP 0x40 +++#define EBT_IP_IGMP 0x80 ++ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ ++- EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP) +++ EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_ICMP | EBT_IP_IGMP) ++ #define EBT_IP_MATCH "ip" ++ ++ /* the same values are used for the invflags */ ++@@ -41,6 +42,7 @@ struct ebt_ip_info { ++ union { ++ __u16 sport[2]; ++ __u8 icmp_type[2]; +++ __u8 igmp_type[2]; ++ }; ++ union { ++ __u16 dport[2]; ++--- a/net/bridge/netfilter/ebt_ip.c +++++ b/net/bridge/netfilter/ebt_ip.c ++@@ -28,6 +28,9 @@ union pkthdr { ++ u8 type; ++ u8 code; ++ } icmphdr; +++ struct { +++ u8 type; +++ } igmphdr; ++ }; ++ ++ static bool ++@@ -57,12 +60,12 @@ ebt_ip_mt(const struct sk_buff *skb, str ++ if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) ++ return false; ++ if (!(info->bitmask & (EBT_IP_DPORT | EBT_IP_SPORT | ++- EBT_IP_ICMP))) +++ EBT_IP_ICMP | EBT_IP_IGMP))) ++ return true; ++ if (ntohs(ih->frag_off) & IP_OFFSET) ++ return false; ++ ++- /* min icmp headersize is 4, so sizeof(_pkthdr) is ok. */ +++ /* min icmp/igmp headersize is 4, so sizeof(_pkthdr) is ok. */ ++ pptr = skb_header_pointer(skb, ih->ihl*4, ++ sizeof(_pkthdr), &_pkthdr); ++ if (pptr == NULL) ++@@ -88,6 +91,11 @@ ebt_ip_mt(const struct sk_buff *skb, str ++ pptr->icmphdr.code > info->icmp_code[1], ++ EBT_IP_ICMP)) ++ return false; +++ if ((info->bitmask & EBT_IP_IGMP) && +++ FWINV(pptr->igmphdr.type < info->igmp_type[0] || +++ pptr->igmphdr.type > info->igmp_type[1], +++ EBT_IP_IGMP)) +++ return false; ++ } ++ return true; ++ } ++@@ -124,6 +132,13 @@ static int ebt_ip_mt_check(const struct ++ info->icmp_code[0] > info->icmp_code[1]) ++ return -EINVAL; ++ } +++ if (info->bitmask & EBT_IP_IGMP) { +++ if ((info->invflags & EBT_IP_PROTO) || +++ info->protocol != IPPROTO_IGMP) +++ return -EINVAL; +++ if (info->igmp_type[0] > info->igmp_type[1]) +++ return -EINVAL; +++ } ++ return 0; ++ } ++ diff --git a/patches/lede/0068-base-files-remove-etc-uci-defaults-11_migrate-sysctl.patch b/patches/lede/0068-base-files-remove-etc-uci-defaults-11_migrate-sysctl.patch new file mode 100644 index 00000000..404f24ee --- /dev/null +++ b/patches/lede/0068-base-files-remove-etc-uci-defaults-11_migrate-sysctl.patch @@ -0,0 +1,31 @@ +From: Matthias Schiffer +Date: Thu, 12 Apr 2018 17:30:16 +0200 +Subject: base-files: remove /etc/uci-defaults/11_migrate-sysctl + +11_migrate-sysctl has not been updated with new file hashes since 2012. +Let's get rid of it. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/etc/uci-defaults/11_migrate-sysctl b/package/base-files/files/etc/uci-defaults/11_migrate-sysctl +deleted file mode 100644 +index 464e275779ceec1d99a7323b6cbf7901aaa9fbb4..0000000000000000000000000000000000000000 +--- a/package/base-files/files/etc/uci-defaults/11_migrate-sysctl ++++ /dev/null +@@ -1,16 +0,0 @@ +-#!/bin/sh +- +-if [ ! -f "/rom/etc/sysctl.conf" ] || cmp -s "/rom/etc/sysctl.conf" "/etc/sysctl.conf"; then +- exit 0 +-fi +- +-fingerprint="$(md5sum /etc/sysctl.conf)" +-fingerprint="${fingerprint%% *}" +- +-if [ "$fingerprint" = "1b05ebb41f72cb84e5510573cd4aca26" ] || \ +- [ "$fingerprint" = "62deb895be1a7f496040187b7c930e4e" ]; then +- logger -t migrate-sysctl "Updating sysctl.conf to use current defaults" +- cp "/rom/etc/sysctl.conf" "/etc/sysctl.conf" +-fi +- +-exit 0 diff --git a/patches/lede/0069-base-files-evaluate-etc-sysctl.d-before-etc-sysctl.conf.patch b/patches/lede/0069-base-files-evaluate-etc-sysctl.d-before-etc-sysctl.conf.patch new file mode 100644 index 00000000..54fd291f --- /dev/null +++ b/patches/lede/0069-base-files-evaluate-etc-sysctl.d-before-etc-sysctl.conf.patch @@ -0,0 +1,35 @@ +From: Matthias Schiffer +Date: Thu, 12 Apr 2018 17:33:51 +0200 +Subject: base-files: evaluate /etc/sysctl.d/* before /etc/sysctl.conf + +We can use /etc/sysctl.d/* for package-supplied sysctl snippets, giving +admins the option to use /etc/sysctl.conf to override settings. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/etc/hotplug.d/net/00-sysctl b/package/base-files/files/etc/hotplug.d/net/00-sysctl +index 7a71652c44f8bd1fb9f2e5643e7baa5d5d76c369..8abe7f8bbd698dc58716b770fe8bc7f8bd475b58 100644 +--- a/package/base-files/files/etc/hotplug.d/net/00-sysctl ++++ b/package/base-files/files/etc/hotplug.d/net/00-sysctl +@@ -1,7 +1,7 @@ + #!/bin/sh + + if [ "$ACTION" = add ]; then +- for CONF in /etc/sysctl.conf /etc/sysctl.d/*.conf; do ++ for CONF in /etc/sysctl.d/*.conf /etc/sysctl.conf; do + [ ! -f "$CONF" ] && continue; + sed -ne "/^[[:space:]]*net\..*\.$DEVICENAME\./p" "$CONF" | \ + sysctl -e -p - | logger -t sysctl +diff --git a/package/base-files/files/etc/init.d/sysctl b/package/base-files/files/etc/init.d/sysctl +index 65e6aa99250d09a3ccd9d023cb8f8205be86eee8..8722126a6612d67a3f615166a7fbec146207e97f 100755 +--- a/package/base-files/files/etc/init.d/sysctl ++++ b/package/base-files/files/etc/init.d/sysctl +@@ -30,7 +30,7 @@ apply_defaults() { + + start() { + apply_defaults +- for CONF in /etc/sysctl.conf /etc/sysctl.d/*.conf; do ++ for CONF in /etc/sysctl.d/*.conf /etc/sysctl.conf; do + [ -f "$CONF" ] && sysctl -p "$CONF" -e >&- + done + } diff --git a/patches/lede/0070-base-files-move-sysctl-defaults-to-etc-sysctl.d-10-default.conf.patch b/patches/lede/0070-base-files-move-sysctl-defaults-to-etc-sysctl.d-10-default.conf.patch new file mode 100644 index 00000000..545528cb --- /dev/null +++ b/patches/lede/0070-base-files-move-sysctl-defaults-to-etc-sysctl.d-10-default.conf.patch @@ -0,0 +1,89 @@ +From: Matthias Schiffer +Date: Thu, 12 Apr 2018 17:37:29 +0200 +Subject: base-files: move sysctl defaults to /etc/sysctl.d/10-default.conf + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/etc/sysctl.conf b/package/base-files/files/etc/sysctl.conf +index 91a3ac9a02d4344cf8c4c8f93a36193120fc4b95..ae04212f420b185ce525dae444b563128ddf0e11 100644 +--- a/package/base-files/files/etc/sysctl.conf ++++ b/package/base-files/files/etc/sysctl.conf +@@ -1,30 +1 @@ +-kernel.panic=3 +-kernel.core_pattern=/tmp/%e.%t.%p.%s.core +- +-net.ipv4.conf.default.arp_ignore=1 +-net.ipv4.conf.all.arp_ignore=1 +-net.ipv4.ip_forward=1 +-net.ipv4.icmp_echo_ignore_broadcasts=1 +-net.ipv4.icmp_ignore_bogus_error_responses=1 +-net.ipv4.igmp_max_memberships=100 +-net.ipv4.tcp_fin_timeout=30 +-net.ipv4.tcp_keepalive_time=120 +-net.ipv4.tcp_syncookies=1 +-net.ipv4.tcp_timestamps=1 +-net.ipv4.tcp_sack=1 +-net.ipv4.tcp_dsack=1 +- +-net.ipv6.conf.default.forwarding=1 +-net.ipv6.conf.all.forwarding=1 +- +-net.netfilter.nf_conntrack_acct=1 +-net.netfilter.nf_conntrack_checksum=0 +-net.netfilter.nf_conntrack_max=16384 +-net.netfilter.nf_conntrack_tcp_timeout_established=7440 +-net.netfilter.nf_conntrack_udp_timeout=60 +-net.netfilter.nf_conntrack_udp_timeout_stream=180 +- +-# disable bridge firewalling by default +-net.bridge.bridge-nf-call-arptables=0 +-net.bridge.bridge-nf-call-ip6tables=0 +-net.bridge.bridge-nf-call-iptables=0 ++# Defaults are configured in /etc/sysctl.d/* and can be customized in this file +diff --git a/package/base-files/files/etc/sysctl.d/10-default.conf b/package/base-files/files/etc/sysctl.d/10-default.conf +new file mode 100644 +index 0000000000000000000000000000000000000000..7c3344dba339514c023c3b13c592e9ce9ca1ff55 +--- /dev/null ++++ b/package/base-files/files/etc/sysctl.d/10-default.conf +@@ -0,0 +1,34 @@ ++# Do not edit, changes to this file will be lost on upgrades ++# /etc/sysctl.conf can be used to customize sysctl settings ++ ++kernel.panic=3 ++kernel.core_pattern=/tmp/%e.%t.%p.%s.core ++fs.suid_dumpable=2 ++ ++net.ipv4.conf.default.arp_ignore=1 ++net.ipv4.conf.all.arp_ignore=1 ++net.ipv4.ip_forward=1 ++net.ipv4.icmp_echo_ignore_broadcasts=1 ++net.ipv4.icmp_ignore_bogus_error_responses=1 ++net.ipv4.igmp_max_memberships=100 ++net.ipv4.tcp_fin_timeout=30 ++net.ipv4.tcp_keepalive_time=120 ++net.ipv4.tcp_syncookies=1 ++net.ipv4.tcp_timestamps=1 ++net.ipv4.tcp_sack=1 ++net.ipv4.tcp_dsack=1 ++ ++net.ipv6.conf.default.forwarding=1 ++net.ipv6.conf.all.forwarding=1 ++ ++net.netfilter.nf_conntrack_acct=1 ++net.netfilter.nf_conntrack_checksum=0 ++net.netfilter.nf_conntrack_max=16384 ++net.netfilter.nf_conntrack_tcp_timeout_established=7440 ++net.netfilter.nf_conntrack_udp_timeout=60 ++net.netfilter.nf_conntrack_udp_timeout_stream=180 ++ ++# disable bridge firewalling by default ++net.bridge.bridge-nf-call-arptables=0 ++net.bridge.bridge-nf-call-ip6tables=0 ++net.bridge.bridge-nf-call-iptables=0 +diff --git a/package/base-files/files/etc/sysctl.d/local.conf b/package/base-files/files/etc/sysctl.d/local.conf +deleted file mode 100644 +index 891da73df8d61e0c47069d4c6c8cc090f693c0b2..0000000000000000000000000000000000000000 +--- a/package/base-files/files/etc/sysctl.d/local.conf ++++ /dev/null +@@ -1 +0,0 @@ +-# local sysctl settings can be stored in this directory diff --git a/patches/lede/0071-base-files-move-netfilter-sysctl-defaults-to-specific-kmod-packages.patch b/patches/lede/0071-base-files-move-netfilter-sysctl-defaults-to-specific-kmod-packages.patch new file mode 100644 index 00000000..5aaef7b3 --- /dev/null +++ b/patches/lede/0071-base-files-move-netfilter-sysctl-defaults-to-specific-kmod-packages.patch @@ -0,0 +1,85 @@ +From: Matthias Schiffer +Date: Thu, 12 Apr 2018 17:57:44 +0200 +Subject: base-files: move netfilter sysctl defaults to specific kmod packages + +Avoid warnings when applying settings for uninstalled kmods. See also +FS#1073. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/etc/sysctl.d/10-default.conf b/package/base-files/files/etc/sysctl.d/10-default.conf +index 7c3344dba339514c023c3b13c592e9ce9ca1ff55..98867b7c7ba1d1ce181f721cdfd17517069fcdf2 100644 +--- a/package/base-files/files/etc/sysctl.d/10-default.conf ++++ b/package/base-files/files/etc/sysctl.d/10-default.conf +@@ -20,15 +20,3 @@ net.ipv4.tcp_dsack=1 + + net.ipv6.conf.default.forwarding=1 + net.ipv6.conf.all.forwarding=1 +- +-net.netfilter.nf_conntrack_acct=1 +-net.netfilter.nf_conntrack_checksum=0 +-net.netfilter.nf_conntrack_max=16384 +-net.netfilter.nf_conntrack_tcp_timeout_established=7440 +-net.netfilter.nf_conntrack_udp_timeout=60 +-net.netfilter.nf_conntrack_udp_timeout_stream=180 +- +-# disable bridge firewalling by default +-net.bridge.bridge-nf-call-arptables=0 +-net.bridge.bridge-nf-call-ip6tables=0 +-net.bridge.bridge-nf-call-iptables=0 +diff --git a/package/kernel/linux/files/sysctl-br-netfilter.conf b/package/kernel/linux/files/sysctl-br-netfilter.conf +new file mode 100644 +index 0000000000000000000000000000000000000000..b10ddc0874b6d393458e646e396716bd67b6b381 +--- /dev/null ++++ b/package/kernel/linux/files/sysctl-br-netfilter.conf +@@ -0,0 +1,7 @@ ++# Do not edit, changes to this file will be lost on upgrades ++# /etc/sysctl.conf can be used to customize sysctl settings ++ ++# disable bridge firewalling by default ++net.bridge.bridge-nf-call-arptables=0 ++net.bridge.bridge-nf-call-ip6tables=0 ++net.bridge.bridge-nf-call-iptables=0 +diff --git a/package/kernel/linux/files/sysctl-nf-conntrack.conf b/package/kernel/linux/files/sysctl-nf-conntrack.conf +new file mode 100644 +index 0000000000000000000000000000000000000000..37baf5fd6ff9d99d37554f5e38bf1d749a7f21e2 +--- /dev/null ++++ b/package/kernel/linux/files/sysctl-nf-conntrack.conf +@@ -0,0 +1,9 @@ ++# Do not edit, changes to this file will be lost on upgrades ++# /etc/sysctl.conf can be used to customize sysctl settings ++ ++net.netfilter.nf_conntrack_acct=1 ++net.netfilter.nf_conntrack_checksum=0 ++net.netfilter.nf_conntrack_max=16384 ++net.netfilter.nf_conntrack_tcp_timeout_established=7440 ++net.netfilter.nf_conntrack_udp_timeout=60 ++net.netfilter.nf_conntrack_udp_timeout_stream=180 +diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk +index 3b26ad1fbf3e261d84ae18216c51c87c53579c06..bb882363f3df4df733424ca6bba72badc96f06f8 100644 +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -74,6 +74,11 @@ define KernelPackage/nf-conntrack + AUTOLOAD:=$(call AutoProbe,$(notdir $(NF_CONNTRACK-m))) + endef + ++define KernelPackage/nf-conntrack/install ++ $(INSTALL_DIR) $(1)/etc/sysctl.d ++ $(INSTALL_DATA) ./files/sysctl-nf-conntrack.conf $(1)/etc/sysctl.d/11-nf-conntrack.conf ++endef ++ + $(eval $(call KernelPackage,nf-conntrack)) + + +@@ -674,6 +679,11 @@ define KernelPackage/br-netfilter + AUTOLOAD:=$(call AutoProbe,br_netfilter) + endef + ++define KernelPackage/br-netfilter/install ++ $(INSTALL_DIR) $(1)/etc/sysctl.d ++ $(INSTALL_DATA) ./files/sysctl-br-netfilter.conf $(1)/etc/sysctl.d/11-br-netfilter.conf ++endef ++ + $(eval $(call KernelPackage,br-netfilter)) + + diff --git a/patches/lede/0072-base-files-remove-etc-sysctl.d-from-conffiles.patch b/patches/lede/0072-base-files-remove-etc-sysctl.d-from-conffiles.patch new file mode 100644 index 00000000..c1445fe2 --- /dev/null +++ b/patches/lede/0072-base-files-remove-etc-sysctl.d-from-conffiles.patch @@ -0,0 +1,23 @@ +From: Matthias Schiffer +Date: Fri, 13 Apr 2018 14:36:43 +0200 +Subject: base-files: remove /etc/sysctl.d/ from conffiles + +Let's use /etc/sysctl.d for package-provided snippets and leave +/etc/sysctl.conf to the admin. Don't backup /etc/sysctl.d on upgrades, so +old defaults get replaced properly. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/Makefile b/package/base-files/Makefile +index f473ef732106eb8fa05e7c5b59df176fef33e42d..32b1ce0923cb984ff32e4444a18eccdad7572d70 100644 +--- a/package/base-files/Makefile ++++ b/package/base-files/Makefile +@@ -59,8 +59,6 @@ define Package/base-files/conffiles + /etc/shadow + /etc/shells + /etc/sysctl.conf +-/etc/sysctl.d/ +-/etc/sysctl.d/local.conf + /etc/sysupgrade.conf + $(call $(TARGET)/conffiles) + endef diff --git a/patches/lede/0073-kernel-disable-accept_ra-by-default.patch b/patches/lede/0073-kernel-disable-accept_ra-by-default.patch new file mode 100644 index 00000000..f39acca3 --- /dev/null +++ b/patches/lede/0073-kernel-disable-accept_ra-by-default.patch @@ -0,0 +1,32 @@ +From: Matthias Schiffer +Date: Thu, 12 Apr 2018 22:14:56 +0200 +Subject: kernel: disable accept_ra by default + +Our commands setting accept_ra to 0 on all interfaces got lost in the +transition to procd. This remained unnoticed for a long time, as we also +enable forwarding on all interfaces, which prevents RA handling by default. + +Restore the commands, while also fixing a possible race condition in the +old version. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/base-files/files/etc/init.d/sysctl b/package/base-files/files/etc/init.d/sysctl +index 8722126a6612d67a3f615166a7fbec146207e97f..a236a0194b665ff56c8330930bfd44709d1b0d3d 100755 +--- a/package/base-files/files/etc/init.d/sysctl ++++ b/package/base-files/files/etc/init.d/sysctl +@@ -26,6 +26,14 @@ apply_defaults() { + net.ipv6.ip6frag_high_thresh="$frag_high_thresh" \ + net.netfilter.nf_conntrack_frag6_low_thresh="$frag_low_thresh" \ + net.netfilter.nf_conntrack_frag6_high_thresh="$frag_high_thresh" ++ ++ # first set default, then all interfaces to avoid races with appearing interfaces ++ if [ -d /proc/sys/net/ipv6/conf ]; then ++ echo 0 > /proc/sys/net/ipv6/conf/default/accept_ra ++ for iface in /proc/sys/net/ipv6/conf/*/accept_ra; do ++ echo 0 > "$iface" ++ done ++ fi + } + + start() { diff --git a/patches/lede/0074-kernel-change-dependency-of-kmod-ebtables-on-kmod-ebtables-to-selecting.patch b/patches/lede/0074-kernel-change-dependency-of-kmod-ebtables-on-kmod-ebtables-to-selecting.patch new file mode 100644 index 00000000..6f9d915f --- /dev/null +++ b/patches/lede/0074-kernel-change-dependency-of-kmod-ebtables-on-kmod-ebtables-to-selecting.patch @@ -0,0 +1,23 @@ +From: Matthias Schiffer +Date: Mon, 9 Apr 2018 18:51:57 +0200 +Subject: kernel: change dependency of kmod-ebtables-* on kmod-ebtables to selecting + +Non-selecting dependencies easily lead to Kconfig failures due to recursive +dependencies. We hit such an issue in Gluon; the easiest fix is to make +the dependency selecting. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk +index bb882363f3df4df733424ca6bba72badc96f06f8..c1d08a54037e6b33834566dac58308f64a427ecd 100644 +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -707,7 +707,7 @@ $(eval $(call KernelPackage,ebtables)) + + define AddDepends/ebtables + SUBMENU:=$(NF_MENU) +- DEPENDS+=kmod-ebtables $(1) ++ DEPENDS+= +kmod-ebtables $(1) + endef + + diff --git a/patches/lede/0075-kernel-unhide-kmod-br-netfilter.patch b/patches/lede/0075-kernel-unhide-kmod-br-netfilter.patch new file mode 100644 index 00000000..c08c7819 --- /dev/null +++ b/patches/lede/0075-kernel-unhide-kmod-br-netfilter.patch @@ -0,0 +1,21 @@ +From: Matthias Schiffer +Date: Mon, 9 Apr 2018 18:56:53 +0200 +Subject: kernel: unhide kmod-br-netfilter + +kmod-br-netfilter is not only a support module, but can be useful on its +own, using the net.bridge.bridge-nf-call-* sysctls. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk +index c1d08a54037e6b33834566dac58308f64a427ecd..275147b8757a42c00de14502a072c8384a0526ab 100644 +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -672,7 +672,6 @@ $(eval $(call KernelPackage,arptables)) + define KernelPackage/br-netfilter + SUBMENU:=$(NF_MENU) + TITLE:=Bridge netfilter support modules +- HIDDEN:=1 + DEPENDS:=+kmod-ipt-core +kmod-bridge + FILES:=$(LINUX_DIR)/net/bridge/br_netfilter.ko + KCONFIG:=CONFIG_BRIDGE_NETFILTER diff --git a/patches/lede/0076-kernel-kmod-ebtables-do-not-depend-on-kmod-br-netfilter.patch b/patches/lede/0076-kernel-kmod-ebtables-do-not-depend-on-kmod-br-netfilter.patch new file mode 100644 index 00000000..472fe77c --- /dev/null +++ b/patches/lede/0076-kernel-kmod-ebtables-do-not-depend-on-kmod-br-netfilter.patch @@ -0,0 +1,22 @@ +From: Matthias Schiffer +Date: Mon, 9 Apr 2018 19:01:56 +0200 +Subject: kernel: kmod-ebtables: do not depend on kmod-br-netfilter + +While ebtables can be combined with br-netfilter, there is no good reason +to make it a dependency. + +Signed-off-by: Matthias Schiffer + +diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk +index 275147b8757a42c00de14502a072c8384a0526ab..34eefcd892b9e8b3157603fa47578d0afc65dc4b 100644 +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -689,7 +689,7 @@ $(eval $(call KernelPackage,br-netfilter)) + define KernelPackage/ebtables + SUBMENU:=$(NF_MENU) + TITLE:=Bridge firewalling modules +- DEPENDS:=+kmod-ipt-core +kmod-bridge +kmod-br-netfilter ++ DEPENDS:=+kmod-ipt-core +kmod-bridge + FILES:=$(foreach mod,$(EBTABLES-m),$(LINUX_DIR)/net/$(mod).ko) + KCONFIG:=$(KCONFIG_EBTABLES) + AUTOLOAD:=$(call AutoProbe,$(notdir $(EBTABLES-m))) diff --git a/patches/lede/0077-iptables-split-physdev-match-out-as-a-separate-package.patch b/patches/lede/0077-iptables-split-physdev-match-out-as-a-separate-package.patch new file mode 100644 index 00000000..8d6c61d7 --- /dev/null +++ b/patches/lede/0077-iptables-split-physdev-match-out-as-a-separate-package.patch @@ -0,0 +1,114 @@ +From: Matthias Schiffer +Date: Mon, 9 Apr 2018 19:41:26 +0200 +Subject: iptables: split physdev match out as a separate package + +Split physdev match out of ipt-extra to allow installing ipt-extra without +pulling in br-netfilter. + +Signed-off-by: Matthias Schiffer + +diff --git a/include/netfilter.mk b/include/netfilter.mk +index 39c8e7c90fab2ba14cd75c80d1e357dd23ae6a1b..79ae3d5343ed77b559f50f40bb8a73a33dd13314 100644 +--- a/include/netfilter.mk ++++ b/include/netfilter.mk +@@ -89,12 +89,14 @@ $(eval $(if $(NF_KMOD),,$(call nf_add,IPT_CONNTRACK_EXTRA,CONFIG_NETFILTER_XT_CO + + $(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_ADDRTYPE, $(if $(NF_KMOD),$(P_XT)xt_addrtype,$(P_XT)ipt_addrtype))) + $(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_OWNER, $(P_XT)xt_owner)) +-$(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_PHYSDEV, $(P_XT)xt_physdev)) + $(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_PKTTYPE, $(P_XT)xt_pkttype)) + $(eval $(call nf_add,IPT_EXTRA,CONFIG_NETFILTER_XT_MATCH_QUOTA, $(P_XT)xt_quota)) + + #$(eval $(call nf_add,IPT_EXTRA,CONFIG_IP_NF_TARGET_ROUTE, $(P_V4)ipt_ROUTE)) + ++# physdev ++ ++$(eval $(call nf_add,IPT_PHYSDEV,CONFIG_NETFILTER_XT_MATCH_PHYSDEV, $(P_XT)xt_physdev)) + + # filter + +@@ -347,6 +349,7 @@ IPT_BUILTIN += $(NF_CONNTRACK6-y) + IPT_BUILTIN += $(IPT_CONNTRACK-y) + IPT_BUILTIN += $(IPT_CONNTRACK_EXTRA-y) + IPT_BUILTIN += $(IPT_EXTRA-y) ++IPT_BUILTIN += $(IPT_PHYSDEV-y) + IPT_BUILTIN += $(IPT_FILTER-y) + IPT_BUILTIN += $(IPT_IPOPT-y) + IPT_BUILTIN += $(IPT_IPRANGE-y) +diff --git a/package/kernel/linux/modules/netfilter.mk b/package/kernel/linux/modules/netfilter.mk +index 34eefcd892b9e8b3157603fa47578d0afc65dc4b..a71904673ae53bffcc9fd88291520aacb4a4f8d7 100644 +--- a/package/kernel/linux/modules/netfilter.mk ++++ b/package/kernel/linux/modules/netfilter.mk +@@ -604,7 +604,7 @@ define KernelPackage/ipt-extra + KCONFIG:=$(KCONFIG_IPT_EXTRA) + FILES:=$(foreach mod,$(IPT_EXTRA-m),$(LINUX_DIR)/net/$(mod).ko) + AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_EXTRA-m))) +- $(call AddDepends/ipt,+kmod-br-netfilter) ++ $(call AddDepends/ipt) + endef + + define KernelPackage/ipt-extra/description +@@ -612,7 +612,6 @@ define KernelPackage/ipt-extra/description + Includes: + - addrtype + - owner +- - physdev (if bridge support was enabled in kernel) + - pkttype + - quota + endef +@@ -620,6 +619,21 @@ endef + $(eval $(call KernelPackage,ipt-extra)) + + ++define KernelPackage/ipt-physdev ++ TITLE:=physdev module ++ KCONFIG:=$(KCONFIG_IPT_PHYSDEV) ++ FILES:=$(foreach mod,$(IPT_PHYSDEV-m),$(LINUX_DIR)/net/$(mod).ko) ++ AUTOLOAD:=$(call AutoProbe,$(notdir $(IPT_PHYSDEV-m))) ++ $(call AddDepends/ipt,+kmod-br-netfilter) ++endef ++ ++define KernelPackage/ipt-physdev/description ++ The iptables physdev kernel module ++endef ++ ++$(eval $(call KernelPackage,ipt-physdev)) ++ ++ + define KernelPackage/ip6tables + SUBMENU:=$(NF_MENU) + TITLE:=IPv6 modules +diff --git a/package/network/utils/iptables/Makefile b/package/network/utils/iptables/Makefile +index 9761ed1820b5c092292d25aef28f8f9a8ffa91a6..af5ed8c6245a9d52f5aea695e71b08ac6f3e6eca 100644 +--- a/package/network/utils/iptables/Makefile ++++ b/package/network/utils/iptables/Makefile +@@ -321,12 +321,20 @@ Other extra iptables extensions. + - addrtype + - condition + - owner +- - physdev (if ebtables is enabled) + - pkttype + - quota + + endef + ++define Package/iptables-mod-physdev ++$(call Package/iptables/Module, +kmod-ipt-physdev) ++ TITLE:=physdev iptables extension ++endef ++ ++define Package/iptables-mod-physdev/description ++The iptables physdev match. ++endef ++ + define Package/iptables-mod-led + $(call Package/iptables/Module, +kmod-ipt-led) + TITLE:=LED trigger iptables extension +@@ -561,6 +569,7 @@ endef + $(eval $(call BuildPackage,iptables)) + $(eval $(call BuildPlugin,iptables-mod-conntrack-extra,$(IPT_CONNTRACK_EXTRA-m))) + $(eval $(call BuildPlugin,iptables-mod-extra,$(IPT_EXTRA-m))) ++$(eval $(call BuildPlugin,iptables-mod-physdev,$(IPT_PHYSDEV-m))) + $(eval $(call BuildPlugin,iptables-mod-filter,$(IPT_FILTER-m))) + $(eval $(call BuildPlugin,iptables-mod-ipopt,$(IPT_IPOPT-m))) + $(eval $(call BuildPlugin,iptables-mod-ipsec,$(IPT_IPSEC-m))) diff --git a/patches/lede/0078-ar71xx-increase-kernel-partition-size-for-UniFi-AP-Pro-and-Outdoor.patch b/patches/lede/0078-ar71xx-increase-kernel-partition-size-for-UniFi-AP-Pro-and-Outdoor.patch new file mode 100644 index 00000000..75188df4 --- /dev/null +++ b/patches/lede/0078-ar71xx-increase-kernel-partition-size-for-UniFi-AP-Pro-and-Outdoor.patch @@ -0,0 +1,24 @@ +From: Matthias Schiffer +Date: Tue, 10 Apr 2018 15:19:52 +0200 +Subject: ar71xx: increase kernel partition size for UniFi AP Pro and Outdoor+ + +Tested on UAP Outdoor+. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/ubnt.mk b/target/linux/ar71xx/image/ubnt.mk +index 899d5d030e44e64bc945f03babf8820d87451177..84bf13d2829c3e8cd250fe9a069245d0098b864d 100644 +--- a/target/linux/ar71xx/image/ubnt.mk ++++ b/target/linux/ar71xx/image/ubnt.mk +@@ -254,9 +254,9 @@ TARGET_DEVICES += ubnt-rs ubnt-rspro ubnt-ls-sr71 + + define Device/ubnt-uap-pro + DEVICE_TITLE := Ubiquiti UAP Pro +- KERNEL_SIZE := 1536k ++ KERNEL_SIZE := 1792k + IMAGE_SIZE := 15744k +- MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,1536k(kernel),14208k(rootfs),256k(cfg)ro,64k(EEPROM)ro,15744k@0x50000(firmware) ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,1792k(kernel),13952k(rootfs),256k(cfg)ro,64k(EEPROM)ro,15744k@0x50000(firmware) + UBNT_TYPE := BZ + UBNT_CHIP := ar934x + BOARDNAME := UAP-PRO diff --git a/patches/lede/0079-firmware-utils-tplink-safeloader-move-CPE-WBS-210-510-version-metainfo-to-the-end.patch b/patches/lede/0079-firmware-utils-tplink-safeloader-move-CPE-WBS-210-510-version-metainfo-to-the-end.patch new file mode 100644 index 00000000..dbe58d7b --- /dev/null +++ b/patches/lede/0079-firmware-utils-tplink-safeloader-move-CPE-WBS-210-510-version-metainfo-to-the-end.patch @@ -0,0 +1,109 @@ +From: Matthias Schiffer +Date: Tue, 10 Apr 2018 17:26:34 +0200 +Subject: firmware-utils: tplink-safeloader: move CPE/WBS 210/510 version metainfo to the end + +Having the metainfo between kernel and rootfs prevents us from resizing +the kernel partition as necessary. + +Signed-off-by: Matthias Schiffer + +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 11ff2e56e19ec3780f988baf7257810530165b23..2a2329d1f188ea8520b6a4aeef25937e05d48a06 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -139,10 +139,10 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x170000}, +- {"soft-version", 0x1b0000, 0x00100}, +- {"support-list", 0x1b1000, 0x00400}, +- {"file-system", 0x1c0000, 0x600000}, ++ {"os-image", 0x40000, 0x180000}, ++ {"file-system", 0x1c0000, 0x5f0000}, ++ {"soft-version", 0x7b0000, 0x00100}, ++ {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, +@@ -151,7 +151,7 @@ static struct device_info boards[] = { + }, + + .first_sysupgrade_partition = "os-image", +- .last_sysupgrade_partition = "file-system", ++ .last_sysupgrade_partition = "support-list", + }, + + /** Firmware layout for the CPE510/520 */ +@@ -177,10 +177,10 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x170000}, +- {"soft-version", 0x1b0000, 0x00100}, +- {"support-list", 0x1b1000, 0x00400}, +- {"file-system", 0x1c0000, 0x600000}, ++ {"os-image", 0x40000, 0x180000}, ++ {"file-system", 0x1c0000, 0x5f0000}, ++ {"soft-version", 0x7b0000, 0x00100}, ++ {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, +@@ -189,7 +189,7 @@ static struct device_info boards[] = { + }, + + .first_sysupgrade_partition = "os-image", +- .last_sysupgrade_partition = "file-system", ++ .last_sysupgrade_partition = "support-list", + }, + + { +@@ -209,10 +209,10 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x170000}, +- {"soft-version", 0x1b0000, 0x00100}, +- {"support-list", 0x1b1000, 0x00400}, +- {"file-system", 0x1c0000, 0x600000}, ++ {"os-image", 0x40000, 0x180000}, ++ {"file-system", 0x1c0000, 0x5f0000}, ++ {"soft-version", 0x7b0000, 0x00100}, ++ {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, +@@ -221,7 +221,7 @@ static struct device_info boards[] = { + }, + + .first_sysupgrade_partition = "os-image", +- .last_sysupgrade_partition = "file-system", ++ .last_sysupgrade_partition = "support-list", + }, + + { +@@ -241,10 +241,10 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x170000}, +- {"soft-version", 0x1b0000, 0x00100}, +- {"support-list", 0x1b1000, 0x00400}, +- {"file-system", 0x1c0000, 0x600000}, ++ {"os-image", 0x40000, 0x180000}, ++ {"file-system", 0x1c0000, 0x5f0000}, ++ {"soft-version", 0x7b0000, 0x00100}, ++ {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, + {"default-config", 0x7d0000, 0x10000}, + {"log", 0x7e0000, 0x10000}, +@@ -253,7 +253,7 @@ static struct device_info boards[] = { + }, + + .first_sysupgrade_partition = "os-image", +- .last_sysupgrade_partition = "file-system", ++ .last_sysupgrade_partition = "support-list", + }, + + /** Firmware layout for the C2600 */ diff --git a/patches/lede/0080-ar71xx-increase-kernel-partition-size-for-CPE-WBS-210-510.patch b/patches/lede/0080-ar71xx-increase-kernel-partition-size-for-CPE-WBS-210-510.patch new file mode 100644 index 00000000..839e6753 --- /dev/null +++ b/patches/lede/0080-ar71xx-increase-kernel-partition-size-for-CPE-WBS-210-510.patch @@ -0,0 +1,67 @@ +From: Matthias Schiffer +Date: Tue, 10 Apr 2018 18:14:41 +0200 +Subject: ar71xx: increase kernel partition size for CPE/WBS 210/510 + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index be7e846c88f9ebbb8a4e4840e690d7864386bf64..1a6e58fca882fc9d122c184ee8167537751acf25 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -167,7 +167,7 @@ TARGET_DEVICES += archer-c60-v1 + define Device/cpe510-520 + DEVICE_TITLE := TP-LINK CPE510/520 + DEVICE_PACKAGES := rssileds +- MTDPARTS := spi0.0:128k(u-boot)ro,64k(pation-table)ro,64k(product-info)ro,1536k(kernel),6144k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware) ++ MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,1792k(kernel),5888k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware) + IMAGE_SIZE := 7680k + BOARDNAME := CPE510 + TPLINK_BOARD_NAME := CPE510 +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 2a2329d1f188ea8520b6a4aeef25937e05d48a06..ba86c71d870c8f38abb92c657c3656086a7782be 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -139,8 +139,8 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x180000}, +- {"file-system", 0x1c0000, 0x5f0000}, ++ {"os-image", 0x40000, 0x1c0000}, ++ {"file-system", 0x200000, 0x5b0000}, + {"soft-version", 0x7b0000, 0x00100}, + {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, +@@ -177,8 +177,8 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x180000}, +- {"file-system", 0x1c0000, 0x5f0000}, ++ {"os-image", 0x40000, 0x1c0000}, ++ {"file-system", 0x200000, 0x5b0000}, + {"soft-version", 0x7b0000, 0x00100}, + {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, +@@ -209,8 +209,8 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x180000}, +- {"file-system", 0x1c0000, 0x5f0000}, ++ {"os-image", 0x40000, 0x1c0000}, ++ {"file-system", 0x200000, 0x5b0000}, + {"soft-version", 0x7b0000, 0x00100}, + {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, +@@ -241,8 +241,8 @@ static struct device_info boards[] = { + {"default-mac", 0x30000, 0x00020}, + {"product-info", 0x31100, 0x00100}, + {"signature", 0x32000, 0x00400}, +- {"os-image", 0x40000, 0x180000}, +- {"file-system", 0x1c0000, 0x5f0000}, ++ {"os-image", 0x40000, 0x1c0000}, ++ {"file-system", 0x200000, 0x5b0000}, + {"soft-version", 0x7b0000, 0x00100}, + {"support-list", 0x7b1000, 0x00400}, + {"user-config", 0x7c0000, 0x10000}, diff --git a/patches/lede/0081-ar71xx-increase-kernel-partition-size-for-TP-Link-RE450-v1.patch b/patches/lede/0081-ar71xx-increase-kernel-partition-size-for-TP-Link-RE450-v1.patch new file mode 100644 index 00000000..e03db780 --- /dev/null +++ b/patches/lede/0081-ar71xx-increase-kernel-partition-size-for-TP-Link-RE450-v1.patch @@ -0,0 +1,41 @@ +From: Piotr Dymacz +Date: Mon, 6 Nov 2017 23:17:24 +0100 +Subject: ar71xx: increase kernel partition size for TP-Link RE450 v1 + +This increases kernel partition size and fixes rootfs (file-system) +partition size on TP-Link RE450 v1. Also, while we are at it, switch +from statically defined kernel and rootfs partitions in kernel cmdline +to "tplink-fw" mtd splitter. + +Fixes: FS#1072. + +Signed-off-by: Piotr Dymacz + +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 1a6e58fca882fc9d122c184ee8167537751acf25..60dfe0e3edafcadad4ddc08be7645b49f269907c 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -207,7 +207,7 @@ TARGET_DEVICES += cpe210-220 cpe510-520 wbs210 wbs510 + define Device/re450 + DEVICE_TITLE := TP-LINK RE450 + DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca988x +- MTDPARTS := spi0.0:128k(u-boot)ro,1344k(kernel),4672k(rootfs),64k(pation-table)ro,64k(product-info)ro,1856k(config)ro,64k(art)ro,6016k@0x20000(firmware) ++ MTDPARTS := spi0.0:128k(u-boot)ro,6016k(firmware),64k(partition-table)ro,64k(product-info)ro,1856k(config)ro,64k(art)ro + IMAGE_SIZE := 7936k + BOARDNAME := RE450 + TPLINK_BOARD_NAME := RE450 +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index ba86c71d870c8f38abb92c657c3656086a7782be..23b69f3bd0eb66aca650eb2ffd7d5cd2a7cb5194 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -689,8 +689,8 @@ static struct device_info boards[] = { + */ + .partitions = { + {"fs-uboot", 0x00000, 0x20000}, +- {"os-image", 0x20000, 0x150000}, +- {"file-system", 0x170000, 0x4a0000}, ++ {"os-image", 0x20000, 0x180000}, ++ {"file-system", 0x1a0000, 0x460000}, + {"partition-table", 0x600000, 0x02000}, + {"default-mac", 0x610000, 0x00020}, + {"pin", 0x610100, 0x00020}, diff --git a/patches/lede/0082-include-kernel.mk-build-kmod-packages-with-empty-FILES.patch b/patches/lede/0082-include-kernel.mk-build-kmod-packages-with-empty-FILES.patch new file mode 100644 index 00000000..c8c4fcc9 --- /dev/null +++ b/patches/lede/0082-include-kernel.mk-build-kmod-packages-with-empty-FILES.patch @@ -0,0 +1,37 @@ +From: Matthias Schiffer +Date: Tue, 10 Apr 2018 09:03:52 +0200 +Subject: include/kernel.mk: build kmod packages with empty FILES + +kmod packages without FILES did not have an install step defined, leading +to no package being built. This affected netfilter/iptables packages, which +filter out builtin modules from FILES. + +Not building a package that it is selected in .config is problematic, as +the generated empty package may be necessary to satisfy dependencies. + +Signed-off-by: Matthias Schiffer + +diff --git a/include/kernel.mk b/include/kernel.mk +index b1d0e8d927cb462b486cfd645d68963f1b6ab8ff..d8d457fe7a5d3584d8aa4e27430da84533c85ed0 100644 +--- a/include/kernel.mk ++++ b/include/kernel.mk +@@ -194,8 +194,7 @@ $(call KernelPackage/$(1)/config) + $(call KernelPackage/depends) + + ifneq ($(if $(filter-out %=y %=n %=m,$(KCONFIG)),$(filter m y,$(foreach c,$(filter-out %=y %=n %=m,$(KCONFIG)),$($(c)))),.),) +- ifneq ($(strip $(FILES)),) +- define Package/kmod-$(1)/install ++ define Package/kmod-$(1)/install + @for mod in $$(call version_filter,$$(FILES)); do \ + if grep -q "$$$$$$$${mod##$(LINUX_DIR)/}" "$(LINUX_DIR)/modules.builtin"; then \ + echo "NOTICE: module '$$$$$$$$mod' is built-in."; \ +@@ -209,8 +208,7 @@ $(call KernelPackage/$(1)/config) + done; + $(call ModuleAutoLoad,$(1),$$(1),$(AUTOLOAD)) + $(call KernelPackage/$(1)/install,$$(1)) +- endef +- endif ++ endef + $(if $(CONFIG_PACKAGE_kmod-$(1)), + else + compile: $(1)-disabled diff --git a/patches/lede/0083-build-move-lzma2eva-build-step-to-image-commands.mk.patch b/patches/lede/0083-build-move-lzma2eva-build-step-to-image-commands.mk.patch new file mode 100644 index 00000000..856479c9 --- /dev/null +++ b/patches/lede/0083-build-move-lzma2eva-build-step-to-image-commands.mk.patch @@ -0,0 +1,50 @@ +From: Mathias Kresin +Date: Sat, 25 Mar 2017 19:18:37 +0100 +Subject: build: move lzma2eva build step to image-commands.mk + +Move it to image-commands.mk so that it can used by other targets with +eva based boards as well. + +Signed-off-by: Mathias Kresin + +diff --git a/include/image-commands.mk b/include/image-commands.mk +index ec35e0fcfe97d9d98c731459d1f1681d2bcfe5ad..19d98feefe02b6deb43735ccd436aac39fc0a8ab 100644 +--- a/include/image-commands.mk ++++ b/include/image-commands.mk +@@ -11,6 +11,11 @@ define Build/uImage + mv $@.new $@ + endef + ++define Build/eva-image ++ $(STAGING_DIR_HOST)/bin/lzma2eva $(KERNEL_LOADADDR) $(KERNEL_LOADADDR) $@ $@.new ++ mv $@.new $@ ++endef ++ + define Build/netgear-chk + $(STAGING_DIR_HOST)/bin/mkchkimg \ + -o $@.new \ +diff --git a/target/linux/lantiq/image/Makefile b/target/linux/lantiq/image/Makefile +index a96e528aab2c5c5c95f01b087f589cecc57c6e51..2cac925bfd95fedd5f76f30e72300cc0fd7d37a9 100644 +--- a/target/linux/lantiq/image/Makefile ++++ b/target/linux/lantiq/image/Makefile +@@ -20,9 +20,8 @@ else + UBIFS_OPTS := -m 2048 -e 126KiB -c 4096 + endif + +-define Build/eva-image +- lzma2eva $(KERNEL_LOADADDR) $(KERNEL_LOADADDR) $@ $@.new +- ( dd if=$@.new bs=64k conv=sync; cat ./eva.dummy.squashfs; ) > $@ ++define Build/append-avm-fakeroot ++ cat ./eva.dummy.squashfs >> $@ + endef + + define Build/dgn3500-sercom-footer +@@ -104,6 +103,8 @@ endef + + define Device/AVM + KERNEL := kernel-bin | append-dtb | lzma | eva-image ++ IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | append-avm-fakeroot | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) + endef + + ifeq ($(SUBTARGET),xway_legacy) diff --git a/patches/lede/0084-ar71xx-add-support-for-Fritz-Box-4020.patch b/patches/lede/0084-ar71xx-add-support-for-Fritz-Box-4020.patch new file mode 100644 index 00000000..bf307493 --- /dev/null +++ b/patches/lede/0084-ar71xx-add-support-for-Fritz-Box-4020.patch @@ -0,0 +1,572 @@ +From: David Bauer +Date: Tue, 24 Apr 2018 19:52:13 +0200 +Subject: ar71xx: add support for Fritz!Box 4020 + +This commit adds support for the AVM Fritz!Box 4020 WiFi-router. + +SoC: Qualcomm Atheros QCA9561 (Dragonfly) 750MHz +RAM: Winbond W971GG6KB-25 +FLASH: Macronix MX25L12835F +WiFi: QCA9561 b/g/n 3x3 450Mbit/s +USB: 1x USB 2.0 +IN: WPS button, WiFi button +OUT: Power LED green, Internet LED green, WLAN LED green, + LAN LED green, INFO LED green, INFO LED red +UART: Header Next to Black metal shield + Pinout is 3.3V - RX - TX - GND (Square Pad is 3.3V) + The Serial setting is 115200-8-N-1. + +Tested and working: + - Ethernet (LAN + WAN) + - WiFi (correct MAC) + - Installation via EVA bootloader + - OpenWRT sysupgrade + - Buttons + - LEDs + +Not working: + - USB port + +Installation via EVA: +In the first seconds after Power is connected, the bootloader will +listen for FTP connections on 169.254.157.1 (Might also be 192.168.178.1). Firmware can be uploaded +like following: + + ftp> quote USER adam2 + ftp> quote PASS adam2 + ftp> binary + ftp> debug + ftp> passive + ftp> quote MEDIA FLSH + ftp> put openwrt-sysupgrade.bin mtd1 + +Note that this procedure might take up to two minutes. After transfer is +complete you need to powercycle the device to boot OpenWRT. + +Signed-off-by: David Bauer + +diff --git a/include/image-commands.mk b/include/image-commands.mk +index 19d98feefe02b6deb43735ccd436aac39fc0a8ab..7e77b878361ef5a4f6278733d25b0a1fed0ce5ff 100644 +--- a/include/image-commands.mk ++++ b/include/image-commands.mk +@@ -16,6 +16,16 @@ define Build/eva-image + mv $@.new $@ + endef + ++define Build/append-squashfs-fakeroot-be ++ rm -rf $@.fakefs $@.fakesquashfs ++ mkdir $@.fakefs ++ $(STAGING_DIR_HOST)/bin/mksquashfs-lzma \ ++ $@.fakefs $@.fakesquashfs \ ++ -noappend -root-owned -be -nopad -b 65536 \ ++ $(if $(SOURCE_DATE_EPOCH),-fixed-time $(SOURCE_DATE_EPOCH)) ++ cat $@.fakesquashfs >> $@ ++endef ++ + define Build/netgear-chk + $(STAGING_DIR_HOST)/bin/mkchkimg \ + -o $@.new \ +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index f9483e9a706fbd98ce6a42e968bc0d31e9da5c84..e8b13af7c24dea86519c962fa6381fd75971e8b9 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -305,6 +305,12 @@ dlan-pro-1200-ac) + ucidef_set_led_gpio "plcw" "dLAN" "devolo:status:dlan" "17" "0" + ucidef_set_led_gpio "plcr" "dLAN" "devolo:error:dlan" "16" "0" + ;; ++fritz4020) ++ ucidef_set_led_default "power" "Power" "$board:green:power" "1" ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ;; + gl-ar150|\ + gl-ar300|\ + gl-ar300m|\ +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 1690172b5dfac1e1aa278c38c27ba64cfd61ade0..1018ab4449f896d565b57ecbdc73b7e3d7fbe486 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -207,6 +207,7 @@ ar71xx_setup_interfaces() + ;; + archer-c58-v1|\ + archer-c59-v1|\ ++ fritz4020|\ + rb-450g) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ucidef_add_switch "switch0" \ +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +index 945167bee6f7dad76bc650a2bb8a7a71f96b738d..7cb708ebe2e9e7546f165022233d17224905a49c 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/10-ath9k-eeprom +@@ -40,6 +40,24 @@ ath9k_ubi_eeprom_extract() { + ath9k_eeprom_die "failed to extract from $ubi" + } + ++ath9k_eeprom_extract_reverse() { ++ local part=$1 ++ local offset=$2 ++ local count=$3 ++ local mtd ++ local reversed ++ local caldata ++ ++ mtd=$(find_mtd_chardev "$part") ++ reversed=$(hexdump -v -s $offset -n $count -e '/1 "%02x "' $mtd) ++ ++ for byte in $reversed; do ++ caldata="\x${byte}${caldata}" ++ done ++ ++ printf "%b" "$caldata" > /lib/firmware/$FIRMWARE ++} ++ + ath9k_patch_firmware_mac() { + local mac=$1 + +@@ -58,6 +76,9 @@ case "$FIRMWARE" in + ath9k_eeprom_extract "art" 4096 2048 + ath9k_patch_firmware_mac $(macaddr_add $(mtd_get_mac_binary art 0) +1) + ;; ++ fritz4020) ++ ath9k_eeprom_extract_reverse "urlader" 5441 1088 ++ ;; + mr18) + . /lib/upgrade/nand.sh + +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 59ede17653bbb1994ce9fa734c86c877aedf67e4..a815ffe07322c20cddaa3c4f97e3bf62a3cf15ec 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -638,6 +638,9 @@ ar71xx_board_detect() { + name="gl-inet" + gl_inet_board_detect + ;; ++ *"FRITZ!Box 4020") ++ name="fritz4020" ++ ;; + *"GL AR150") + name="gl-ar150" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 5e8a06a7ae70ec349693c09deedbfce41a52cfc2..491b5d5a98b44844f14441d4024f2ad9667186e0 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -612,6 +612,9 @@ platform_check_image() { + + return 0; + ;; ++ fritz4020) ++ return 0 ++ ;; + esac + + echo "Sysupgrade is not yet supported on $board." +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index b84e1cb584f3afce016d0685fb2397962ee85645..9f449973b17a1d82098fb5b50f4b8f6cc9f869f8 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -106,6 +106,7 @@ CONFIG_ATH79_MACH_ESR1750=y + CONFIG_ATH79_MACH_ESR900=y + CONFIG_ATH79_MACH_EW_DORIN=y + CONFIG_ATH79_MACH_F9K1115V2=y ++CONFIG_ATH79_MACH_FRITZ4020=y + CONFIG_ATH79_MACH_GL_AR150=y + CONFIG_ATH79_MACH_GL_AR300=y + CONFIG_ATH79_MACH_GL_AR300M=y +@@ -374,6 +375,7 @@ CONFIG_MTD_PHYSMAP=y + CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-2 + CONFIG_MTD_REDBOOT_PARTS=y + CONFIG_MTD_SPI_NOR=y ++CONFIG_MTD_SPLIT_EVA_FW=y + CONFIG_MTD_SPLIT_FIRMWARE=y + CONFIG_MTD_SPLIT_LZMA_FW=y + CONFIG_MTD_SPLIT_SEAMA_FW=y +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 4c9012acc6b4c40d88ffc8752086cac86b9b9c92..46366e0d922808e5e14fed0f2b5409cda11afd26 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1918,3 +1918,12 @@ config ATH79_MACH_TL_WPA8630 + select ATH79_DEV_LEDS_GPIO + select ATH79_DEV_M25P80 + select ATH79_DEV_WMAC ++ ++config ATH79_MACH_FRITZ4020 ++ bool "AVM FRITZ!Box 4020 support" ++ select SOC_QCA956X ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_USB ++ select ATH79_DEV_M25P80 +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index 8408894669dc5f14f05701359073ef233a1b89f0..29c9c65bc122c0d02839adf1abb61dcda0795fb6 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -111,6 +111,7 @@ obj-$(CONFIG_ATH79_MACH_ESR1750) += mach-esr1750.o + obj-$(CONFIG_ATH79_MACH_ESR900) += mach-esr900.o + obj-$(CONFIG_ATH79_MACH_EW_DORIN) += mach-ew-dorin.o + obj-$(CONFIG_ATH79_MACH_F9K1115V2) += mach-f9k1115v2.o ++obj-$(CONFIG_ATH79_MACH_FRITZ4020) += mach-fritz4020.o + obj-$(CONFIG_ATH79_MACH_GL_AR150) += mach-gl-ar150.o + obj-$(CONFIG_ATH79_MACH_GL_AR300) += mach-gl-ar300.o + obj-$(CONFIG_ATH79_MACH_GL_AR300M) += mach-gl-ar300m.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +index 427de6a50d0fcbc9dae11f8e6921194c0a5b09ed..5f971ea32d35035617229076b7a7fc30ed4d2dcc 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c +@@ -1224,6 +1224,15 @@ void __init ath79_parse_ascii_mac(char *mac_str, u8 *mac) + } + } + ++void __init ath79_extract_mac_reverse(u8 *ptr, u8 *out) ++{ ++ int i; ++ ++ for (i = 0; i < ETH_ALEN; i++) { ++ out[i] = ptr[ETH_ALEN-i-1]; ++ } ++} ++ + static void __init ath79_set_mac_base_ascii(char *str) + { + u8 mac[ETH_ALEN]; +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h +index fb9e4f63c66ef9008e423007ecff02c93c321fb8..4d78260fbe35db20f8dc6dd245abcd0cbb275477 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.h +@@ -18,6 +18,7 @@ struct platform_device; + + extern unsigned char ath79_mac_base[] __initdata; + void ath79_parse_ascii_mac(char *mac_str, u8 *mac); ++void ath79_extract_mac_reverse(u8 *ptr, u8 *out); + void ath79_init_mac(unsigned char *dst, const unsigned char *src, + int offset); + void ath79_init_local_mac(unsigned char *dst, const unsigned char *src); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c +new file mode 100644 +index 0000000000000000000000000000000000000000..ed7f9a8b3ead80dbbe7f8d27c7dd5ecf0543d733 +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-fritz4020.c +@@ -0,0 +1,242 @@ ++/* ++ * AVM FRITZ!Box 4020 board support ++ * ++ * Copyright (C) 2018 David Bauer ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-spi.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++ ++#define FRITZ4020_GPIO_SHIFT_SER 19 /* DS, Data Serial Input */ ++#define FRITZ4020_GPIO_SHIFT_SRCLK 20 /* SHCP, Shift Reg Clock Input */ ++ ++#define FRITZ4020_SSR_BIT_0 0 ++#define FRITZ4020_SSR_BIT_1 1 ++#define FRITZ4020_SSR_BIT_2 2 ++#define FRITZ4020_SSR_BIT_3 3 ++#define FRITZ4020_SSR_BIT_4 4 ++#define FRITZ4020_SSR_BIT_5 5 ++#define FRITZ4020_SSR_BIT_6 6 ++#define FRITZ4020_SSR_BIT_7 7 ++ ++#define FRITZ4020_74HC_GPIO_BASE 32 ++#define FRITZ4020_74HC_GPIO_LED_LAN (FRITZ4020_74HC_GPIO_BASE + 0) ++#define FRITZ4020_74HC_GPIO_LED_INFO_RED (FRITZ4020_74HC_GPIO_BASE + 1) ++#define FRITZ4020_74HC_GPIO_LED_POWER (FRITZ4020_74HC_GPIO_BASE + 2) ++#define FRITZ4020_74HC_GPIO_LED_WLAN (FRITZ4020_74HC_GPIO_BASE + 3) ++#define FRITZ4020_74HC_GPIO_LED_WAN (FRITZ4020_74HC_GPIO_BASE + 4) ++#define FRITZ4020_74HC_GPIO_USB_RST (FRITZ4020_74HC_GPIO_BASE + 5) ++#define FRITZ4020_74HC_GPIO_LED_INFO (FRITZ4020_74HC_GPIO_BASE + 6) ++ ++ ++#define FRITZ4020_GPIO_BTN_WPS 2 ++#define FRITZ4020_GPIO_BTN_WLAN 21 ++#define FRITZ4020_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define FRITZ4020_KEYS_DEBOUNCE_INTERVAL (3 * FRITZ4020_KEYS_POLL_INTERVAL) ++ ++#define FRTIZ4020_OFFSET_URLADER_WIFI_MAC_REVERSE 0x1979 ++ ++ ++static struct spi_gpio_platform_data fritz4020_spi_data = { ++ .sck = FRITZ4020_GPIO_SHIFT_SRCLK, ++ .miso = SPI_GPIO_NO_MISO, ++ .mosi = FRITZ4020_GPIO_SHIFT_SER, ++ .num_chipselect = 1, ++}; ++ ++static u8 fritz4020_ssr_initdata[] = { ++ BIT(FRITZ4020_SSR_BIT_7) | ++ BIT(FRITZ4020_SSR_BIT_6) | ++ BIT(FRITZ4020_SSR_BIT_5) | ++ BIT(FRITZ4020_SSR_BIT_4) | ++ BIT(FRITZ4020_SSR_BIT_3) | ++ BIT(FRITZ4020_SSR_BIT_2) | ++ BIT(FRITZ4020_SSR_BIT_1) ++}; ++ ++static struct gen_74x164_chip_platform_data fritz4020_ssr_data = { ++ .base = FRITZ4020_74HC_GPIO_BASE, ++ .num_registers = ARRAY_SIZE(fritz4020_ssr_initdata), ++ .init_data = fritz4020_ssr_initdata, ++}; ++ ++static struct platform_device fritz4020_spi_device = { ++ .name = "spi_gpio", ++ .id = 1, ++ .dev = { ++ .platform_data = &fritz4020_spi_data, ++ }, ++}; ++ ++static struct spi_board_info fritz4020_spi_info[] = { ++ { ++ .bus_num = 1, ++ .chip_select = 0, ++ .max_speed_hz = 10000000, ++ .modalias = "74x164", ++ .platform_data = &fritz4020_ssr_data, ++ .controller_data = (void *) 0x0, ++ }, ++}; ++ ++static struct mtd_partition fritz4020_flash_partitions[] = { ++ { ++ .name = "urlader", ++ .offset = 0, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0020000, ++ .size = 0x0EE0000, ++ }, { ++ .name = "tffs (1)", ++ .offset = 0x0f00000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "tffs (2)", ++ .offset = 0x0f80000, ++ .size = 0x0080000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++ ++static struct flash_platform_data fritz4020_flash_data = { ++ .parts = fritz4020_flash_partitions, ++ .nr_parts = ARRAY_SIZE(fritz4020_flash_partitions), ++}; ++ ++static struct gpio_led fritz4020_leds_gpio[] __initdata = { ++ { ++ .name = "fritz4020:green:lan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_LAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:info", ++ .gpio = FRITZ4020_74HC_GPIO_LED_INFO, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:red:info", ++ .gpio = FRITZ4020_74HC_GPIO_LED_INFO_RED, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:power", ++ .gpio = FRITZ4020_74HC_GPIO_LED_POWER, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:wlan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "fritz4020:green:wan", ++ .gpio = FRITZ4020_74HC_GPIO_LED_WAN, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button fritz4020_gpio_keys[] __initdata = { ++ { ++ .desc = "RFKILL button", ++ .type = EV_KEY, ++ .code = KEY_RFKILL, ++ .debounce_interval = FRITZ4020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = FRITZ4020_GPIO_BTN_WLAN, ++ .active_low = 0, ++ }, ++ { ++ .desc = "WPS button", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .debounce_interval = FRITZ4020_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = FRITZ4020_GPIO_BTN_WPS, ++ .active_low = 0, ++ }, ++}; ++ ++static void __init fritz4020_setup(void) { ++ u8 *urlader = (u8 *) KSEG1ADDR(0x1f000000); ++ u8 wifi_mac[ETH_ALEN]; ++ ++ ath79_register_m25p80(&fritz4020_flash_data); ++ ++ /* Initialize ethernet */ ++ ath79_extract_mac_reverse(urlader + FRTIZ4020_OFFSET_URLADER_WIFI_MAC_REVERSE, wifi_mac); ++ ath79_setup_qca956x_eth_cfg(QCA956X_ETH_CFG_SW_PHY_SWAP | ++ QCA956X_ETH_CFG_SW_PHY_ADDR_SWAP); ++ ++ ath79_register_mdio(0, 0x0); ++ ath79_register_mdio(1, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, wifi_mac, -1); ++ ath79_init_mac(ath79_eth1_data.mac_addr, wifi_mac, -2); ++ ++ /* WAN port */ ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(0); ++ ath79_register_eth(0); ++ ++ /* LAN ports */ ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(0); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ /* Initialize 2.4GHz WiFi */ ++ ath79_register_wmac_simple(); ++ ++ /* Activate USB Power */ ++ gpio_request_one(FRITZ4020_74HC_GPIO_USB_RST, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ /* Initialize USB port */ ++ ath79_register_usb(); ++ ++ /* Register LED shift-register */ ++ spi_register_board_info(fritz4020_spi_info, ++ ARRAY_SIZE(fritz4020_spi_info)); ++ platform_device_register(&fritz4020_spi_device); ++ ++ /* Register GPIO buttons */ ++ ath79_register_gpio_keys_polled(-1, FRITZ4020_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(fritz4020_gpio_keys), ++ fritz4020_gpio_keys); ++ ++ /* Register LEDs */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(fritz4020_leds_gpio), ++ fritz4020_leds_gpio); ++} ++ ++MIPS_MACHINE(ATH79_MACH_FRITZ4020, "FRITZ4020", ++ "AVM FRITZ!Box 4020", fritz4020_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 72c1e38c74707aba8fbd3aebc36f35becabd4987..07f1877180e27ff189387c5f34a61702d0fa9bd2 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -102,6 +102,7 @@ enum ath79_mach_type { + ATH79_MACH_EW_DORIN, /* embedded wireless Dorin Platform */ + ATH79_MACH_EW_DORIN_ROUTER, /* embedded wireless Dorin Router Platform */ + ATH79_MACH_F9K1115V2, /* Belkin AC1750DB */ ++ ATH79_MACH_FRITZ4020, /* AVM FRITZ!Box 4020 */ + ATH79_MACH_GL_AR150, /* GL-AR150 support */ + ATH79_MACH_GL_AR300, /* GL-AR300 */ + ATH79_MACH_GL_AR300M, /* GL-AR300M */ +diff --git a/target/linux/ar71xx/image/generic.mk b/target/linux/ar71xx/image/generic.mk +index e11a8992f9c2f950079fddf121eb30c34926e33d..d113c5ad621bb2f15d4cbc4fd50e60904313a7da 100644 +--- a/target/linux/ar71xx/image/generic.mk ++++ b/target/linux/ar71xx/image/generic.mk +@@ -738,3 +738,22 @@ define Device/bhr-4grv2 + IMAGE/factory.bin = append-kernel | pad-to $$$$(KERNEL_SIZE) | append-rootfs | pad-rootfs | mkbuffaloimg + endef + TARGET_DEVICES += bhr-4grv2 ++ ++define Device/AVM ++ DEVICE_PACKAGES := fritz-tffs -uboot-envtools ++ KERNEL := kernel-bin | patch-cmdline | lzma | eva-image ++ KERNEL_INITRAMFS := $$(KERNEL) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to 64k | \ ++ append-squashfs-fakeroot-be | pad-to 256 | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++ ++define Device/fritz4020 ++ $(call Device/AVM) ++ DEVICE_TITLE := AVM FRITZ!Box 4020 ++ DEVICE_PACKAGES := kmod-usb-core kmod-usb2 kmod-usb-storage ++ BOARDNAME := FRITZ4020 ++ SUPPORTED_DEVICES := fritz4020 ++ IMAGE_SIZE := 15232k ++endef ++TARGET_DEVICES += fritz4020 +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index 23e862762600f0724a37fe1a390d4d09639c472c..e0401102229c00985e8000331dce43375903e1aa 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -71,6 +71,7 @@ + # CONFIG_ATH79_MACH_ESR900 is not set + # CONFIG_ATH79_MACH_EW_DORIN is not set + # CONFIG_ATH79_MACH_F9K1115V2 is not set ++# CONFIG_ATH79_MACH_FRITZ4020 is not set + # CONFIG_ATH79_MACH_GL_AR150 is not set + # CONFIG_ATH79_MACH_GL_AR300 is not set + # CONFIG_ATH79_MACH_GL_AR300M is not set +@@ -217,6 +218,7 @@ CONFIG_MTD_NAND_ECC=y + CONFIG_MTD_NAND_RB4XX=y + CONFIG_MTD_NAND_RB750=y + CONFIG_MTD_NAND_RB91X=y ++# CONFIG_MTD_SPLIT_EVA_FW is not set + # CONFIG_MTD_REDBOOT_PARTS is not set + # CONFIG_MTD_TPLINK_PARTS is not set + CONFIG_MTD_UBI=y +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index c11ccfe29795d013776870cf21fb6ca8d907af1b..790fa8f9bd42aba8521b960c2a49a742285e6157 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -29,6 +29,7 @@ + # CONFIG_ATH79_MACH_DIR_869_A1 is not set + # CONFIG_ATH79_MACH_EAP7660D is not set + # CONFIG_ATH79_MACH_EW_DORIN is not set ++# CONFIG_ATH79_MACH_FRITZ4020 is not set + # CONFIG_ATH79_MACH_HORNET_UB is not set + # CONFIG_ATH79_MACH_JA76PF is not set + # CONFIG_ATH79_MACH_JWAP003 is not set +@@ -104,6 +105,7 @@ CONFIG_MTD_NAND_ECC=y + CONFIG_MTD_NAND_ECC_BCH=y + # CONFIG_MTD_REDBOOT_PARTS is not set + # CONFIG_MTD_SM_COMMON is not set ++# CONFIG_MTD_SPLIT_EVA_FW is not set + # CONFIG_MTD_SPLIT_SEAMA_FW is not set + # CONFIG_MTD_TPLINK_PARTS is not set + CONFIG_MTD_UBI=y diff --git a/patches/lede/0085-ar71xx-add-support-for-TP-Link-TL-WR940N-v6.patch b/patches/lede/0085-ar71xx-add-support-for-TP-Link-TL-WR940N-v6.patch new file mode 100644 index 00000000..4cbe2d82 --- /dev/null +++ b/patches/lede/0085-ar71xx-add-support-for-TP-Link-TL-WR940N-v6.patch @@ -0,0 +1,233 @@ +From: Robert Marko +Date: Wed, 21 Feb 2018 13:15:17 +0100 +Subject: ar71xx: add support for TP-Link TL-WR940N v6 + +Add support for TL-WR940N v6 board. It is pretty much the same as v5 +except they only left WAN LED and removed other ones. + +Installation: flash factory image through WEB UI or use TFTP. + +Signed-off-by: Robert Marko + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index e8b13af7c24dea86519c962fa6381fd75971e8b9..62d7f014be28782b9961551f2377a66ccadfb329 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -676,6 +676,9 @@ tl-wr941nd-v6) + ucidef_set_led_switch "lan4" "LAN4" "tp-link:blue:lan4" "switch0" "0x02" + ucidef_set_led_wlan "wlan" "WLAN" "tp-link:blue:wlan" "phy0tpt" + ;; ++tl-wr940n-v6) ++ ucidef_set_led_netdev "wan" "WAN" "tp-link:blue:wan" "eth0" ++ ;; + tl-wr841n-v9|\ + tl-wr841n-v11|\ + tl-wr842n-v3) +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 1018ab4449f896d565b57ecbdc73b7e3d7fbe486..ae82cfe008169a8282ac51746cf2299eec8c81d8 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -298,6 +298,7 @@ ar71xx_setup_interfaces() + tl-wdr6500-v2|\ + tl-wr841n-v8|\ + tl-wr940n-v4|\ ++ tl-wr940n-v6|\ + tl-wr941nd-v5|\ + tl-wr941nd-v6|\ + wnr1000-v2|\ +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 382500b75ee6dc1fe1126fb3121f4ae205c901d4..4d792e773c8efe0cb2e5e328d777db853cdd846b 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -397,6 +397,9 @@ get_status_led() { + tl-wr941nd-v6) + status_led="tp-link:blue:system" + ;; ++ tl-wr940n-v6) ++ status_led="tp-link:orange:diag" ++ ;; + tl-wr841n-v9) + status_led="tp-link:green:qss" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index a815ffe07322c20cddaa3c4f97e3bf62a3cf15ec..21b1c44404d383ef99860caf95a8e19b9cbf5087 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -1082,6 +1082,9 @@ ar71xx_board_detect() { + *TL-WR941ND) + name="tl-wr941nd" + ;; ++ *"TL-WR940N v6") ++ name="tl-wr940n-v6" ++ ;; + *"TL-WR941N/ND v5") + name="tl-wr941nd-v5" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 491b5d5a98b44844f14441d4024f2ad9667186e0..03677ad1240c9a5af341354b95561f9d493a9cd8 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -443,6 +443,7 @@ platform_check_image() { + tl-wr941nd-v5|\ + tl-wr941nd-v6|\ + tl-wr940n-v4|\ ++ tl-wr940n-v6|\ + tl-wr941nd) + local magic_ver="0100" + +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c +index d693b947c843d2a74cd252503fa8bf68b20da4ab..b530622d9f00b8ce3b906ad5fe62de019d82763a 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wr940n-v4.c +@@ -1,5 +1,5 @@ + /* +- * TP-LINK TL-WR940N v4 board support ++ * TP-LINK TL-WR940N v4 and v6 board support + * + * Copyright (C) 2016 David Lutz + * +@@ -32,12 +32,15 @@ + #define TL_WR940N_V4_GPIO_LED_LAN1 8 + #define TL_WR940N_V4_GPIO_LED_WLAN 7 + #define TL_WR940N_V4_GPIO_LED_SYSTEM 5 ++/* WR940N v6 specific GPIO*/ ++#define TL_WR940N_V6_GPIO_LED_DIAG_ORANGE 15 ++#define TL_WR940N_V6_GPIO_LED_WAN_BLUE 14 + + #define TL_WR940N_V4_GPIO_BTN_RESET 1 + #define TL_WR940N_V4_GPIO_BTN_RFKILL 2 + +-#define TL_WR940N_V4_KEYS_POLL_INTERVAL 20 +-#define TL_WR940N_V4_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR940N_V4_KEYS_POLL_INTERVAL) ++#define TL_WR940N_KEYS_POLL_INTERVAL 20 ++#define TL_WR940N_KEYS_DEBOUNCE_INTERVAL (3 * TL_WR940N_KEYS_POLL_INTERVAL) + + + static struct gpio_led tl_wr940n_v4_leds_gpio[] __initdata = { +@@ -93,43 +96,49 @@ static struct gpio_keys_button tl_wr940n_v4_gpio_keys[] __initdata = { + .desc = "Reset button", + .type = EV_KEY, + .code = KEY_RESTART, +- .debounce_interval = TL_WR940N_V4_KEYS_DEBOUNCE_INTERVAL, ++ .debounce_interval = TL_WR940N_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR940N_V4_GPIO_BTN_RESET, + .active_low = 1, + }, { + .desc = "RFKILL button", + .type = EV_KEY, + .code = KEY_RFKILL, +- .debounce_interval = TL_WR940N_V4_KEYS_DEBOUNCE_INTERVAL, ++ .debounce_interval = TL_WR940N_KEYS_DEBOUNCE_INTERVAL, + .gpio = TL_WR940N_V4_GPIO_BTN_RFKILL, + .active_low = 1, + } + }; + ++static struct gpio_led tl_wr940n_v6_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:blue:wan", ++ .gpio = TL_WR940N_V6_GPIO_LED_WAN_BLUE, ++ .active_low = 1, ++ }, ++ { ++ .name = "tp-link:orange:diag", ++ .gpio = TL_WR940N_V6_GPIO_LED_DIAG_ORANGE, ++ .active_low = 0, ++ }, ++}; ++ + +-static const char *tl_wr940n_v4_part_probes[] = { ++static const char *tl_wr940n_part_probes[] = { + "tp-link", + NULL, + }; + +-static struct flash_platform_data tl_wr940n_v4_flash_data = { +- .part_probes = tl_wr940n_v4_part_probes, ++static struct flash_platform_data tl_wr940n_flash_data = { ++ .part_probes = tl_wr940n_part_probes, + }; + + +-static void __init tl_wr940n_v4_setup(void) ++static void __init tl_wr940n_setup(void) + { + u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); + u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); + +- ath79_register_m25p80(&tl_wr940n_v4_flash_data); +- +- ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr940n_v4_leds_gpio), +- tl_wr940n_v4_leds_gpio); +- +- ath79_register_gpio_keys_polled(-1, TL_WR940N_V4_KEYS_POLL_INTERVAL, +- ARRAY_SIZE(tl_wr940n_v4_gpio_keys), +- tl_wr940n_v4_gpio_keys); ++ ath79_register_m25p80(&tl_wr940n_flash_data); + + ath79_register_mdio(0, 0x0); + +@@ -145,5 +154,31 @@ static void __init tl_wr940n_v4_setup(void) + + } + ++static void __init tl_wr940n_v4_setup(void) ++{ ++ tl_wr940n_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr940n_v4_leds_gpio), ++ tl_wr940n_v4_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR940N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr940n_v4_gpio_keys), ++ tl_wr940n_v4_gpio_keys); ++} ++ ++static void __init tl_wr940n_v6_setup(void) ++{ ++ tl_wr940n_setup(); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(tl_wr940n_v6_leds_gpio), ++ tl_wr940n_v6_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, TL_WR940N_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr940n_v4_gpio_keys), ++ tl_wr940n_v4_gpio_keys); ++} ++ + MIPS_MACHINE(ATH79_MACH_TL_WR940N_V4, "TL-WR940N-v4", "TP-LINK TL-WR940N v4", + tl_wr940n_v4_setup); ++MIPS_MACHINE(ATH79_MACH_TL_WR940N_V6, "TL-WR940N-v6", "TP-LINK TL-WR940N v6", ++ tl_wr940n_v6_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 07f1877180e27ff189387c5f34a61702d0fa9bd2..89ddbbc976c9393608a80b9ce56e02a4d403ea2a 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -242,6 +242,7 @@ enum ath79_mach_type { + ATH79_MACH_TL_WR941ND_V5, /* TP-LINK TL-WR941ND v5 */ + ATH79_MACH_TL_WR941ND_V6, /* TP-LINK TL-WR941ND v6 */ + ATH79_MACH_TL_WR940N_V4, /* TP-LINK TL-WR940N v4 */ ++ ATH79_MACH_TL_WR940N_V6, /* TP-LINK TL-WR940N v6 */ + ATH79_MACH_TUBE2H, /* Alfa Network Tube2H */ + ATH79_MACH_UBNT_AIRGW, /* Ubiquiti AirGateway */ + ATH79_MACH_UBNT_AIRGWP, /* Ubiquiti AirGateway Pro */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 60dfe0e3edafcadad4ddc08be7645b49f269907c..1e40d943ac2aa43aea670fd86268708aea39a46c 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -857,6 +857,14 @@ define Device/tl-wr940n-v4 + IMAGE/factory-eu.bin := append-rootfs | mktplinkfw factory -C EU + endef + ++define Device/tl-wr940n-v6 ++ $(Device/tl-wr940n-v4) ++ DEVICE_TITLE := TP-LINK TL-WR940N v6 ++ BOARDNAME := TL-WR940N-v6 ++ TPLINK_HWID := 0x09400006 ++endef ++TARGET_DEVICES += tl-wr940n-v6 ++ + # Chinese version (unlike European) is similar to the TL-WDR3500 + define Device/tl-wr941nd-v6-cn + $(Device/tplink-4mlzma) diff --git a/patches/lede/0086-ar71xx-set-status-led-for-the-gl-boards.patch b/patches/lede/0086-ar71xx-set-status-led-for-the-gl-boards.patch new file mode 100644 index 00000000..3dd8739b --- /dev/null +++ b/patches/lede/0086-ar71xx-set-status-led-for-the-gl-boards.patch @@ -0,0 +1,348 @@ +From: Wojciech Jowsa +Date: Wed, 15 Feb 2017 12:38:07 +0100 +Subject: ar71xx: set status led for the gl-* boards + +Signed-off-by: Wojciech Jowsa + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 62d7f014be28782b9961551f2377a66ccadfb329..f4d83cee519406a188cc9dde355f509dd644625a 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -311,19 +311,18 @@ fritz4020) + ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" + ;; +-gl-ar150|\ +-gl-ar300|\ +-gl-ar300m|\ ++gl-ar300m) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" ++ ;; + gl-mifi) ++ ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" ++ ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" ++ ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" ++ ucidef_set_led_netdev "3gnet" "3GNET" "$board:green:net" "3g-wan" ++ ;; ++gl-ar150|\ ++gl-ar300) + ucidef_set_led_wlan "wlan" "WLAN" "$board:wlan" "phy0tpt" +- +- case "$board" in +- gl-mifi) +- ucidef_set_led_netdev "wan" "WAN" "$board:wan" "eth0" +- ucidef_set_led_netdev "lan" "LAN" "$board:lan" "eth1" +- ucidef_set_led_netdev "3gnet" "3GNET" "$board:net" "3g-wan" +- ;; +- esac + ;; + gl-domino|\ + wrt160nl) +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 4d792e773c8efe0cb2e5e328d777db853cdd846b..336d078f72a06073e3465c36ca98035c7d70282f 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -64,7 +64,9 @@ get_status_led() { + ap90q|\ + cpe830|\ + cpe870|\ +- gl-inet) ++ gl-inet|\ ++ gl-mifi|\ ++ gl-ar300m) + status_led="$board:green:lan" + ;; + ap96) +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c +index 62906a1922f890eb36ad212e9542dc52dc56006c..ca44b364c51559350fedc5551a023b2772bb69a1 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar300m.c +@@ -6,9 +6,9 @@ + * Copyright (C) 2013 alzhao + * Copyright (C) 2014 Michel Stempin + * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License version 2 as published +- * by the Free Software Foundation. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. + */ + + #include +@@ -37,130 +37,130 @@ + #define GL_AR300M_GPIO_BTN_LEFT 0 + #define GL_AR300M_GPIO_BTN_RIGHT 1 + +-#define GL_AR300M_KEYS_POLL_INTERVAL 20 /* msecs */ +-#define GL_AR300M_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR300M_KEYS_POLL_INTERVAL) ++#define GL_AR300M_KEYS_POLL_INTERVAL 20 /* msecs */ ++#define GL_AR300M_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR300M_KEYS_POLL_INTERVAL) + +-#define GL_AR300M_MAC0_OFFSET 0 +-#define GL_AR300M_MAC1_OFFSET 6 +-#define GL_AR300M_WMAC_CALDATA_OFFSET 0x1000 +-#define GL_AR300M_PCIE_CALDATA_OFFSET 0x5000 ++#define GL_AR300M_MAC0_OFFSET 0 ++#define GL_AR300M_MAC1_OFFSET 6 ++#define GL_AR300M_WMAC_CALDATA_OFFSET 0x1000 ++#define GL_AR300M_PCIE_CALDATA_OFFSET 0x5000 + + static struct gpio_led gl_ar300m_leds_gpio[] __initdata = { +- { +- .name = "gl-ar300m:usb", +- .gpio = GL_AR300M_GPIO_LED_USB, +- .active_low = 0, +- .default_state = 1, +- }, +- { +- .name = "gl-ar300m:wlan", +- .gpio = GL_AR300M_GPIO_LED_WLAN, +- .active_low = 1, +- }, +- { +- .name = "gl-ar300m:lan", +- .gpio = GL_AR300M_GPIO_LED_LAN, +- .active_low = 1, +- }, +- { +- .name = "gl-ar300m:system", +- .gpio = GL_AR300M_GPIO_LED_SYSTEM, +- .active_low = 1, +- .default_state = 1, +- }, ++ { ++ .name = "gl-ar300m:green:usb", ++ .gpio = GL_AR300M_GPIO_LED_USB, ++ .active_low = 0, ++ .default_state = 1, ++ }, ++ { ++ .name = "gl-ar300m:green:wlan", ++ .gpio = GL_AR300M_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-ar300m::green:lan", ++ .gpio = GL_AR300M_GPIO_LED_LAN, ++ .active_low = 1, ++ }, ++ { ++ .name = "gl-ar300m:green:system", ++ .gpio = GL_AR300M_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ .default_state = 1, ++ }, + }; + + static struct gpio_keys_button gl_ar300m_gpio_keys[] __initdata = { +- { +- .desc = "reset", +- .type = EV_KEY, +- .code = KEY_RESTART, +- .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, +- .gpio = GL_AR300M_GPIO_BTN_RESET, +- .active_low = 1, +- }, +- { +- .desc = "button right", +- .type = EV_KEY, +- .code = BTN_0, +- .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, +- .gpio = GL_AR300M_GPIO_BTN_LEFT, +- .active_low = 0, +- }, +- { +- .desc = "button left", +- .type = EV_KEY, +- .code = BTN_1, +- .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, +- .gpio = GL_AR300M_GPIO_BTN_RIGHT, +- .active_low = 0, +- }, ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, ++ { ++ .desc = "button right", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_LEFT, ++ .active_low = 0, ++ }, ++ { ++ .desc = "button left", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .debounce_interval = GL_AR300M_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR300M_GPIO_BTN_RIGHT, ++ .active_low = 0, ++ }, + }; + + static struct spi_board_info gl_ar300m_spi_info[] = { +- { +- .bus_num = 0, +- .chip_select = 0, +- .max_speed_hz = 25000000, +- .modalias = "m25p80", +- .platform_data = NULL, +- }, +- { +- .bus_num = 0, +- .chip_select = 1, +- .max_speed_hz = 25000000, +- .modalias = "ath79-spinand", +- .platform_data = NULL, +- } ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = NULL, ++ }, ++ { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "ath79-spinand", ++ .platform_data = NULL, ++ } + }; + + static struct ath79_spi_platform_data gl_ar300m_spi_data = { +- .bus_num = 0, +- .num_chipselect = 2, ++ .bus_num = 0, ++ .num_chipselect = 2, + }; + + static void __init gl_ar300m_setup(void) + { +- u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); +- u8 tmpmac[ETH_ALEN]; +- +- ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); +- ath79_register_spi(&gl_ar300m_spi_data, gl_ar300m_spi_info, 2); +- +- /* register gpio LEDs and keys */ +- ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar300m_leds_gpio), +- gl_ar300m_leds_gpio); +- ath79_register_gpio_keys_polled(-1, GL_AR300M_KEYS_POLL_INTERVAL, +- ARRAY_SIZE(gl_ar300m_gpio_keys), +- gl_ar300m_gpio_keys); +- +- ath79_register_mdio(0, 0x0); +- +- /* WAN */ +- ath79_init_mac(ath79_eth0_data.mac_addr, art + GL_AR300M_MAC0_OFFSET, 0); +- ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; +- ath79_eth0_data.speed = SPEED_100; +- ath79_eth0_data.duplex = DUPLEX_FULL; +- ath79_eth0_data.phy_mask = BIT(4); +- ath79_register_eth(0); +- +- /* LAN */ +- ath79_init_mac(ath79_eth1_data.mac_addr, art + GL_AR300M_MAC1_OFFSET, 0); +- ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; +- ath79_eth1_data.speed = SPEED_1000; +- ath79_eth1_data.duplex = DUPLEX_FULL; +- ath79_switch_data.phy_poll_mask |= BIT(4); +- ath79_switch_data.phy4_mii_en = 1; +- ath79_register_eth(1); +- +- ath79_init_mac(tmpmac, art + GL_AR300M_WMAC_CALDATA_OFFSET + 2, 0); +- ath79_register_wmac(art + GL_AR300M_WMAC_CALDATA_OFFSET, tmpmac); +- +- /* enable usb */ +- ath79_register_usb(); +- /* enable pci */ +- ath79_register_pci(); ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 tmpmac[ETH_ALEN]; ++ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ath79_register_spi(&gl_ar300m_spi_data, gl_ar300m_spi_info, 2); ++ ++ /* register gpio LEDs and keys */ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar300m_leds_gpio), ++ gl_ar300m_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, GL_AR300M_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar300m_gpio_keys), ++ gl_ar300m_gpio_keys); ++ ++ ath79_register_mdio(0, 0x0); ++ ++ /* WAN */ ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + GL_AR300M_MAC0_OFFSET, 0); ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + GL_AR300M_MAC1_OFFSET, 0); ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_eth1_data.speed = SPEED_1000; ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_switch_data.phy_poll_mask |= BIT(4); ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_register_eth(1); ++ ++ ath79_init_mac(tmpmac, art + GL_AR300M_WMAC_CALDATA_OFFSET + 2, 0); ++ ath79_register_wmac(art + GL_AR300M_WMAC_CALDATA_OFFSET, tmpmac); ++ ++ /* enable usb */ ++ ath79_register_usb(); ++ /* enable pci */ ++ ath79_register_pci(); + } + + MIPS_MACHINE(ATH79_MACH_GL_AR300M, "GL-AR300M", "GL-AR300M", +- gl_ar300m_setup); ++ gl_ar300m_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c +index 42f4415d7fe0252aadf39e2ca50f96566c023728..412c562fa042e7abb0ccb35208bb55821efc8660 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-mifi.c +@@ -41,27 +41,27 @@ + + static struct gpio_led gl_mifi_leds_gpio[] __initdata = { + { +- .name = "gl-mifi:wan", ++ .name = "gl-mifi:greeen:wan", + .gpio = GL_MIFI_GPIO_LED_WAN, + .active_low = 0, + }, + { +- .name = "gl-mifi:lan", ++ .name = "gl-mifi:green:lan", + .gpio = GL_MIFI_GPIO_LED_LAN, + .active_low = 0, + }, + { +- .name = "gl-mifi:wlan", ++ .name = "gl-mifi:green:wlan", + .gpio = GL_MIFI_GPIO_LED_WLAN, + .active_low = 0, + }, + { +- .name = "gl-mifi:net", ++ .name = "gl-mifi:green:net", + .gpio = GL_MIFI_GPIO_LED_NET, + .active_low = 0, + }, + { +- .name = "gl-mifi:3gcontrol", ++ .name = "gl-mifi:green:3gcontrol", + .gpio = GL_MIFI_GPIO_LED_3GCONTROL, + .active_low = 0, + } diff --git a/patches/lede/0087-ar71xx-add-support-for-GL.iNet-GL-AR750.patch b/patches/lede/0087-ar71xx-add-support-for-GL.iNet-GL-AR750.patch new file mode 100644 index 00000000..7c574e94 --- /dev/null +++ b/patches/lede/0087-ar71xx-add-support-for-GL.iNet-GL-AR750.patch @@ -0,0 +1,364 @@ +From: Piotr Dymacz +Date: Tue, 17 Oct 2017 23:30:01 +0200 +Subject: ar71xx: add support for GL.iNet GL-AR750 + +GL.iNet GL-AR750 is a small size, dual-band (AC750) router, based on +Qualcomm/Atheros QCA9531 v2 + QCA9887. FCC ID: 2AFIW-AR750. + +Specification: + +- 650/597/216 MHz (CPU/DDR/AHB) +- 128 MB of RAM (DDR2) +- 16 MB of FLASH (SPI NOR) +- 3x 10/100 Mbps Ethernet +- 2T2R 2.4 GHz (QCA9531) +- 1T1R 5 GHz (QCA9887) +- 1x USB 2.0 (power controlled by GPIO) +- 1x microSD (GL857L) +- 3x LED (all driven by GPIO) +- 1x button (reset) +- 1x 2-pos switch +- header for optional PoE module +- 1x micro USB for main power input +- UART + I2C header on PCB + +Flash instruction: + +Vendor firmware is based on OpenWrt/LEDE. GUI or sysupgrade can be used +to flash OpenWrt/LEDE firmware. + +Signed-off-by: Piotr Dymacz + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index f4d83cee519406a188cc9dde355f509dd644625a..f94cc3c85b798458cc97c06bb0d44bdc426d057d 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -314,6 +314,10 @@ fritz4020) + gl-ar300m) + ucidef_set_led_wlan "wlan" "WLAN" "$board:red:wlan" "phy0tpt" + ;; ++gl-ar750) ++ ucidef_set_led_wlan "wlan2g" "WLAN2G" "$board:white:wlan2g" "phy1tpt" ++ ucidef_set_led_wlan "wlan5g" "WLAN5G" "$board:white:wlan5g" "phy0tpt" ++ ;; + gl-mifi) + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" + ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index ae82cfe008169a8282ac51746cf2299eec8c81d8..c8990c60f504286d0fd28c7b17f54c9c3b5a891e 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -369,6 +369,7 @@ ar71xx_setup_interfaces() + onion-omega) + ucidef_set_interface_lan "wlan0" + ;; ++ gl-ar750|\ + rb-435g) + ucidef_set_interfaces_lan_wan "eth1" "eth0" + ucidef_add_switch "switch0" \ +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 336d078f72a06073e3465c36ca98035c7d70282f..01d3b787bedcab82a5797c9a4801e8139887cc2c 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -249,6 +249,7 @@ get_status_led() { + nbg460n_550n_550nh) + status_led="nbg460n:green:power" + ;; ++ gl-ar750|\ + nbg6716) + status_led="$board:white:power" + ;; +@@ -489,7 +490,8 @@ set_state() { + done) + status_led_on + case $(ar71xx_board_name) in +- gl-ar300m) ++ gl-ar300m|\ ++ gl-ar750) + fw_printenv lc >/dev/null 2>&1 && fw_setenv "bootcount" 0 + ;; + qihoo-c301) +diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +index 65251284bba605afda8709c4799060e7a5554193..3b1e408f00846f8cc39e05d90600992e382b314a 100644 +--- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata ++++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata +@@ -109,6 +109,7 @@ case "$FIRMWARE" in + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth1/address) -2) + ;; ++ gl-ar750|\ + tl-wpa8630) + ath10kcal_extract "art" 20480 2116 + ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +1) +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 21b1c44404d383ef99860caf95a8e19b9cbf5087..35b742a5f1fee0bc24ab2d88e32f118c1df4e2b3 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -650,6 +650,9 @@ ar71xx_board_detect() { + *"GL-AR300M") + name="gl-ar300m" + ;; ++ *"GL-AR750") ++ name="gl-ar750" ++ ;; + *"GL-MIFI") + name="gl-mifi" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx b/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx +index d677599d8c6380d9920e95abc9fb4b92cc0cec29..ba6e08b00d979bc73f7199756e22ca3941fad97d 100644 +--- a/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx ++++ b/target/linux/ar71xx/base-files/lib/preinit/05_set_preinit_iface_ar71xx +@@ -17,6 +17,7 @@ set_preinit_iface() { + archer-c7 |\ + bhr-4grv2 |\ + dir-505-a1 |\ ++ gl-ar750|\ + gl-inet |\ + jwap003 |\ + pb42 |\ +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 03677ad1240c9a5af341354b95561f9d493a9cd8..236520b27c4d6d0b1b7e483d1100fb5ab156d475 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -253,6 +253,7 @@ platform_check_image() { + gl-ar150|\ + gl-ar300m|\ + gl-ar300|\ ++ gl-ar750|\ + gl-domino|\ + gl-mifi|\ + hiwifi-hc6361|\ +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index 9f449973b17a1d82098fb5b50f4b8f6cc9f869f8..d5ad6396a5c422b9b68b0a94658962226c13006e 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -110,6 +110,7 @@ CONFIG_ATH79_MACH_FRITZ4020=y + CONFIG_ATH79_MACH_GL_AR150=y + CONFIG_ATH79_MACH_GL_AR300=y + CONFIG_ATH79_MACH_GL_AR300M=y ++CONFIG_ATH79_MACH_GL_AR750=y + CONFIG_ATH79_MACH_GL_DOMINO=y + CONFIG_ATH79_MACH_GL_INET=y + CONFIG_ATH79_MACH_GL_MIFI=y +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 46366e0d922808e5e14fed0f2b5409cda11afd26..2449a8d6bce17f0a703d8fc4f82dd38e1f861ae3 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -691,6 +691,17 @@ config ATH79_MACH_GL_AR300M + select ATH79_DEV_USB + select ATH79_DEV_WMAC + ++config ATH79_MACH_GL_AR750 ++ bool "GL.iNet GL-AR750 support" ++ select SOC_QCA953X ++ select ATH79_DEV_AP9X_PCI if PCI ++ select ATH79_DEV_ETH ++ select ATH79_DEV_GPIO_BUTTONS ++ select ATH79_DEV_LEDS_GPIO ++ select ATH79_DEV_M25P80 ++ select ATH79_DEV_USB ++ select ATH79_DEV_WMAC ++ + config ATH79_MACH_GL_DOMINO + bool "DOMINO support" + select SOC_AR933X +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Makefile b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +index 29c9c65bc122c0d02839adf1abb61dcda0795fb6..98281db31a05713168713f3e0fd62f736a2e7614 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Makefile ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Makefile +@@ -115,6 +115,7 @@ obj-$(CONFIG_ATH79_MACH_FRITZ4020) += mach-fritz4020.o + obj-$(CONFIG_ATH79_MACH_GL_AR150) += mach-gl-ar150.o + obj-$(CONFIG_ATH79_MACH_GL_AR300) += mach-gl-ar300.o + obj-$(CONFIG_ATH79_MACH_GL_AR300M) += mach-gl-ar300m.o ++obj-$(CONFIG_ATH79_MACH_GL_AR750) += mach-gl-ar750.o + obj-$(CONFIG_ATH79_MACH_GL_DOMINO) += mach-gl-domino.o + obj-$(CONFIG_ATH79_MACH_GL_INET) += mach-gl-inet.o + obj-$(CONFIG_ATH79_MACH_GL_MIFI) += mach-gl-mifi.o +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c +new file mode 100644 +index 0000000000000000000000000000000000000000..9ee6e29c02139b972a83a555fcd693765bf8194f +--- /dev/null ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-gl-ar750.c +@@ -0,0 +1,146 @@ ++/* ++ * GL.iNet GL-AR750 board support ++ * ++ * Copyright (C) 2018 Piotr Dymacz ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "common.h" ++#include "dev-ap9x-pci.h" ++#include "dev-eth.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++#include "dev-wmac.h" ++#include "machtypes.h" ++ ++#define GL_AR750_GPIO_LED_POWER 12 ++#define GL_AR750_GPIO_LED_WLAN2G 14 ++#define GL_AR750_GPIO_LED_WLAN5G 13 ++ ++#define GL_AR750_GPIO_BTN_RESET 3 ++#define GL_AR750_GPIO_BTN_SW1 0 ++ ++#define GL_AR750_GPIO_I2C_SCL 16 ++#define GL_AR750_GPIO_I2C_SDA 17 ++ ++#define GL_AR750_GPIO_USB_POWER 2 ++ ++#define GL_AR750_KEYS_POLL_INTERVAL 20 ++#define GL_AR750_KEYS_DEBOUNCE_INTERVAL (3 * GL_AR750_KEYS_POLL_INTERVAL) ++ ++#define GL_AR750_MAC0_OFFSET 0 ++#define GL_AR750_WMAC2G_CALDATA_OFFSET 0x1000 ++#define GL_AR750_WMAC5G_CALDATA_OFFSET 0x5000 ++ ++static struct gpio_led gl_ar750_leds_gpio[] __initdata = { ++ { ++ .name = "gl-ar750:white:power", ++ .gpio = GL_AR750_GPIO_LED_POWER, ++ .default_state = LEDS_GPIO_DEFSTATE_KEEP, ++ .active_low = 1, ++ }, { ++ .name = "gl-ar750:white:wlan2g", ++ .gpio = GL_AR750_GPIO_LED_WLAN2G, ++ .active_low = 1, ++ }, { ++ .name = "gl-ar750:white:wlan5g", ++ .gpio = GL_AR750_GPIO_LED_WLAN5G, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_keys_button gl_ar750_gpio_keys[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = GL_AR750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .debounce_interval = GL_AR750_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = GL_AR750_GPIO_BTN_SW1, ++ .active_low = 1, ++ }, ++}; ++ ++static struct i2c_gpio_platform_data gl_ar750_i2c_gpio_data = { ++ .sda_pin = GL_AR750_GPIO_I2C_SDA, ++ .scl_pin = GL_AR750_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device gl_ar750_i2c_gpio = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &gl_ar750_i2c_gpio_data, ++ }, ++}; ++ ++static void __init gl_ar750_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1f050000); ++ ++ ath79_register_m25p80(NULL); ++ ++ ath79_setup_ar933x_phy4_switch(false, false); ++ ath79_register_mdio(0, 0x0); ++ ++ ath79_switch_data.phy4_mii_en = 1; ++ ath79_switch_data.phy_poll_mask = 0xfc; ++ ++ /* WAN */ ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_init_mac(ath79_eth0_data.mac_addr, art + GL_AR750_MAC0_OFFSET, 0); ++ ath79_register_eth(0); ++ ++ /* LAN */ ++ ath79_eth1_data.duplex = DUPLEX_FULL; ++ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_GMII; ++ ath79_init_mac(ath79_eth1_data.mac_addr, art + GL_AR750_MAC0_OFFSET, 1); ++ ath79_register_eth(1); ++ ++ /* Disable JTAG (enables GPIO0-3) */ ++ ath79_gpio_function_enable(AR934X_GPIO_FUNC_JTAG_DISABLE); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(gl_ar750_leds_gpio), ++ gl_ar750_leds_gpio); ++ ++ ath79_register_gpio_keys_polled(-1, GL_AR750_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(gl_ar750_gpio_keys), ++ gl_ar750_gpio_keys); ++ ++ gpio_request_one(GL_AR750_GPIO_USB_POWER, ++ GPIOF_OUT_INIT_HIGH | GPIOF_EXPORT_DIR_FIXED, ++ "USB power"); ++ ++ platform_device_register(&gl_ar750_i2c_gpio); ++ ++ ath79_register_usb(); ++ ++ ath79_register_wmac(art + GL_AR750_WMAC2G_CALDATA_OFFSET, NULL); ++ ++ ap91_pci_init(art + GL_AR750_WMAC5G_CALDATA_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(ATH79_MACH_GL_AR750, "GL-AR750", "GL.iNet GL-AR750", ++ gl_ar750_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 89ddbbc976c9393608a80b9ce56e02a4d403ea2a..11ccdbb5083807ef137b8cd2d110de7a97a34e38 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -106,6 +106,7 @@ enum ath79_mach_type { + ATH79_MACH_GL_AR150, /* GL-AR150 support */ + ATH79_MACH_GL_AR300, /* GL-AR300 */ + ATH79_MACH_GL_AR300M, /* GL-AR300M */ ++ ATH79_MACH_GL_AR750, /* GL.iNet GL-AR750 */ + ATH79_MACH_GL_DOMINO, /* Domino */ + ATH79_MACH_GL_INET, /* GL-CONNECT GL-INET */ + ATH79_MACH_GL_MIFI, /* GL-MIFI support */ +diff --git a/target/linux/ar71xx/image/generic.mk b/target/linux/ar71xx/image/generic.mk +index d113c5ad621bb2f15d4cbc4fd50e60904313a7da..d1375c8742d8aea6224f7aca3d9e9522d8056a94 100644 +--- a/target/linux/ar71xx/image/generic.mk ++++ b/target/linux/ar71xx/image/generic.mk +@@ -161,6 +161,19 @@ define Device/gl-ar300m + endef + TARGET_DEVICES += gl-ar300m + ++define Device/gl-ar750 ++ DEVICE_TITLE := GL.iNet GL-AR750 ++ DEVICE_PACKAGES := kmod-ath10k ath10k-firmware-qca9887 kmod-usb-core \ ++ kmod-usb2 kmod-usb-storage ++ BOARDNAME := GL-AR750 ++ SUPPORTED_DEVICES := gl-ar750 ++ IMAGE_SIZE := 16000k ++ MTDPARTS := spi0.0:256k(u-boot)ro,64k(u-boot-env),64k(art)ro,-(firmware) ++ IMAGE/sysupgrade.bin := append-kernel | pad-to $$$$(BLOCKSIZE) | \ ++ append-rootfs | pad-rootfs | append-metadata | check-size $$$$(IMAGE_SIZE) ++endef ++TARGET_DEVICES += gl-ar750 ++ + define Device/gl-domino + DEVICE_TITLE := GL Domino Pi + DEVICE_PACKAGES := kmod-usb-core kmod-usb2 diff --git a/patches/lede/0088-uboot-envtools-add-support-for-GL.iNet-GL-AR750.patch b/patches/lede/0088-uboot-envtools-add-support-for-GL.iNet-GL-AR750.patch new file mode 100644 index 00000000..4a85a27f --- /dev/null +++ b/patches/lede/0088-uboot-envtools-add-support-for-GL.iNet-GL-AR750.patch @@ -0,0 +1,18 @@ +From: Piotr Dymacz +Date: Tue, 17 Oct 2017 23:32:11 +0200 +Subject: uboot-envtools: add support for GL.iNet GL-AR750 + +Signed-off-by: Piotr Dymacz + +diff --git a/package/boot/uboot-envtools/files/ar71xx b/package/boot/uboot-envtools/files/ar71xx +index 25bec7eb33fd691bae417512c4c03e133d93213d..26f1ff938b8191e84315cf308f78e0907264c671 100644 +--- a/package/boot/uboot-envtools/files/ar71xx ++++ b/package/boot/uboot-envtools/files/ar71xx +@@ -29,6 +29,7 @@ cr3000|\ + cr5000|\ + eap300v2|\ + gl-ar300m|\ ++gl-ar750|\ + hornet-ub|\ + hornet-ub-x2|\ + jwap230|\ diff --git a/patches/lede/0089-ar71xx-add-model-detection-for-UBNT-AC-Mesh.patch b/patches/lede/0089-ar71xx-add-model-detection-for-UBNT-AC-Mesh.patch new file mode 100644 index 00000000..dede27e3 --- /dev/null +++ b/patches/lede/0089-ar71xx-add-model-detection-for-UBNT-AC-Mesh.patch @@ -0,0 +1,54 @@ +From: David Bauer +Date: Sun, 25 Feb 2018 12:09:38 +0100 +Subject: ar71xx: add model detection for UBNT AC-Mesh + +This commit adds correct model detection for UniFi +AC-Mesh. Previously said device was incorrectly detected +as UniFi AC-Lite. + +The Information about the device is stored at 0xC in the EEPROM +partition. It corresponds to the sysid in /etc/board.info of the +Ubiquiti stock firmware. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 35b742a5f1fee0bc24ab2d88e32f118c1df4e2b3..59c1899a588007d6a6a1860fcf95064b0ec35561 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -98,6 +98,27 @@ ubnt_xm_board_detect() { + [ -z "$model" ] || AR71XX_MODEL="${model}${magic:3:1}" + } + ++ubnt_ac_lite_get_mtd_part_magic() { ++ ar71xx_get_mtd_offset_size_format EEPROM 12 2 %02x ++} ++ ++ubnt_ac_lite_board_detect() { ++ local model ++ local magic ++ ++ magic="$(ubnt_ac_lite_get_mtd_part_magic)" ++ case ${magic:0:4} in ++ "e517") ++ model="Ubiquiti UniFi-AC-LITE" ++ ;; ++ "e557") ++ model="Ubiquiti UniFi-AC-MESH" ++ ;; ++ esac ++ ++ [ -z "$model" ] || AR71XX_MODEL="${model}" ++} ++ + cybertan_get_hw_magic() { + local part + +@@ -1129,6 +1150,7 @@ ar71xx_board_detect() { + ;; + *"UniFi-AC-LITE") + name="unifiac-lite" ++ ubnt_ac_lite_board_detect + ;; + *"UniFi-AC-PRO") + name="unifiac-pro" diff --git a/patches/lede/0090-ar71xx-generic-enable-CONFIG_MTD_SPLIT_TPLINK_FW.patch b/patches/lede/0090-ar71xx-generic-enable-CONFIG_MTD_SPLIT_TPLINK_FW.patch new file mode 100644 index 00000000..7df0cbaa --- /dev/null +++ b/patches/lede/0090-ar71xx-generic-enable-CONFIG_MTD_SPLIT_TPLINK_FW.patch @@ -0,0 +1,46 @@ +From: Piotr Dymacz +Date: Mon, 3 Jul 2017 18:57:36 +0200 +Subject: ar71xx: generic: enable CONFIG_MTD_SPLIT_TPLINK_FW + +We can use "tplink-fw" mtd splitter for TP-Link devices which use kernel +with TP-Link header embedded inside "safeloader" image type and thus get +rid of statically defined "kernel" and "rootfs" partitions in cmdline. + +Signed-off-by: Piotr Dymacz + +diff --git a/target/linux/ar71xx/config-4.4 b/target/linux/ar71xx/config-4.4 +index d5ad6396a5c422b9b68b0a94658962226c13006e..26f855e66796106cd0f232c9c5e920b02365de31 100644 +--- a/target/linux/ar71xx/config-4.4 ++++ b/target/linux/ar71xx/config-4.4 +@@ -380,6 +380,7 @@ CONFIG_MTD_SPLIT_EVA_FW=y + CONFIG_MTD_SPLIT_FIRMWARE=y + CONFIG_MTD_SPLIT_LZMA_FW=y + CONFIG_MTD_SPLIT_SEAMA_FW=y ++CONFIG_MTD_SPLIT_TPLINK_FW=y + CONFIG_MTD_SPLIT_UIMAGE_FW=y + CONFIG_MTD_SPLIT_WRGG_FW=y + CONFIG_MTD_TPLINK_PARTS=y +diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default +index e0401102229c00985e8000331dce43375903e1aa..f5d48ae0f674883371f8d549594f695913c3d216 100644 +--- a/target/linux/ar71xx/mikrotik/config-default ++++ b/target/linux/ar71xx/mikrotik/config-default +@@ -219,6 +219,7 @@ CONFIG_MTD_NAND_RB4XX=y + CONFIG_MTD_NAND_RB750=y + CONFIG_MTD_NAND_RB91X=y + # CONFIG_MTD_SPLIT_EVA_FW is not set ++# CONFIG_MTD_SPLIT_TPLINK_FW is not set + # CONFIG_MTD_REDBOOT_PARTS is not set + # CONFIG_MTD_TPLINK_PARTS is not set + CONFIG_MTD_UBI=y +diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default +index 790fa8f9bd42aba8521b960c2a49a742285e6157..0eee52d3ee69990fadf77de9f03f03c9c9b59190 100644 +--- a/target/linux/ar71xx/nand/config-default ++++ b/target/linux/ar71xx/nand/config-default +@@ -107,6 +107,7 @@ CONFIG_MTD_NAND_ECC_BCH=y + # CONFIG_MTD_SM_COMMON is not set + # CONFIG_MTD_SPLIT_EVA_FW is not set + # CONFIG_MTD_SPLIT_SEAMA_FW is not set ++# CONFIG_MTD_SPLIT_TPLINK_FW is not set + # CONFIG_MTD_TPLINK_PARTS is not set + CONFIG_MTD_UBI=y + CONFIG_MTD_UBI_BEB_LIMIT=20 diff --git a/patches/lede/0091-mac80211-initialize-sinfo-in-cfg80211_get_station.patch b/patches/lede/0091-mac80211-initialize-sinfo-in-cfg80211_get_station.patch new file mode 100644 index 00000000..78259ec0 --- /dev/null +++ b/patches/lede/0091-mac80211-initialize-sinfo-in-cfg80211_get_station.patch @@ -0,0 +1,71 @@ +From: Sven Eckelmann +Date: Wed, 6 Jun 2018 11:21:53 +0200 +Subject: mac80211: initialize sinfo in cfg80211_get_station + +Most of the implementations behind cfg80211_get_station will not initialize +sinfo to zero before manipulating it. For example, the member "filled", +which indicates the filled in parts of this struct, is often only modified +by enabling certain bits in the bitfield while keeping the remaining bits +in their original state. A caller without a preinitialized sinfo.filled can +then no longer decide which parts of sinfo were filled in by +cfg80211_get_station (or actually the underlying implementations). + +cfg80211_get_station must therefore take care that sinfo is initialized to +zero. Otherwise, the caller may tries to read information which was not +filled in and which must therefore also be considered uninitialized. In +batadv_v_elp_get_throughput's case, an invalid "random" expected throughput +may be stored for this neighbor and thus the B.A.T.M.A.N V algorithm may +switch to non-optimal neighbors for certain destinations. + +Signed-off-by: Sven Eckelmann + +Forwarded: https://github.com/openwrt/openwrt/pull/1015 + +diff --git a/package/kernel/mac80211/patches/379-cfg80211-initialize-sinfo-in-cfg80211_get_station.patch b/package/kernel/mac80211/patches/379-cfg80211-initialize-sinfo-in-cfg80211_get_station.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..37323c1f7defee830b3f876a46f255acf21fce42 +--- /dev/null ++++ b/package/kernel/mac80211/patches/379-cfg80211-initialize-sinfo-in-cfg80211_get_station.patch +@@ -0,0 +1,42 @@ ++From 4f717a2589be649afddbbd3ac58b67ebfa7426f7 Mon Sep 17 00:00:00 2001 ++From: Sven Eckelmann ++Date: Wed, 6 Jun 2018 10:18:31 +0200 ++Subject: [PATCH v2] cfg80211: initialize sinfo in cfg80211_get_station ++ ++Most of the implementations behind cfg80211_get_station will not initialize ++sinfo to zero before manipulating it. For example, the member "filled", ++which indicates the filled in parts of this struct, is often only modified ++by enabling certain bits in the bitfield while keeping the remaining bits ++in their original state. A caller without a preinitialized sinfo.filled can ++then no longer decide which parts of sinfo were filled in by ++cfg80211_get_station (or actually the underlying implementations). ++ ++cfg80211_get_station must therefore take care that sinfo is initialized to ++zero. Otherwise, the caller may tries to read information which was not ++filled in and which must therefore also be considered uninitialized. In ++batadv_v_elp_get_throughput's case, an invalid "random" expected throughput ++may be stored for this neighbor and thus the B.A.T.M.A.N V algorithm may ++switch to non-optimal neighbors for certain destinations. ++ ++Fixes: 7406353d43c8 ("cfg80211: implement cfg80211_get_station cfg80211 API") ++Reported-by: Thomas Lauer ++Reported-by: Marcel Schmidt ++Cc: b.a.t.m.a.n@lists.open-mesh.org ++Signed-off-by: Sven Eckelmann ++ ++Forwarded: https://patchwork.kernel.org/patch/10449857/ ++--- ++ net/wireless/util.c | 2 ++ ++ 1 file changed, 2 insertions(+) ++ ++--- a/net/wireless/util.c +++++ b/net/wireless/util.c ++@@ -1749,6 +1749,8 @@ int cfg80211_get_station(struct net_devi ++ if (!rdev->ops->get_station) ++ return -EOPNOTSUPP; ++ +++ memset(sinfo, 0, sizeof(*sinfo)); +++ ++ return rdev_get_station(rdev, dev, mac_addr, sinfo); ++ } ++ EXPORT_SYMBOL(cfg80211_get_station); diff --git a/patches/lede/0092-ar71xx-lzma-loader-move-padding-workaround-to-gzip-step.patch b/patches/lede/0092-ar71xx-lzma-loader-move-padding-workaround-to-gzip-step.patch new file mode 100644 index 00000000..870f7427 --- /dev/null +++ b/patches/lede/0092-ar71xx-lzma-loader-move-padding-workaround-to-gzip-step.patch @@ -0,0 +1,54 @@ +From: Matthias Schiffer +Date: Wed, 6 Jun 2018 20:51:05 +0200 +Subject: ar71xx: lzma-loader: move padding workaround to gzip step + +Some devices (TP-Link TL-WR1043ND v1) don't boot reliably when the +uncompressed loader is too small. This was workarounded in the loader by +adding 512KB of padding to the .data section of the loader binary. + +This approach had two issues: + +- The padding was only working when .data was non-empty (otherwise the + section would become NOBITS, omitting it in the binary). .data was only + empty when no CMDLINE was set, leading to further workarounds like + fe594bf90d09 ("ath79: fix loader-okli, lzma-loader"), and this + workaround was only effective because a missing "const" led to the kernel + argv being stored in .data instead of .rodata +- The padding was not only added to the compressed .gz loader, but also + uncompressed .bin and .elf loaders. The prevented embedding the kernel + cmdline in the loader for non-gz loader types. + +To fix both issues, move the creation of the padding from the linker script +to the gzip step. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/lzma-loader/Makefile b/target/linux/ar71xx/image/lzma-loader/Makefile +index 9b81e87306f235d1e7284401828240b9b9787011..738093a958013624abb8f84a3874e1c795da349d 100644 +--- a/target/linux/ar71xx/image/lzma-loader/Makefile ++++ b/target/linux/ar71xx/image/lzma-loader/Makefile +@@ -47,7 +47,11 @@ loader-compile: $(PKG_BUILD_DIR)/.prepared + clean all + + loader.gz: $(PKG_BUILD_DIR)/loader.bin +- gzip -nc9 $< > $(LOADER_GZ) ++ # Workaround for buggy bootloaders: Some devices ++ # (TP-Link TL-WR1043ND v1) don't work correctly when ++ # the uncompressed loader is too small (probably a cache ++ # invalidation issue) ++ dd if=$< bs=512K conv=sync | gzip -nc9 > $(LOADER_GZ) + + loader.elf: $(PKG_BUILD_DIR)/loader.elf + $(CP) $< $(LOADER_ELF) +diff --git a/target/linux/ar71xx/image/lzma-loader/src/loader.lds b/target/linux/ar71xx/image/lzma-loader/src/loader.lds +index 80cc7ca3ecf53a747fc139560b89c233f4343293..01ff85236147dc62bae480b191a44005171b1561 100644 +--- a/target/linux/ar71xx/image/lzma-loader/src/loader.lds ++++ b/target/linux/ar71xx/image/lzma-loader/src/loader.lds +@@ -13,7 +13,6 @@ SECTIONS { + .data : { + *(.data) + *(.data.*) +- . = . + 524288; /* workaround for buggy bootloaders */ + } + + . = ALIGN(32); diff --git a/patches/lede/0093-ar71xx-lzma-loader-set-page-size-to-4KB.patch b/patches/lede/0093-ar71xx-lzma-loader-set-page-size-to-4KB.patch new file mode 100644 index 00000000..f9fdae6a --- /dev/null +++ b/patches/lede/0093-ar71xx-lzma-loader-set-page-size-to-4KB.patch @@ -0,0 +1,23 @@ +From: Matthias Schiffer +Date: Wed, 6 Jun 2018 00:27:42 +0200 +Subject: ar71xx: lzma-loader: set page size to 4KB + +The text section in the ELF loader is aligned to the maximum page size, +which defaults to 64KB. Reduce it to the actual page size to avoid wasting +flash space for this alignment. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/lzma-loader/src/Makefile b/target/linux/ar71xx/image/lzma-loader/src/Makefile +index 5f10bdb8f1499f24f00a8bf4d53f370fef88bd1e..fadb7e6206070c07aab3e8b323324976c6998eea 100644 +--- a/target/linux/ar71xx/image/lzma-loader/src/Makefile ++++ b/target/linux/ar71xx/image/lzma-loader/src/Makefile +@@ -95,7 +95,7 @@ loader2.o: loader.bin + $(LD) -r -b binary --oformat $(O_FORMAT) -o $@ $< + + loader.elf: loader2.o +- $(LD) -e startup -T loader2.lds -Ttext $(LOADADDR) -o $@ $< ++ $(LD) -z max-page-size=0x1000 -e startup -T loader2.lds -Ttext $(LOADADDR) -o $@ $< + + mrproper: clean + diff --git a/patches/lede/0094-ar71xx-lzma-loader-constify-kernel-argv-array.patch b/patches/lede/0094-ar71xx-lzma-loader-constify-kernel-argv-array.patch new file mode 100644 index 00000000..6dfe3ca2 --- /dev/null +++ b/patches/lede/0094-ar71xx-lzma-loader-constify-kernel-argv-array.patch @@ -0,0 +1,22 @@ +From: Matthias Schiffer +Date: Wed, 6 Jun 2018 00:30:57 +0200 +Subject: ar71xx: lzma-loader: constify kernel argv array + +By making the kernel argv array const, the .data section can always be +omitted from the laoder binary. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/lzma-loader/src/loader.c b/target/linux/ar71xx/image/lzma-loader/src/loader.c +index cc73eb1721cbfbf2ad1bb94e8e6d3ab006983c5d..794c4b6285a7fa0423c22d172828415e6f2be93b 100644 +--- a/target/linux/ar71xx/image/lzma-loader/src/loader.c ++++ b/target/linux/ar71xx/image/lzma-loader/src/loader.c +@@ -75,7 +75,7 @@ static unsigned long kernel_la; + #ifdef CONFIG_KERNEL_CMDLINE + #define kernel_argc 2 + static const char kernel_cmdline[] = CONFIG_KERNEL_CMDLINE; +-static const char *kernel_argv[] = { ++static const char *const kernel_argv[] = { + NULL, + kernel_cmdline, + NULL, diff --git a/patches/lede/0095-ar71xx-make-loader-okli-build-step-more-generic.patch b/patches/lede/0095-ar71xx-make-loader-okli-build-step-more-generic.patch new file mode 100644 index 00000000..737d21bc --- /dev/null +++ b/patches/lede/0095-ar71xx-make-loader-okli-build-step-more-generic.patch @@ -0,0 +1,36 @@ +From: Matthias Schiffer +Date: Wed, 6 Jun 2018 00:34:25 +0200 +Subject: ar71xx: make loader-okli build step more generic + +Add support for different loader types. + +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile +index 8eac5fc997cab0203718fb0558e6f5aaaeec9c38..de27f5d7c5ce6dbd31305c139afc128edaed15ee 100644 +--- a/target/linux/ar71xx/image/Makefile ++++ b/target/linux/ar71xx/image/Makefile +@@ -73,8 +73,9 @@ define Build/loader-kernel-cmdline + $(call Build/loader-common,LOADER_DATA="$@" KERNEL_CMDLINE="$(CMDLINE)") + endef + ++# Arguments: + define Build/loader-okli +- dd if=$(KDIR)/loader-$(1).gz bs=7680 conv=sync of="$@.new" ++ dd if=$(KDIR)/loader-$(word 1,$(1)).$(LOADER_TYPE) bs=$(word 2,$(1)) conv=sync of="$@.new" + cat "$@" >> "$@.new" + mv "$@.new" "$@" + endef +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 1e40d943ac2aa43aea670fd86268708aea39a46c..18e2c73737f477f4d00020893878cbdfb81a735b 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -69,7 +69,7 @@ $(Device/tplink) + LOADER_FLASH_OFFS := 0x22000 + COMPILE := loader-$(1).gz + COMPILE/loader-$(1).gz := loader-okli-compile +- KERNEL := copy-file $(KDIR)/vmlinux.bin.lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) ++ KERNEL := copy-file $(KDIR)/vmlinux.bin.lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 7680 + KERNEL_INITRAMFS := copy-file $(KDIR)/vmlinux-initramfs.bin.lzma | loader-kernel-cmdline | mktplinkfw-combined + endef + diff --git a/patches/lede/0096-ar71xx-switch-CPE-WBS-210-510-to-okli-loader.patch b/patches/lede/0096-ar71xx-switch-CPE-WBS-210-510-to-okli-loader.patch new file mode 100644 index 00000000..f77a2cfa --- /dev/null +++ b/patches/lede/0096-ar71xx-switch-CPE-WBS-210-510-to-okli-loader.patch @@ -0,0 +1,39 @@ +From: Matthias Schiffer +Date: Wed, 6 Jun 2018 00:35:17 +0200 +Subject: ar71xx: switch CPE/WBS 210/510 to okli-loader + +We recently increased the kernel partition size of the CPE/WBS 210/510. +This works fine for new installations of the factory image, but on +sysupgrades, the partition table read by the bootloader is not adjusted. +This limits the maximum size of the kernel loaded by the bootloader to the +old partition size. + +While adjusting the partition table would be a cleanest solution, such a +migration would have to happen before an upgrade to a new version with a +newer kernel. This is error-prone and would require a two-step upgrade, as +we mark the partition table partition read-only. + +Instead, switch from the lzma-loader with embedded kernel to the +okli-loader, so only the tiny lzma-loader is loaded by the bootloader as +"kernel", and the lzma-loader will then load the rest of the kernel by +itself. + +Fixes: e39847ea2f70 ("ar71xx: increase kernel partition size for CPE/WBS 210/510") +Signed-off-by: Matthias Schiffer + +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 18e2c73737f477f4d00020893878cbdfb81a735b..709b1558a5f8487c50e922ec4d27b643f080cbcc 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -173,7 +173,10 @@ define Device/cpe510-520 + TPLINK_BOARD_NAME := CPE510 + DEVICE_PROFILE := CPE510 + LOADER_TYPE := elf +- KERNEL := kernel-bin | patch-cmdline | lzma | loader-kernel ++ LOADER_FLASH_OFFS := 0x43000 ++ COMPILE := loader-$(1).elf ++ COMPILE/loader-$(1).elf := loader-okli-compile ++ KERNEL := kernel-bin | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 + IMAGES := sysupgrade.bin factory.bin + IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade + IMAGE/factory.bin := append-rootfs | tplink-safeloader factory diff --git a/patches/lede/0097-ar71xx-add-support-for-TP-Link-TL-WA901ND-v5.patch b/patches/lede/0097-ar71xx-add-support-for-TP-Link-TL-WA901ND-v5.patch new file mode 100644 index 00000000..e83bd189 --- /dev/null +++ b/patches/lede/0097-ar71xx-add-support-for-TP-Link-TL-WA901ND-v5.patch @@ -0,0 +1,123 @@ +From: Paul Wassi +Date: Sun, 22 Oct 2017 22:39:30 +0200 +Subject: ar71xx: add support for TP-Link TL-WA901ND v5 + +The TL-WA901ND v5 has the same hardware as v4, although the PCB has +a different layout. Installation from factory is done via TFTP. +(rename -factory image to wa901ndv4_tp_recovery.bin for tftp) + +Signed-off-by: Paul Wassi + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index f94cc3c85b798458cc97c06bb0d44bdc426d057d..a742854bc9b0aa48c61b37e58288177bbb56d14d 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -606,7 +606,8 @@ tl-wa860re|\ + tl-wa830re-v2|\ + tl-wa801nd-v2|\ + tl-wa901nd-v3|\ +-tl-wa901nd-v4) ++tl-wa901nd-v4|\ ++tl-wa901nd-v5) + ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "tp-link:green:wlan" "phy0tpt" + ;; +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index c8990c60f504286d0fd28c7b17f54c9c3b5a891e..875a1a38ada9fb66503505d2f094310db1295a07 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -110,6 +110,7 @@ ar71xx_setup_interfaces() + tl-wa901nd-v2|\ + tl-wa901nd-v3|\ + tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ + tl-wr703n|\ + tl-wr802n-v1|\ + tube2h|\ +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index 01d3b787bedcab82a5797c9a4801e8139887cc2c..f8d2eb314f7b57a1134b68c504c0dac202ed947c 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -363,6 +363,7 @@ get_status_led() { + tl-wa901nd-v2|\ + tl-wa901nd-v3|\ + tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ + tl-wdr3320-v2|\ + tl-wdr3500|\ + tl-wr1041n-v2|\ +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index 59c1899a588007d6a6a1860fcf95064b0ec35561..b365b6ae4aa6021960499b3889d846b5171eec0f 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -1058,6 +1058,9 @@ ar71xx_board_detect() { + *"TL-WA901ND v4") + name="tl-wa901nd-v4" + ;; ++ *"TL-WA901ND v5") ++ name="tl-wa901nd-v5" ++ ;; + *"TL-WDR3320 v2") + name="tl-wdr3320-v2" + ;; +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 236520b27c4d6d0b1b7e483d1100fb5ab156d475..0b422d71c2639a31bc7e88a20976266b66ec4490 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -415,6 +415,7 @@ platform_check_image() { + tl-wa901nd-v2|\ + tl-wa901nd-v3|\ + tl-wa901nd-v4|\ ++ tl-wa901nd-v5|\ + tl-wa901nd|\ + tl-wdr3320-v2|\ + tl-wdr3500|\ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c +index 9c651bb1d256bc13a3fe31b664f2cd3590e8092f..ffbcd6fe42df9b7c0dd86ae23a21ab7c90917a8c 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-tl-wa901nd-v4.c +@@ -1,5 +1,5 @@ + /* +- * TP-LINK TL-WA901ND v4 board ++ * TP-LINK TL-WA901ND v4, v5 board + * + * Copyright (C) 2015 Matthias Schiffer + * Copyright (C) 2016 Tiziano Bacocco +@@ -110,3 +110,6 @@ static void __init TL_WA901ND_V4_setup(void) + + MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V4, "TL-WA901ND-v4", "TP-LINK TL-WA901ND v4", + TL_WA901ND_V4_setup); ++ ++MIPS_MACHINE(ATH79_MACH_TL_WA901ND_V5, "TL-WA901ND-v5", "TP-LINK TL-WA901ND v5", ++ TL_WA901ND_V4_setup); +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index 11ccdbb5083807ef137b8cd2d110de7a97a34e38..a4c7f52fe94e17bc48bebfb460f12f3e5ac35afe 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -213,6 +213,7 @@ enum ath79_mach_type { + ATH79_MACH_TL_WA901ND_V2, /* TP-LINK TL-WA901ND v2 */ + ATH79_MACH_TL_WA901ND_V3, /* TP-LINK TL-WA901ND v3 */ + ATH79_MACH_TL_WA901ND_V4, /* TP-LINK TL-WA901ND v4 */ ++ ATH79_MACH_TL_WA901ND_V5, /* TP-LINK TL-WA901ND v5 */ + ATH79_MACH_TL_WDR3320_V2, /* TP-LINK TL-WDR3320 v2 */ + ATH79_MACH_TL_WDR3500, /* TP-LINK TL-WDR3500 */ + ATH79_MACH_TL_WDR4300, /* TP-LINK TL-WDR4300 */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 709b1558a5f8487c50e922ec4d27b643f080cbcc..6a3faef518ebfa4f36d3074ee9c102b801e04275 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -1103,7 +1103,13 @@ define Device/tl-wa901nd-v4 + IMAGE/factory.bin := append-rootfs | mktplinkfw factory -C EU + endef + +-TARGET_DEVICES += tl-wa901nd-v1 tl-wa901nd-v2 tl-wa901nd-v3 tl-wa901nd-v4 ++define Device/tl-wa901nd-v5 ++ $(Device/tl-wa901nd-v4) ++ DEVICE_TITLE := TP-LINK TL-WA901N/ND v5 ++ BOARDNAME := TL-WA901ND-v5 ++ TPLINK_HWID := 0x09010005 ++endef ++TARGET_DEVICES += tl-wa901nd-v1 tl-wa901nd-v2 tl-wa901nd-v3 tl-wa901nd-v4 tl-wa901nd-v5 + + define Device/tl-wa7210n-v2 + $(Device/tplink-4mlzma) diff --git a/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch b/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch new file mode 100644 index 00000000..e82d7bcd --- /dev/null +++ b/patches/lede/0098-ar71xx-disable-40Mhz-refclk-for-QCA953x.patch @@ -0,0 +1,182 @@ +From: Sven Eckelmann +Date: Fri, 19 Jan 2018 14:02:09 +0100 +Subject: ar71xx: disable 40Mhz refclk for QCA953x + +The "QCA9531 v2.0 802.11n 2x2 2.4 GHz Premium SOC for WLAN Platforms" +datasheet (80-Y7991-1 Rev. C - October 2014) doesn't specify support for a +40 Mhz reference clock. The register description for "Bootstrap Options" +(page 31) defines following states for the bit 4 (REF_CLK): + +* 0 - CLK25 (default) +* 1 - (reserved) + +Devices like the TP-Link CPE210 v2 has this bit set to 1 but is using a 25 +Mhz reference clock. OpenWrt is still interpreted this bit as 40 Mhz and +then break the bootup of the system due to this incorrect interpretation. + +Signed-off-by: Sven Eckelmann +[refreshed patches] +Signed-off-by: Piotr Dymacz + +Origin: backport, https://github.com/openwrt/openwrt/commit/b1d57dadb2da0e010e157fd2383523578c9dcc2e + +diff --git a/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch b/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch +index 777f7b2c8838f2c93f79d5d5212f90b2bd82ced3..d55c97165a5abad8cb25fcc6ddc29415f238c7e6 100644 +--- a/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch ++++ b/target/linux/ar71xx/patches-4.4/620-MIPS-ath79-add-support-for-QCA953x-SoC.patch +@@ -44,7 +44,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + config ATH79_NVRAM + --- a/arch/mips/ath79/clock.c + +++ b/arch/mips/ath79/clock.c +-@@ -354,6 +354,91 @@ static void __init ar934x_clocks_init(vo ++@@ -354,6 +354,87 @@ static void __init ar934x_clocks_init(vo + iounmap(dpll_base); + } + +@@ -56,13 +56,9 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + + unsigned long ahb_rate; + + u32 pll, out_div, ref_div, nint, frac, clk_ctrl, postdiv; + + u32 cpu_pll, ddr_pll; +-+ u32 bootstrap; + + +-+ bootstrap = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); +-+ if (bootstrap & QCA953X_BOOTSTRAP_REF_CLK_40) +-+ ref_rate = 40 * 1000 * 1000; +-+ else +-+ ref_rate = 25 * 1000 * 1000; +++ /* QCA953X only supports 25MHz ref_clk */ +++ ref_rate = 25 * 1000 * 1000; + + + + pll = ath79_pll_rr(QCA953X_PLL_CPU_CONFIG_REG); + + out_div = (pll >> QCA953X_PLL_CPU_CONFIG_OUTDIV_SHIFT) & +@@ -136,7 +132,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + static void __init qca955x_clocks_init(void) + { + unsigned long ref_rate; +-@@ -451,6 +536,8 @@ void __init ath79_clocks_init(void) ++@@ -451,6 +532,8 @@ void __init ath79_clocks_init(void) + ar933x_clocks_init(); + else if (soc_is_ar934x()) + ar934x_clocks_init(); +@@ -247,14 +243,12 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + + ath79_wmac_data.external_reset = ar933x_wmac_reset; + } +-@@ -151,6 +151,26 @@ static void ar934x_wmac_setup(void) ++@@ -151,6 +151,21 @@ static void ar934x_wmac_setup(void) + ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; + } + + +static void qca953x_wmac_setup(void) + +{ +-+ u32 t; +-+ + + ath79_wmac_device.name = "qca953x_wmac"; + + + + ath79_wmac_resources[0].start = QCA953X_WMAC_BASE; +@@ -262,11 +256,8 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + + ath79_wmac_resources[1].start = ATH79_IP2_IRQ(1); + + ath79_wmac_resources[1].end = ATH79_IP2_IRQ(1); + + +-+ t = ath79_reset_rr(QCA953X_RESET_REG_BOOTSTRAP); +-+ if (t & QCA953X_BOOTSTRAP_REF_CLK_40) +-+ ath79_wmac_data.is_clk_25mhz = false; +-+ else +-+ ath79_wmac_data.is_clk_25mhz = true; +++ /* QCA953X only supports 25MHz ref_clk */ +++ ath79_wmac_data.is_clk_25mhz = true; + + + + ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; + +} +@@ -274,7 +265,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + static void qca955x_wmac_setup(void) + { + u32 t; +-@@ -368,6 +388,8 @@ void __init ath79_register_wmac(u8 *cal_ ++@@ -368,6 +383,8 @@ void __init ath79_register_wmac(u8 *cal_ + ar933x_wmac_setup(); + else if (soc_is_ar934x()) + ar934x_wmac_setup(); +@@ -550,7 +541,7 @@ meaning of the bits CPUCLK_FROM_CPUPLL and DDRCLK_FROM_DDRPLL is reversed. + +#define QCA953X_BOOTSTRAP_SW_OPTION2 BIT(12) + +#define QCA953X_BOOTSTRAP_SW_OPTION1 BIT(11) + +#define QCA953X_BOOTSTRAP_EJTAG_MODE BIT(5) +-+#define QCA953X_BOOTSTRAP_REF_CLK_40 BIT(4) +++#define QCA953X_BOOTSTRAP_REF_CLK BIT(4) + +#define QCA953X_BOOTSTRAP_SDRAM_DISABLED BIT(1) + +#define QCA953X_BOOTSTRAP_DDR1 BIT(0) + + +diff --git a/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch +index ed90c40d882fcff1a451533748912865cc78c6e8..de0ee4604cdeb946bab222cacaa51fb150b25aab 100644 +--- a/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch ++++ b/target/linux/ar71xx/patches-4.4/621-MIPS-ath79-add-support-for-QCA956x-SoC.patch +@@ -24,7 +24,7 @@ + config ATH79_NVRAM + --- a/arch/mips/ath79/clock.c + +++ b/arch/mips/ath79/clock.c +-@@ -524,6 +524,100 @@ static void __init qca955x_clocks_init(v ++@@ -520,6 +520,100 @@ static void __init qca955x_clocks_init(v + clk_add_alias("uart", NULL, "ref", NULL); + } + +@@ -125,7 +125,7 @@ + void __init ath79_clocks_init(void) + { + if (soc_is_ar71xx()) +-@@ -540,6 +634,8 @@ void __init ath79_clocks_init(void) ++@@ -536,6 +630,8 @@ void __init ath79_clocks_init(void) + qca953x_clocks_init(); + else if (soc_is_qca955x()) + qca955x_clocks_init(); +@@ -219,7 +219,7 @@ + } + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -189,6 +189,26 @@ static void qca955x_wmac_setup(void) ++@@ -184,6 +184,26 @@ static void qca955x_wmac_setup(void) + ath79_wmac_data.is_clk_25mhz = true; + } + +@@ -246,7 +246,7 @@ + static bool __init + ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data) + { +-@@ -392,6 +412,8 @@ void __init ath79_register_wmac(u8 *cal_ ++@@ -387,6 +407,8 @@ void __init ath79_register_wmac(u8 *cal_ + qca953x_wmac_setup(); + else if (soc_is_qca955x()) + qca955x_wmac_setup(); +diff --git a/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch b/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch +index 16a0b909c570b403473346b0c992f9de02b67132..b0e15379787ade16a02363c78c143e878f27a7f2 100644 +--- a/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch ++++ b/target/linux/ar71xx/patches-4.4/631-MIPS-ath79-wmac-enable-set-led-pin.patch +@@ -1,6 +1,6 @@ + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -400,6 +400,11 @@ void __init ath79_wmac_set_ext_lna_gpio( ++@@ -395,6 +395,11 @@ void __init ath79_wmac_set_ext_lna_gpio( + ar934x_set_ext_lna_gpio(chain, gpio); + } + +diff --git a/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch b/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +index 8aa5957a7152af27854f6f7c197120b8029cf9e8..b59e43c7712a18e5e81944361c358dfb08c488ea 100644 +--- a/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch ++++ b/target/linux/ar71xx/patches-4.4/640-MIPS-ath79-add-QCA955x-wmac-reset.patch +@@ -32,7 +32,7 @@ + */ + --- a/arch/mips/ath79/dev-wmac.c + +++ b/arch/mips/ath79/dev-wmac.c +-@@ -171,6 +171,27 @@ static void qca953x_wmac_setup(void) ++@@ -166,6 +166,27 @@ static void qca953x_wmac_setup(void) + ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; + } + +@@ -60,7 +60,7 @@ + static void qca955x_wmac_setup(void) + { + u32 t; +-@@ -187,6 +208,8 @@ static void qca955x_wmac_setup(void) ++@@ -182,6 +203,8 @@ static void qca955x_wmac_setup(void) + ath79_wmac_data.is_clk_25mhz = false; + else + ath79_wmac_data.is_clk_25mhz = true; diff --git a/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch b/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch new file mode 100644 index 00000000..8b418e06 --- /dev/null +++ b/patches/lede/0099-ar71xx-Add-TP-Link-Pharos-v2-board-detection.patch @@ -0,0 +1,139 @@ +From: Adrian Schmutzler +Date: Fri, 19 Jan 2018 12:58:40 +0100 +Subject: ar71xx: Add TP-Link Pharos v2 board detection + +Add support for detecting TP-Link Pharos v2 boards. +They use different format in product-info partition than v1 boards. + +Code was written mostly by Alexander Couzens + +Signed-off-by: Robert Marko +Signed-off-by: Adrian Schmutzler + +Origin: backport, https://github.com/openwrt/openwrt/commit/2524febf7927a1bf430d64b7790feb126023e3d1 + +diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh +index b365b6ae4aa6021960499b3889d846b5171eec0f..94311f75989b0861e188dc89b3e714b5545c1ad8 100755 +--- a/target/linux/ar71xx/base-files/lib/ar71xx.sh ++++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh +@@ -375,7 +375,7 @@ tplink_pharos_get_model_string() { + } + + tplink_pharos_board_detect() { +- local model_string="$(tplink_pharos_get_model_string | tr -d '\r')" ++ local model_string="$1" + local oIFS="$IFS"; IFS=":"; set -- $model_string; IFS="$oIFS" + + local model="${1%%\(*}" +@@ -396,6 +396,14 @@ gl_inet_board_detect() { + esac + } + ++tplink_pharos_v2_get_model_string() { ++ local part ++ part=$(find_mtd_part 'product-info') ++ [ -z "$part" ] && return 1 ++ ++ dd if=$part bs=1 skip=4360 count=64 2>/dev/null | tr -d '\r\0' | head -n 1 ++} ++ + ar71xx_board_detect() { + local machine + local name +@@ -546,11 +554,15 @@ ar71xx_board_detect() { + ;; + *"CPE210/220") + name="cpe210" +- tplink_pharos_board_detect ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" ++ ;; ++ *"CPE210 v2") ++ name="cpe210-v2" ++ tplink_pharos_board_detect "$(tplink_pharos_v2_get_model_string)" + ;; + *"CPE510/520") + name="cpe510" +- tplink_pharos_board_detect ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" + ;; + *CPE830) + name="cpe830" +@@ -560,11 +572,11 @@ ar71xx_board_detect() { + ;; + *WBS210) + name="wbs210" +- tplink_pharos_board_detect ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" + ;; + *WBS510) + name="wbs510" +- tplink_pharos_board_detect ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" + ;; + *CR3000) + name="cr3000" +@@ -641,7 +653,7 @@ ar71xx_board_detect() { + ;; + *"EAP120") + name="eap120" +- tplink_pharos_board_detect ++ tplink_pharos_board_detect "$(tplink_pharos_get_model_string | tr -d '\r')" + ;; + *"EAP300 v2") + name="eap300v2" +diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +index 0b422d71c2639a31bc7e88a20976266b66ec4490..9bc49c41a6308b732e45a7ae35c851133c367254 100755 +--- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh ++++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh +@@ -97,10 +97,11 @@ tplink_pharos_check_support_list() { + local image="$1" + local offset="$2" + local model="$3" ++ local trargs="$4" + + # Here $image is given to dd directly instead of using get_image; + # otherwise the skip will take almost a second (as dd can't seek) +- dd if="$image" bs=1 skip=$offset count=1024 2>/dev/null | ( ++ dd if="$image" bs=1 skip=$offset count=1024 2>/dev/null | tr -d "$trargs" | ( + while IFS= read -r line; do + [ "$line" = "$model" ] && exit 0 + done +@@ -110,17 +111,19 @@ tplink_pharos_check_support_list() { + } + + tplink_pharos_check_image() { +- local magic_long="$(get_magic_long "$1")" +- [ "$magic_long" != "7f454c46" ] && { +- echo "Invalid image magic '$magic_long'" ++ local image_magic="$(get_magic_long "$1")" ++ local board_magic="$2" ++ [ "$image_magic" != "$board_magic" ] && { ++ echo "Invalid image magic '$image_magic'. Expected '$board_magic'." + return 1 + } + +- local model_string="$(tplink_pharos_get_model_string)" ++ local model_string="$3" ++ local trargs="$4" + + # New images have the support list at 7802888, old ones at 1511432 +- tplink_pharos_check_support_list "$1" 7802888 "$model_string" || \ +- tplink_pharos_check_support_list "$1" 1511432 "$model_string" || { ++ tplink_pharos_check_support_list "$1" 7802888 "$model_string" "$trargs" || \ ++ tplink_pharos_check_support_list "$1" 1511432 "$model_string" "$trargs" || { + echo "Unsupported image (model not in support-list)" + return 1 + } +@@ -507,7 +510,11 @@ platform_check_image() { + eap120|\ + wbs210|\ + wbs510) +- tplink_pharos_check_image "$1" && return 0 ++ tplink_pharos_check_image "$1" "7f454c46" "$(tplink_pharos_get_model_string)" '' && return 0 ++ return 1 ++ ;; ++ cpe210-v2) ++ tplink_pharos_check_image "$1" "01000000" "$(tplink_pharos_v2_get_model_string)" '\0\xff\r' && return 0 + return 1 + ;; + a40|\ diff --git a/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch b/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch new file mode 100644 index 00000000..a25b10fd --- /dev/null +++ b/patches/lede/0100-ar71xx-Add-support-for-TP-Link-CPE210-v2.patch @@ -0,0 +1,324 @@ +From: Adrian Schmutzler +Date: Fri, 19 Jan 2018 14:45:42 +0100 +Subject: ar71xx: Add support for TP-Link CPE210 v2 + +This PR adds support for a popular low-cost 2.4GHz N based AP + +Specifications: + - SoC: Qualcomm Atheros QCA9533 (650MHz) + - RAM: 64MB + - Storage: 8 MB SPI NOR + - Wireless: 2.4GHz N based built into SoC 2x2 + - Ethernet: 1x 100/10 Mbps, integrated into SoC, 24V POE IN + +Installation: +Flash factory image through stock firmware WEB UI +or through TFTP +To get to TFTP recovery just hold reset button while powering on for +around 4-5 seconds and release. +Rename factory image to recovery.bin +Stock TFTP server IP:192.168.0.100 +Stock device TFTP adress:192.168.0.254 + +Notes: +TP-Link does not use bootstrap registers so without this patch reference +clock detects as 40MHz while it is actually 25MHz. +This is due to messed up bootstrap resistor configuration on the PCB. +Provided GPL code just forces 25MHz reference clock. +That causes booting with completely wrong clocks, for example, CPU tries +to boot at 1040MHz while the stock is 650MHz. +So this PR depends on PR #672 to remove 40MHz reference clock. +Thanks to Sven Eckelmann for properly patching that. + +Signed-off-by: Robert Marko +Signed-off-by: Adrian Schmutzler + +Origin: backport, https://github.com/openwrt/openwrt/commit/5c5bf8b8658a588423f6ec445d7ef6a36f99a396 + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index a742854bc9b0aa48c61b37e58288177bbb56d14d..54046dffc9a4d4ad0216dcda32bf98ee5d38b569 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -187,16 +187,25 @@ cf-e530n) + ucidef_set_led_netdev "wan" "WAN" "$board:blue:wan" "eth1" + ;; + cpe210|\ ++cpe210-v2|\ + cpe510|\ + wbs210|\ + wbs510) +- ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20" +- ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" + ucidef_set_rssimon "wlan0" "200000" "1" + ucidef_set_led_rssi "rssilow" "RSSILOW" "tp-link:green:link1" "wlan0" "1" "100" "0" "13" + ucidef_set_led_rssi "rssimediumlow" "RSSIMEDIUMLOW" "tp-link:green:link2" "wlan0" "26" "100" "-25" "13" + ucidef_set_led_rssi "rssimediumhigh" "RSSIMEDIUMHIGH" "tp-link:green:link3" "wlan0" "51" "100" "-50" "13" + ucidef_set_led_rssi "rssihigh" "RSSIHIGH" "tp-link:green:link4" "wlan0" "76" "100" "-75" "13" ++ ++ case "$board" in ++ cpe210-v2) ++ ucidef_set_led_netdev "lan" "LAN" "tp-link:green:lan0" "eth0" ++ ;; ++ *) ++ ucidef_set_led_switch "lan0" "LAN0" "tp-link:green:lan0" "switch0" "0x20" ++ ucidef_set_led_switch "lan1" "LAN1" "tp-link:green:lan1" "switch0" "0x10" ++ ;; ++ esac + ;; + cr3000) + ucidef_set_led_netdev "wan" "WAN" "pcs:blue:wan" "eth1" +diff --git a/target/linux/ar71xx/base-files/etc/board.d/02_network b/target/linux/ar71xx/base-files/etc/board.d/02_network +index 875a1a38ada9fb66503505d2f094310db1295a07..633d4e1b7415983f44164187ad3696311ec25621 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/02_network ++++ b/target/linux/ar71xx/base-files/etc/board.d/02_network +@@ -67,6 +67,7 @@ ar71xx_setup_interfaces() + cap4200ag|\ + cf-e380ac-v1|\ + cf-e380ac-v2|\ ++ cpe210-v2|\ + eap120|\ + eap300v2|\ + eap7660d|\ +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +index 2449a8d6bce17f0a703d8fc4f82dd38e1f861ae3..35532d86ac3ad32630592c79477c79783af4addb 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt ++++ b/target/linux/ar71xx/files/arch/mips/ath79/Kconfig.openwrt +@@ -1301,6 +1301,7 @@ config ATH79_MACH_ARCHER_C7 + config ATH79_MACH_CPE510 + bool "TP-LINK CPE510 support" + select SOC_AR934X ++ select SOC_QCA953X + select ATH79_DEV_ETH + select ATH79_DEV_GPIO_BUTTONS + select ATH79_DEV_LEDS_GPIO +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c +index d2dbed1fe286c44d3188262e984253faaee7edba..ceb1769ddd522d51014228fe65e2662f2f3e627c 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c ++++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-cpe510.c +@@ -1,7 +1,8 @@ + /* +- * TP-LINK CPE210/220/510/520 board support ++ * TP-LINK CPE210/210 v2/220/510/520 board support + * + * Copyright (C) 2014 Matthias Schiffer ++ * Copyright (C) 2017 Robert Marko + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published +@@ -41,6 +42,8 @@ + #define CPE510_KEYS_POLL_INTERVAL 20 /* msecs */ + #define CPE510_KEYS_DEBOUNCE_INTERVAL (3 * CPE510_KEYS_POLL_INTERVAL) + ++/* CPE210 v2 reset GPIO */ ++#define CPE210_V2_GPIO_BTN_RESET 17 + + static struct gpio_led cpe510_leds_gpio[] __initdata = { + { +@@ -98,6 +101,30 @@ static struct gpio_led wbs510_leds_gpio[] __initdata = { + }, + }; + ++static struct gpio_led cpe210_v2_leds_gpio[] __initdata = { ++ { ++ .name = "tp-link:green:lan0", ++ .gpio = CPE510_GPIO_LED_LAN0, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link1", ++ .gpio = CPE510_GPIO_LED_L1, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link2", ++ .gpio = CPE510_GPIO_LED_L2, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link3", ++ .gpio = CPE510_GPIO_LED_L3, ++ .active_low = 1, ++ }, { ++ .name = "tp-link:green:link4", ++ .gpio = CPE510_GPIO_LED_L4, ++ .active_low = 1, ++ }, ++}; ++ + static struct gpio_keys_button cpe510_gpio_keys[] __initdata = { + { + .desc = "Reset button", +@@ -109,6 +136,17 @@ static struct gpio_keys_button cpe510_gpio_keys[] __initdata = { + } + }; + ++static struct gpio_keys_button cpe210_v2_gpio_keys[] __initdata = { ++ { ++ .desc = "Reset button", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .debounce_interval = CPE510_KEYS_DEBOUNCE_INTERVAL, ++ .gpio = CPE210_V2_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ + static void __init cpe_setup(u8 *mac) + { + /* Disable JTAG, enabling GPIOs 0-3 */ +@@ -171,9 +209,33 @@ static void __init wbs_setup(void) + ath79_register_wmac(ee, mac); + } + ++static void __init cpe210_v2_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f830008); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ath79_register_leds_gpio(-1, ARRAY_SIZE(cpe210_v2_leds_gpio), ++ cpe210_v2_leds_gpio); ++ ath79_register_gpio_keys_polled(-1, CPE510_KEYS_POLL_INTERVAL, ++ ARRAY_SIZE(cpe210_v2_gpio_keys), ++ cpe210_v2_gpio_keys); ++ ath79_register_m25p80(NULL); ++ ath79_register_mdio(0, 0x0); ++ ath79_init_mac(ath79_eth0_data.mac_addr, mac, 0); ++ ath79_eth0_data.duplex = DUPLEX_FULL; ++ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ath79_eth0_data.speed = SPEED_100; ++ ath79_eth0_data.phy_mask = BIT(4); ++ ath79_register_eth(0); ++ ath79_register_wmac(ee, mac); ++} ++ + MIPS_MACHINE(ATH79_MACH_CPE210, "CPE210", "TP-LINK CPE210/220", + cpe210_setup); + ++MIPS_MACHINE(ATH79_MACH_CPE210_V2, "CPE210V2", "TP-LINK CPE210 v2", ++ cpe210_v2_setup); ++ + MIPS_MACHINE(ATH79_MACH_CPE510, "CPE510", "TP-LINK CPE510/520", + cpe510_setup); + +diff --git a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +index a4c7f52fe94e17bc48bebfb460f12f3e5ac35afe..e7e7f94775a3122286dc39447f04b42f4863f313 100644 +--- a/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h ++++ b/target/linux/ar71xx/files/arch/mips/ath79/machtypes.h +@@ -64,7 +64,8 @@ enum ath79_mach_type { + ATH79_MACH_CF_E380AC_V2, /* COMFAST CF-E380AC v2 */ + ATH79_MACH_CF_E520N, /* COMFAST CF-E520N */ + ATH79_MACH_CF_E530N, /* COMFAST CF-E530N */ +- ATH79_MACH_CPE210, /* TP-LINK CPE210 */ ++ ATH79_MACH_CPE210, /* TP-LINK CPE210 v1 */ ++ ATH79_MACH_CPE210_V2, /* TP-LINK CPE210 v2 */ + ATH79_MACH_CPE510, /* TP-LINK CPE510 */ + ATH79_MACH_CPE830, /* YunCore CPE830 */ + ATH79_MACH_CPE870, /* YunCore CPE870 */ +diff --git a/target/linux/ar71xx/image/tp-link.mk b/target/linux/ar71xx/image/tp-link.mk +index 6a3faef518ebfa4f36d3074ee9c102b801e04275..b61ef6dc78918dd8d040c0f2bfb6451e5e13ba92 100644 +--- a/target/linux/ar71xx/image/tp-link.mk ++++ b/target/linux/ar71xx/image/tp-link.mk +@@ -164,22 +164,26 @@ define Device/archer-c60-v1 + endef + TARGET_DEVICES += archer-c60-v1 + +-define Device/cpe510-520 +- DEVICE_TITLE := TP-LINK CPE510/520 ++define Device/cpexxx + DEVICE_PACKAGES := rssileds + MTDPARTS := spi0.0:128k(u-boot)ro,64k(partition-table)ro,64k(product-info)ro,1792k(kernel),5888k(rootfs),192k(config)ro,64k(ART)ro,7680k@0x40000(firmware) + IMAGE_SIZE := 7680k +- BOARDNAME := CPE510 +- TPLINK_BOARD_NAME := CPE510 + DEVICE_PROFILE := CPE510 + LOADER_TYPE := elf ++ IMAGES := sysupgrade.bin factory.bin ++ IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade ++ IMAGE/factory.bin := append-rootfs | tplink-safeloader factory ++endef ++ ++define Device/cpe510-520 ++ $(Device/cpexxx) ++ DEVICE_TITLE := TP-LINK CPE510/520 v1 ++ BOARDNAME := CPE510 ++ TPLINK_BOARD_NAME := CPE510 + LOADER_FLASH_OFFS := 0x43000 + COMPILE := loader-$(1).elf + COMPILE/loader-$(1).elf := loader-okli-compile + KERNEL := kernel-bin | lzma | uImage lzma -M 0x4f4b4c49 | loader-okli $(1) 12288 +- IMAGES := sysupgrade.bin factory.bin +- IMAGE/sysupgrade.bin := append-rootfs | tplink-safeloader sysupgrade +- IMAGE/factory.bin := append-rootfs | tplink-safeloader factory + endef + + define Device/cpe210-220 +@@ -190,6 +194,19 @@ $(Device/cpe510-520) + TPLINK_BOARD_NAME := CPE210 + endef + ++define Device/cpe210-v2 ++ $(Device/cpexxx) ++ DEVICE_TITLE := TP-LINK CPE210 v2 ++ BOARDNAME := CPE210V2 ++ TPLINK_BOARD_NAME := CPE210V2 ++ KERNEL := kernel-bin | patch-cmdline | lzma | mktplinkfw-combined ++ TPLINK_HWID := 0x0 ++ TPLINK_HWREV := 0 ++ TPLINK_HEADER_VERSION := 1 ++ TPLINK_FLASHLAYOUT := 8Mlzma ++endef ++TARGET_DEVICES += cpe210-v2 ++ + define Device/wbs210 + $(Device/cpe510-520) + DEVICE_TITLE := TP-LINK WBS210 +diff --git a/tools/firmware-utils/src/tplink-safeloader.c b/tools/firmware-utils/src/tplink-safeloader.c +index 23b69f3bd0eb66aca650eb2ffd7d5cd2a7cb5194..e6ecc5b2c52c1627c8b998fa731b50ed39649f96 100644 +--- a/tools/firmware-utils/src/tplink-safeloader.c ++++ b/tools/firmware-utils/src/tplink-safeloader.c +@@ -154,6 +154,48 @@ static struct device_info boards[] = { + .last_sysupgrade_partition = "support-list", + }, + ++ /** Firmware layout for the CPE210 V2 */ ++ { ++ .id = "CPE210V2", ++ .vendor = "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n", ++ .support_list = ++ "SupportList:\r\n" ++ "CPE210(TP-LINK|EU|N300-2|00000000):2.0\r\n" ++ "CPE210(TP-LINK|EU|N300-2|45550000):2.0\r\n" ++ "CPE210(TP-LINK|EU|N300-2|55530000):2.0\r\n" ++ "CPE210(TP-LINK|UN|N300-2|00000000):2.0\r\n" ++ "CPE210(TP-LINK|UN|N300-2|45550000):2.0\r\n" ++ "CPE210(TP-LINK|UN|N300-2|55530000):2.0\r\n" ++ "CPE210(TP-LINK|US|N300-2|55530000):2.0\r\n" ++ "CPE210(TP-LINK|UN|N300-2):2.0\r\n" ++ "CPE210(TP-LINK|EU|N300-2):2.0\r\n" ++ "CPE210(TP-LINK|US|N300-2):2.0\r\n", ++ .support_trail = '\xff', ++ .soft_ver = NULL, ++ ++ .partitions = { ++ {"fs-uboot", 0x00000, 0x20000}, ++ {"partition-table", 0x20000, 0x02000}, ++ {"default-mac", 0x30000, 0x00020}, ++ {"product-info", 0x31100, 0x00100}, ++ {"device-info", 0x31400, 0x00400}, ++ {"signature", 0x32000, 0x00400}, ++ {"device-id", 0x33000, 0x00100}, ++ {"os-image", 0x40000, 0x1c0000}, ++ {"file-system", 0x200000, 0x5b0000}, ++ {"soft-version", 0x7b0000, 0x00100}, ++ {"support-list", 0x7b1000, 0x01000}, ++ {"user-config", 0x7c0000, 0x10000}, ++ {"default-config", 0x7d0000, 0x10000}, ++ {"log", 0x7e0000, 0x10000}, ++ {"radio", 0x7f0000, 0x10000}, ++ {NULL, 0, 0} ++ }, ++ ++ .first_sysupgrade_partition = "os-image", ++ .last_sysupgrade_partition = "support-list", ++ }, ++ + /** Firmware layout for the CPE510/520 */ + { + .id = "CPE510", diff --git a/patches/lede/0101-ar71xx-use-Power-LED-as-Diag-LED-on-FRITZBox-4020.patch b/patches/lede/0101-ar71xx-use-Power-LED-as-Diag-LED-on-FRITZBox-4020.patch new file mode 100644 index 00000000..96567055 --- /dev/null +++ b/patches/lede/0101-ar71xx-use-Power-LED-as-Diag-LED-on-FRITZBox-4020.patch @@ -0,0 +1,33 @@ +From: David Bauer +Date: Fri, 8 Jun 2018 21:42:52 +0200 +Subject: ar71xx: use Power-LED as Diag-LED on FRITZBox 4020 + +This commit makes use of the Power-LED as Diag-LED, allowing the LED to +work as a status indicator. + +Signed-off-by: David Bauer + +diff --git a/target/linux/ar71xx/base-files/etc/board.d/01_leds b/target/linux/ar71xx/base-files/etc/board.d/01_leds +index 54046dffc9a4d4ad0216dcda32bf98ee5d38b569..e163e3171a747c3756c376c4a92b1bc50baa8eaa 100755 +--- a/target/linux/ar71xx/base-files/etc/board.d/01_leds ++++ b/target/linux/ar71xx/base-files/etc/board.d/01_leds +@@ -315,7 +315,6 @@ dlan-pro-1200-ac) + ucidef_set_led_gpio "plcr" "dLAN" "devolo:error:dlan" "16" "0" + ;; + fritz4020) +- ucidef_set_led_default "power" "Power" "$board:green:power" "1" + ucidef_set_led_netdev "lan" "LAN" "$board:green:lan" "eth1" + ucidef_set_led_netdev "wan" "WAN" "$board:green:wan" "eth0" + ucidef_set_led_wlan "wlan" "WLAN" "$board:green:wlan" "phy0tpt" +diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh +index f8d2eb314f7b57a1134b68c504c0dac202ed947c..8002e9702720a431dd38c598cb8f1f3284d3af1c 100644 +--- a/target/linux/ar71xx/base-files/etc/diag.sh ++++ b/target/linux/ar71xx/base-files/etc/diag.sh +@@ -55,6 +55,7 @@ get_status_led() { + archer-c58-v1|\ + archer-c59-v1|\ + archer-c60-v1|\ ++ fritz4020|\ + mr12|\ + mr16|\ + nbg6616|\ diff --git a/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch b/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch deleted file mode 100644 index 0db0eda7..00000000 --- a/patches/openwrt/0001-tools-Makefile-fix-host-tools-build-dependencies.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Matthias Schiffer -Date: Sat, 26 Jul 2014 06:10:23 +0200 -Subject: tools/Makefile: fix host tools build dependencies - -diff --git a/tools/Makefile b/tools/Makefile -index d2fe2ff..c6cded8 100644 ---- a/tools/Makefile -+++ b/tools/Makefile -@@ -95,10 +95,16 @@ define PrepareStaging - endef - - # preparatory work -+ifneq ($(ARCH),) -+staging_prepared = $(STAGING_DIR)/.prepared -+ - $(STAGING_DIR)/.prepared: $(TMP_DIR)/.build - $(call PrepareStaging,$(STAGING_DIR)) - mkdir -p $(BUILD_DIR)/stamp - touch $@ -+else -+staging_prepared := -+endif - - $(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build - $(call PrepareStaging,$(STAGING_DIR_HOST)) -@@ -110,8 +116,8 @@ $(STAGING_DIR_HOST)/.prepared: $(TMP_DIR)/.build - - endif - --$(curdir)//prepare = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared --$(curdir)//compile = $(STAGING_DIR)/.prepared $(STAGING_DIR_HOST)/.prepared -+$(curdir)//prepare = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared -+$(curdir)//compile = $(staging_prepared) $(STAGING_DIR_HOST)/.prepared - - # prerequisites for the individual targets - $(curdir)/ := .config prereq diff --git a/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch b/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch deleted file mode 100644 index 82de5300..00000000 --- a/patches/openwrt/0003-odhcp6c-always-accept-RDNSS-independent-of-the-default-router-lifetime.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Matthias Schiffer -Date: Thu, 13 Nov 2014 01:17:24 +0100 -Subject: odhcp6c: always accept RDNSS, independent of the default router lifetime - -diff --git a/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch -new file mode 100644 -index 0000000..cb694ca ---- /dev/null -+++ b/package/network/ipv6/odhcp6c/patches/001-always_accept_rdnss.patch -@@ -0,0 +1,21 @@ -+--- a/src/ra.c -++++ b/src/ra.c -+@@ -438,18 +438,6 @@ bool ra_process(void) -+ } -+ } -+ } -+- -+- int states[2] = {STATE_RA_DNS, STATE_RA_SEARCH}; -+- for (size_t i = 0; i < 2; ++i) { -+- size_t ra_dns_len; -+- uint8_t *start = odhcp6c_get_state(states[i], &ra_dns_len); -+- for (struct odhcp6c_entry *c = (struct odhcp6c_entry*)start; -+- (uint8_t*)c < &start[ra_dns_len] && &c->auxtarget[c->auxlen] <= &start[ra_dns_len]; -+- c = (struct odhcp6c_entry*)(&c->auxtarget[c->auxlen])) -+- if (IN6_ARE_ADDR_EQUAL(&c->router, &from.sin6_addr) && -+- c->valid > router_valid) -+- c->valid = router_valid; -+- } -+ } -+ -+ if (found) diff --git a/patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch b/patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch deleted file mode 100644 index 772ade62..00000000 --- a/patches/openwrt/0004-busybox-enable-telnet-only-when-root-password-is-really-empty-not-when-it-is-locked.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 5 Dec 2014 18:57:16 +0100 -Subject: busybox: enable telnet only when root password is really empty, not when it is locked - -diff --git a/package/utils/busybox/files/telnet b/package/utils/busybox/files/telnet -index a1d1cdf..f95be90 100755 ---- a/package/utils/busybox/files/telnet -+++ b/package/utils/busybox/files/telnet -@@ -11,7 +11,7 @@ has_root_pwd() { - pwd="${pwd#*root:}" - pwd="${pwd%%:*}" - -- test -n "${pwd#[\!x]}" -+ test -n "${pwd}" - } - - get_root_home() { -@@ -28,7 +28,7 @@ has_ssh_pubkey() { - - start_service() { - if ( ! has_ssh_pubkey && \ -- ! has_root_pwd /etc/passwd && ! has_root_pwd /etc/shadow ) || \ -+ ( ! has_root_pwd /etc/passwd || ! has_root_pwd /etc/shadow ) ) || \ - ( ! /etc/init.d/dropbear enabled 2> /dev/null && ! /etc/init.d/sshd enabled 2> /dev/null ); - then - procd_open_instance diff --git a/patches/openwrt/0005-base-files-disable-reset-button-handling.patch b/patches/openwrt/0005-base-files-disable-reset-button-handling.patch deleted file mode 100644 index a889df96..00000000 --- a/patches/openwrt/0005-base-files-disable-reset-button-handling.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Matthias Schiffer -Date: Sat, 21 Mar 2015 16:40:52 +0100 -Subject: base-files: disable reset button handling - -This conflicts with our reset button usage. - -diff --git a/package/base-files/files/etc/rc.button/reset b/package/base-files/files/etc/rc.button/reset -deleted file mode 100755 -index 3e24146..0000000 ---- a/package/base-files/files/etc/rc.button/reset -+++ /dev/null -@@ -1,20 +0,0 @@ --#!/bin/sh -- --[ "${ACTION}" = "released" ] || exit 0 -- --. /lib/functions.sh -- --logger "$BUTTON pressed for $SEEN seconds" -- --if [ "$SEEN" -lt 1 ] --then -- echo "REBOOT" > /dev/console -- sync -- reboot --elif [ "$SEEN" -gt 5 ] --then -- echo "FACTORY RESET" > /dev/console -- jffs2reset -y && reboot & --fi -- --return 0 diff --git a/patches/openwrt/0006-ath10k-firmware-add-Candela-Technologies-firmware-for-QCA988X.patch b/patches/openwrt/0006-ath10k-firmware-add-Candela-Technologies-firmware-for-QCA988X.patch deleted file mode 100644 index 5baf2712..00000000 --- a/patches/openwrt/0006-ath10k-firmware-add-Candela-Technologies-firmware-for-QCA988X.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: Matthias Schiffer -Date: Tue, 9 Feb 2016 18:22:29 +0100 -Subject: ath10k-firmware: add Candela Technologies firmware for QCA988X - -diff --git a/package/firmware/ath10k-firmware/Makefile b/package/firmware/ath10k-firmware/Makefile -index b03d644..7d4d449 100644 ---- a/package/firmware/ath10k-firmware/Makefile -+++ b/package/firmware/ath10k-firmware/Makefile -@@ -44,6 +44,26 @@ define Download/ath10k-firmware-qca988x - endef - $(eval $(call Download,ath10k-firmware-qca988x)) - -+ -+define Package/ath10k-firmware-qca988x-ct -+$(Package/ath10k-firmware-default) -+ TITLE:=ath10k firmware for QCA988x devices (Candela Technologies version) -+ CONFLICTS:=ath10k-firmware-qca988x -+endef -+ -+QCA988X_CT_FIRMWARE_FILE:=firmware-5-ct-full-community.bin -+ -+define Download/ath10k-firmware-qca988x-ct -+ # See http://www.candelatech.com/ath10k.php -+ #URL:=http://www.candelatech.com/downloads/ath10k-10-2/ -+ # Update to beta version (will switch back to official URL after v2 release) -+ URL:=https://home.universe-factory.net/neoraider/ -+ FILE:=$(QCA988X_CT_FIRMWARE_FILE) -+ MD5SUM:=9aa205cfd6b98e695ca8e9ae6d1bcb6b -+endef -+$(eval $(call Download,ath10k-firmware-qca988x-ct)) -+ -+ - define Package/ath10k-firmware-qca99x0 - $(Package/ath10k-firmware-default) - TITLE:=ath10k firmware for QCA99x0 devices -@@ -79,6 +99,16 @@ define Package/ath10k-firmware-qca988x/install - $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin - endef - -+define Package/ath10k-firmware-qca988x-ct/install -+ $(INSTALL_DIR) $(1)/lib/firmware/ath10k/QCA988X/hw2.0 -+ $(INSTALL_DATA) \ -+ $(PKG_BUILD_DIR)/QCA988X/board.bin \ -+ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/ -+ $(INSTALL_DATA) \ -+ $(DL_DIR)/$(QCA988X_CT_FIRMWARE_FILE) \ -+ $(1)/lib/firmware/ath10k/QCA988X/hw2.0/firmware-5.bin -+endef -+ - define Package/ath10k-firmware-qca6174/install - $(INSTALL_DIR) $(1)/lib/firmware/ath10k - $(CP) $(PKG_BUILD_DIR)/QCA6174 $(1)/lib/firmware/ath10k/ -@@ -98,5 +128,6 @@ define Package/ath10k-firmware-qca99x0/install - endef - - $(eval $(call BuildPackage,ath10k-firmware-qca988x)) -+$(eval $(call BuildPackage,ath10k-firmware-qca988x-ct)) - $(eval $(call BuildPackage,ath10k-firmware-qca99x0)) - $(eval $(call BuildPackage,ath10k-firmware-qca6174)) -diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile -index 30da1cf..cd8d670 100644 ---- a/package/kernel/mac80211/Makefile -+++ b/package/kernel/mac80211/Makefile -@@ -247,7 +247,7 @@ define KernelPackage/ath10k - $(call KernelPackage/mac80211/Default) - TITLE:=Atheros 802.11ac wireless cards support - URL:=https://wireless.wiki.kernel.org/en/users/Drivers/ath10k -- DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +@KERNEL_RELAY +ath10k-firmware-qca988x -+ DEPENDS+= @PCI_SUPPORT +kmod-ath +@DRIVER_11N_SUPPORT +@DRIVER_11W_SUPPORT +@KERNEL_RELAY - FILES:= \ - $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_core.ko \ - $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath10k/ath10k_pci.ko diff --git a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch b/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch deleted file mode 100644 index 7586d3a2..00000000 --- a/patches/openwrt/0007-mac80211-ath10k-allow-simultaneous-AP-IBSS.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 20 May 2015 23:10:36 +0200 -Subject: mac80211: ath10k: allow simultaneous AP+IBSS - -diff --git a/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch -new file mode 100644 -index 0000000..33b3110 ---- /dev/null -+++ b/package/kernel/mac80211/patches/950-ath10k_AP_IBSS.patch -@@ -0,0 +1,32 @@ -+--- a/drivers/net/wireless/ath/ath10k/mac.c -++++ b/drivers/net/wireless/ath/ath10k/mac.c -+@@ -5264,6 +5264,10 @@ static const struct ieee80211_iface_limi -+ .max = 7, -+ .types = BIT(NL80211_IFTYPE_AP) -+ }, -++ { -++ .max = 1, -++ .types = BIT(NL80211_IFTYPE_ADHOC) -++ }, -+ }; -+ -+ static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { -+@@ -5271,6 +5275,10 @@ static const struct ieee80211_iface_limi -+ .max = 8, -+ .types = BIT(NL80211_IFTYPE_AP) -+ }, -++ { -++ .max = 1, -++ .types = BIT(NL80211_IFTYPE_ADHOC) -++ }, -+ }; -+ -+ static const struct ieee80211_iface_combination ath10k_if_comb[] = { -+@@ -5575,6 +5583,7 @@ int ath10k_mac_register(struct ath10k *a -+ ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb; -+ ar->hw->wiphy->n_iface_combinations = -+ ARRAY_SIZE(ath10k_10x_if_comb); -++ ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); -+ break; -+ case ATH10K_FW_WMI_OP_VERSION_UNSET: -+ case ATH10K_FW_WMI_OP_VERSION_MAX: diff --git a/patches/openwrt/0008-iwinfo-update-NanoStation-Loco-txpower-offsets.patch b/patches/openwrt/0008-iwinfo-update-NanoStation-Loco-txpower-offsets.patch deleted file mode 100644 index b45cf4e7..00000000 --- a/patches/openwrt/0008-iwinfo-update-NanoStation-Loco-txpower-offsets.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 20 May 2015 23:15:20 +0200 -Subject: iwinfo: update NanoStation (Loco) txpower offsets - -diff --git a/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch b/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch -new file mode 100644 -index 0000000..1e13570 ---- /dev/null -+++ b/package/network/utils/iwinfo/patches/001-update_nanostation_offsets.patch -@@ -0,0 +1,14 @@ -+--- a/hardware.txt -++++ b/hardware.txt -+@@ -42,8 +42,9 @@ -+ 0x168c 0x0027 0x0777 0x4082 7 0 "Ubiquiti" "SR71" -+ 0x168c 0x0029 0x0777 0x4005 7 0 "Ubiquiti" "SR71-15" -+ 0x168c 0x002a 0x0777 0xe302 12 0 "Ubiquiti" "PicoStation M2" /* ToDo: confirm offset */ -+-0x168c 0x002a 0x0777 0xe012 12 0 "Ubiquiti" "NanoStation M2" /* ToDo: confirm offset */ -+-0x168c 0x002a 0x0777 0xe005 5 0 "Ubiquiti" "NanoStation M5" /* ToDo: confirm offset */ -++0x168c 0x002a 0x0777 0xe012 11 0 "Ubiquiti" "NanoStation M2" -++0x168c 0x002e 0x0777 0xe0a2 8 0 "Ubiquiti" "NanoStation Loco M2" -++0x168c 0x002a 0x0777 0xe005 16 0 "Ubiquiti" "NanoStation M5" -+ 0x168c 0x002a 0x0777 0xe202 12 0 "Ubiquiti" "Bullet M2" -+ 0x168c 0x002a 0x0777 0xe805 5 0 "Ubiquiti" "Bullet M5" -+ 0x168c 0x002a 0x0777 0xe345 0 0 "Ubiquiti" "WispStation M5" /* ToDo: confirm offset */ diff --git a/patches/openwrt/0010-ath9k-add-HSR-tuner-support-for-UniFi-Outdoor-Plus.patch b/patches/openwrt/0010-ath9k-add-HSR-tuner-support-for-UniFi-Outdoor-Plus.patch deleted file mode 100644 index 3b74d88d..00000000 --- a/patches/openwrt/0010-ath9k-add-HSR-tuner-support-for-UniFi-Outdoor-Plus.patch +++ /dev/null @@ -1,392 +0,0 @@ -From: Matthias Schiffer -Date: Thu, 3 Sep 2015 23:50:51 +0200 -Subject: ath9k: add HSR tuner support for UniFi Outdoor Plus - -Patch-by: Stefan Rompf - -diff --git a/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch -new file mode 100644 -index 0000000..4533335 ---- /dev/null -+++ b/package/kernel/mac80211/patches/931-ubnt-uap-plus-hsr.patch -@@ -0,0 +1,346 @@ -+--- a/drivers/net/wireless/ath/ath9k/channel.c -++++ b/drivers/net/wireless/ath/ath9k/channel.c -+@@ -15,6 +15,8 @@ -+ */ -+ -+ #include "ath9k.h" -++#include -++#include "hsr.h" -+ -+ /* Set/change channels. If the channel is really being changed, it's done -+ * by reseting the chip. To accomplish this we must first cleanup any pending -+@@ -22,6 +24,7 @@ -+ */ -+ static int ath_set_channel(struct ath_softc *sc) -+ { -++ struct ath9k_platform_data *pdata = sc->dev->platform_data; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ieee80211_hw *hw = sc->hw; -+@@ -41,6 +44,11 @@ static int ath_set_channel(struct ath_so -+ ath_dbg(common, CONFIG, "Set channel: %d MHz width: %d\n", -+ chan->center_freq, chandef->width); -+ -++ if (pdata && pdata->ubnt_hsr) { -++ hsr_enable(ah, chandef->width, chan->center_freq); -++ hsr_status(ah); -++ } -++ -+ /* update survey stats for the old channel before switching */ -+ spin_lock_bh(&common->cc_lock); -+ ath_update_survey_stats(sc); -+--- /dev/null -++++ b/drivers/net/wireless/ath/ath9k/hsr.c -+@@ -0,0 +1,220 @@ -++/* -++ * -++ * The MIT License (MIT) -++ * -++ * Copyright (c) 2015 Kirill Berezin -++ * -++ * Permission is hereby granted, free of charge, to any person obtaining a copy -++ * of this software and associated documentation files (the "Software"), to deal -++ * in the Software without restriction, including without limitation the rights -++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -++ * copies of the Software, and to permit persons to whom the Software is -++ * furnished to do so, subject to the following conditions: -++ * -++ * The above copyright notice and this permission notice shall be included in all -++ * copies or substantial portions of the Software. -++ * -++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -++ * SOFTWARE. -++ * -++ */ -++ -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++#include -++ -++#include "hw.h" -++#include "ath9k.h" -++ -++#define HSR_GPIO_CSN 8 -++#define HSR_GPIO_CLK 6 -++#define HSR_GPIO_DOUT 7 -++#define HSR_GPIO_DIN 5 -++ -++/* delays are in useconds */ -++#define HSR_DELAY_HALF_TICK 100 -++#define HSR_DELAY_PRE_WRITE 75 -++#define HSR_DELAY_FINAL 20000 -++#define HSR_DELAY_TRAILING 200 -++ -++ -++void hsr_init(struct ath_hw* ah) { -++ ath9k_hw_cfg_gpio_input(ah, HSR_GPIO_DIN); -++ ath9k_hw_cfg_output(ah, HSR_GPIO_CSN, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -++ ath9k_hw_cfg_output(ah, HSR_GPIO_CLK, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -++ ath9k_hw_cfg_output(ah, HSR_GPIO_DOUT, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, 0); -++ -++ udelay(HSR_DELAY_TRAILING); -++} -++ -++static u32 hsr_write_byte(struct ath_hw* ah, int delay, u32 value){ -++ struct ath_common *common = ath9k_hw_common(ah); -++ int i; -++ u32 rval = 0; -++ -++ udelay(delay); -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -++ udelay(HSR_DELAY_HALF_TICK); -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 0); -++ udelay(HSR_DELAY_HALF_TICK); -++ -++ for( i = 0; i < 8; ++i) { -++ rval = rval << 1; -++ -++ // pattern is left to right, that is 7-th bit runs first -++ ath9k_hw_set_gpio(ah, HSR_GPIO_DOUT, (value >> (7 - i)) & 0x1); -++ udelay(HSR_DELAY_HALF_TICK); -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 1); -++ udelay(HSR_DELAY_HALF_TICK); -++ -++ rval |= ath9k_hw_gpio_get(ah, HSR_GPIO_DIN); -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CLK, 0); -++ udelay(HSR_DELAY_HALF_TICK); -++ } -++ -++ ath9k_hw_set_gpio(ah, HSR_GPIO_CSN, 1); -++ udelay(HSR_DELAY_HALF_TICK); -++ -++ ath_dbg(common, CONFIG, "hsr_write_byte: write byte %d return value is %d %c\n", -++ value, rval, rval > 32 ? rval : '-'); -++ -++ return rval & 0xff; -++} -++ -++static int hsr_write_a_chain(struct ath_hw* ah, char* chain, int items) { -++ int i = 0; -++ int status = 0; -++ -++ // a preamble -++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -++ status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -++ -++ // clear HSR's reply buffer -++ if (status) { -++ int loop = 0; -++ for ( loop = 0; (loop < 42) && status; ++loop) { -++ status = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -++ } -++ if ( loop >= 42) { -++ ATH_DBG_WARN(1, "hsr_write_a_chain: can't clear an output buffer after a 42 cycles.\n"); -++ return -1; -++ } -++ } -++ -++ for ( i =0; (i < items) && ( 0 != chain[i]); ++i) { -++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, (u32)chain[i]); -++ } -++ -++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -++ mdelay(HSR_DELAY_FINAL / 1000); -++ -++ // reply -++ memset(chain, 0, items); -++ -++ hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0); -++ udelay(HSR_DELAY_TRAILING); -++ -++ for ( i = 0; i < (items - 1); ++i) { -++ u32 ret; -++ if ( 0 != (ret = hsr_write_byte(ah, HSR_DELAY_PRE_WRITE, 0))) { -++ chain[i] = (char)ret; -++ } else { -++ break; -++ } -++ udelay(HSR_DELAY_TRAILING); -++ } -++ -++ return (1 < i) ? simple_strtol(chain + 1, NULL, 10) : 0; -++} -++ -++int hsr_disable(struct ath_hw* ah) { -++ char cmd[10] = {'b', '4', '0', 0, 0, 0, 0, 0, 0, 0}; -++ int ret; -++ -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( (ret > 0) && (*cmd == 'B')) { -++ return 0; -++ } -++ -++ return -1; -++} -++ -++int hsr_enable(struct ath_hw* ah, int bw, int fq) { -++ char cmd[10]; -++ int ret; -++ -++ /* Bandwidth argument is 0 sometimes. Assume default 802.11bgn -++ 20MHz on invalid values */ -++ if ( (bw != 5) && (bw != 10) && (bw != 20) && (bw != 40)) { -++ bw = 20; -++ } -++ -++ memset(cmd, 0, sizeof(cmd)); -++ *cmd = 'b'; // 98 -++ snprintf(cmd + 1, 3, "%02d", bw); -++ -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( (*cmd != 'B') || (ret != bw)) { -++ ATH_DBG_WARN(1, "hsr_enable: failed changing bandwidth -> set (%d,%d) reply (%d, %d) \n", 'b', bw, *cmd, ret); -++ return -1; -++ } -++ -++ memset(cmd, 0, sizeof(cmd)); -++ *cmd = 'x'; // 120 -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( *cmd != 'X') { -++ ATH_DBG_WARN(1, "hsr_enable: failed 'x' command -> reply (%d, %d) \n", *cmd, ret); -++ return -1; -++ } -++ -++ memset(cmd, 0, sizeof(cmd)); -++ *cmd = 'm'; // 109 -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( *cmd != 'M') { -++ ATH_DBG_WARN(1, "hsr_enable: failed 'm' command -> reply (%d, %d) \n", *cmd, ret); -++ return -1; -++ } -++ -++ memset(cmd, 0, sizeof(cmd)); -++ *cmd = 'f'; // 102 -++ snprintf(cmd + 1, 6, "%05d", fq); -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( (*cmd != 'F') && (ret != fq)) { -++ ATH_DBG_WARN(1, "hsr_enable: failed set frequency -> reply (%d, %d) \n", *cmd, ret); -++ return -1; -++ } -++ -++ return 0; -++} -++ -++int hsr_status(struct ath_hw* ah) { -++ char cmd[10] = {'s', 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 115 -++ int ret; -++ -++ ret = hsr_write_a_chain(ah, cmd, sizeof(cmd)); -++ if ( (*cmd != 'S')) { -++ ATH_DBG_WARN(1, "hsr_status: returned %d,%d \n", *cmd, ret); -++ return -1; -++ } -++ -++ return 0; -++} -++ -+--- /dev/null -++++ b/drivers/net/wireless/ath/ath9k/hsr.h -+@@ -0,0 +1,33 @@ -++/* -++ * The MIT License (MIT) -++ * -++ * Copyright (c) 2015 Kirill Berezin -++ * -++ * Permission is hereby granted, free of charge, to any person obtaining a copy -++ * of this software and associated documentation files (the "Software"), to deal -++ * in the Software without restriction, including without limitation the rights -++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -++ * copies of the Software, and to permit persons to whom the Software is -++ * furnished to do so, subject to the following conditions: -++ * -++ * The above copyright notice and this permission notice shall be included in all -++ * copies or substantial portions of the Software. -++ * -++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -++ * SOFTWARE. -++ */ -++ -++#ifndef HSR_H_ -++#define HSR_H_ -++ -++void hsr_init(struct ath_hw* ah); -++int hsr_disable(struct ath_hw* ah); -++int hsr_enable(struct ath_hw* ah, int bw, int fq); -++int hsr_status(struct ath_hw* ah); -++ -++#endif /* HSR_H_ */ -+--- a/drivers/net/wireless/ath/ath9k/main.c -++++ b/drivers/net/wireless/ath/ath9k/main.c -+@@ -16,8 +16,10 @@ -+ -+ #include -+ #include -++#include -+ #include "ath9k.h" -+ #include "btcoex.h" -++#include "hsr.h" -+ -+ u8 ath9k_parse_mpdudensity(u8 mpdudensity) -+ { -+@@ -652,6 +654,7 @@ void ath_reset_work(struct work_struct * -+ static int ath9k_start(struct ieee80211_hw *hw) -+ { -+ struct ath_softc *sc = hw->priv; -++ struct ath9k_platform_data *pdata = sc->dev->platform_data; -+ struct ath_hw *ah = sc->sc_ah; -+ struct ath_common *common = ath9k_hw_common(ah); -+ struct ieee80211_channel *curchan = sc->cur_chan->chandef.chan; -+@@ -730,6 +733,11 @@ static int ath9k_start(struct ieee80211_ -+ (ah->config.led_active_high) ? 1 : 0); -+ } -+ -++ if (pdata && pdata->ubnt_hsr) { -++ hsr_init(ah); -++ hsr_disable(ah); -++ } -++ -+ /* -+ * Reset key cache to sane defaults (all entries cleared) instead of -+ * semi-random values after suspend/resume. -+--- a/drivers/net/wireless/ath/ath9k/Makefile -++++ b/drivers/net/wireless/ath/ath9k/Makefile -+@@ -6,7 +6,8 @@ ath9k-y += beacon.o \ -+ xmit.o \ -+ link.o \ -+ antenna.o \ -+- channel.o -++ channel.o \ -++ hsr.o -+ -+ ath9k-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += mci.o -+ ath9k-$(CPTCFG_ATH9K_PCI) += pci.o -+--- a/include/linux/ath9k_platform.h -++++ b/include/linux/ath9k_platform.h -+@@ -44,6 +44,8 @@ struct ath9k_platform_data { -+ -+ int num_leds; -+ const struct gpio_led *leds; -++ -++ bool ubnt_hsr; -+ }; -+ -+ #endif /* _LINUX_ATH9K_PLATFORM_H */ -diff --git a/target/linux/ar71xx/patches-3.18/608-MIPS-ath79-ubnt-xm-add-more-boards.patch b/target/linux/ar71xx/patches-3.18/608-MIPS-ath79-ubnt-xm-add-more-boards.patch -index 7803513..d865ed2 100644 ---- a/target/linux/ar71xx/patches-3.18/608-MIPS-ath79-ubnt-xm-add-more-boards.patch -+++ b/target/linux/ar71xx/patches-3.18/608-MIPS-ath79-ubnt-xm-add-more-boards.patch -@@ -254,6 +254,7 @@ - + ath79_register_eth(0); - + ath79_register_eth(1); - + -++ ap9x_pci_get_wmac_data(0)->ubnt_hsr = true; - + ap91_pci_init(ee, NULL); - + - + ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifi_outdoor_plus_leds_gpio), -diff --git a/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch b/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch -new file mode 100644 -index 0000000..a0ebbc7 ---- /dev/null -+++ b/target/linux/generic/patches-3.18/150-ath9k_ubnt_hsr_filter.patch -@@ -0,0 +1,16 @@ -+Flag that this platform is an Ubiquiti UniFi Outdoor Plus -+containing a RF filter in ath9k's receive path. -+ -+Signed-off-by: Stefan Rompf -+ -+--- a/include/linux/ath9k_platform.h -++++ b/include/linux/ath9k_platform.h -+@@ -44,6 +44,8 @@ struct ath9k_platform_data { -+ -+ int num_leds; -+ const struct gpio_led *leds; -++ -++ bool ubnt_hsr; -+ }; -+ -+ #endif /* _LINUX_ATH9K_PLATFORM_H */ diff --git a/patches/openwrt/0011-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch b/patches/openwrt/0011-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch deleted file mode 100644 index c1eaeefe..00000000 --- a/patches/openwrt/0011-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch +++ /dev/null @@ -1,57 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 2 Nov 2015 02:02:02 +0100 -Subject: ipv6: fix crash on ICMPv6 redirects with prohibited/blackholed source - -There are other error values besides ip6_null_entry that can be returned by -ip6_route_redirect(): fib6_rule_action() can also result in -ip6_blk_hole_entry and ip6_prohibit_entry if such ip rules are installed. - -Only checking for ip6_null_entry in rt6_do_redirect() causes ip6_ins_rt() -to be called with rt->rt6i_table == NULL in these cases, making the kernel -crash. - -diff --git a/target/linux/generic/patches-3.18/672-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch b/target/linux/generic/patches-3.18/672-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch -new file mode 100644 -index 0000000..6e4b3da ---- /dev/null -+++ b/target/linux/generic/patches-3.18/672-ipv6-fix-crash-on-ICMPv6-redirects-with-prohibited-blackholed-source.patch -@@ -0,0 +1,39 @@ -+From 7426eb388ade0f1ad800c408d7efa227d4f41408 Mon Sep 17 00:00:00 2001 -+Message-Id: <7426eb388ade0f1ad800c408d7efa227d4f41408.1446425986.git.mschiffer@universe-factory.net> -+From: Matthias Schiffer -+Date: Mon, 2 Nov 2015 01:05:15 +0100 -+Subject: [PATCH] ipv6: fix crash on ICMPv6 redirects with -+ prohibited/blackholed source -+ -+There are other error values besides ip6_null_entry that can be returned by -+ip6_route_redirect(): fib6_rule_action() can also result in -+ip6_blk_hole_entry and ip6_prohibit_entry if such ip rules are installed. -+ -+Only checking for ip6_null_entry in rt6_do_redirect() causes ip6_ins_rt() -+to be called with rt->rt6i_table == NULL in these cases, making the kernel -+crash. -+ -+Signed-off-by: Matthias Schiffer -+--- -+ net/ipv6/route.c | 3 +-- -+ 1 file changed, 1 insertion(+), 2 deletions(-) -+ -+--- a/net/ipv6/route.c -++++ b/net/ipv6/route.c -+@@ -1766,7 +1766,6 @@ static int ip6_route_del(struct fib6_con -+ -+ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb) -+ { -+- struct net *net = dev_net(skb->dev); -+ struct netevent_redirect netevent; -+ struct rt6_info *rt, *nrt = NULL; -+ struct ndisc_options ndopts; -+@@ -1827,7 +1826,7 @@ static void rt6_do_redirect(struct dst_e -+ } -+ -+ rt = (struct rt6_info *) dst; -+- if (rt == net->ipv6.ip6_null_entry) { -++ if (rt->rt6i_flags & RTF_REJECT) { -+ net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n"); -+ return; -+ } diff --git a/patches/openwrt/0012-lua-fix-installation-of-headers-for-host-build.patch b/patches/openwrt/0012-lua-fix-installation-of-headers-for-host-build.patch deleted file mode 100644 index ab49ad65..00000000 --- a/patches/openwrt/0012-lua-fix-installation-of-headers-for-host-build.patch +++ /dev/null @@ -1,16 +0,0 @@ -From: Matthias Schiffer -Date: Tue, 29 Dec 2015 22:48:52 +0100 -Subject: lua: fix installation of headers for host build - -diff --git a/package/utils/lua/Makefile b/package/utils/lua/Makefile -index 72d5631..c37d99b 100644 ---- a/package/utils/lua/Makefile -+++ b/package/utils/lua/Makefile -@@ -140,6 +140,7 @@ define Host/Install - $(MAKE) -C $(HOST_BUILD_DIR) \ - INSTALL_TOP="$(STAGING_DIR_HOST)" \ - install -+ $(CP) $(HOST_BUILD_DIR)/src/lnum_config.h $(STAGING_DIR_HOST)/include/ - endef - - define Build/InstallDev diff --git a/patches/openwrt/0013-kernel-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-processes.patch b/patches/openwrt/0013-kernel-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-processes.patch deleted file mode 100644 index 72ad4f7d..00000000 --- a/patches/openwrt/0013-kernel-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-processes.patch +++ /dev/null @@ -1,63 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 4 Jan 2016 10:22:52 +0100 -Subject: kernel: fs, seq_file: fallback to vmalloc instead of oom kill processes - -diff --git a/target/linux/generic/patches-3.18/089-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-.patch b/target/linux/generic/patches-3.18/089-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-.patch -new file mode 100644 -index 0000000..cad56f4 ---- /dev/null -+++ b/target/linux/generic/patches-3.18/089-fs-seq_file-fallback-to-vmalloc-instead-of-oom-kill-.patch -@@ -0,0 +1,53 @@ -+From 5cec38ac866bfb8775638e71a86e4d8cac30caae Mon Sep 17 00:00:00 2001 -+Message-Id: <5cec38ac866bfb8775638e71a86e4d8cac30caae.1451899087.git.mschiffer@universe-factory.net> -+From: David Rientjes -+Date: Fri, 12 Dec 2014 16:56:16 -0800 -+Subject: [PATCH] fs, seq_file: fallback to vmalloc instead of oom kill -+ processes -+ -+Since commit 058504edd026 ("fs/seq_file: fallback to vmalloc allocation"), -+seq_buf_alloc() falls back to vmalloc() when the kmalloc() for contiguous -+memory fails. This was done to address order-4 slab allocations for -+reading /proc/stat on large machines and noticed because -+PAGE_ALLOC_COSTLY_ORDER < 4, so there is no infinite loop in the page -+allocator when allocating new slab for such high-order allocations. -+ -+Contiguous memory isn't necessary for caller of seq_buf_alloc(), however. -+Other GFP_KERNEL high-order allocations that are <= -+PAGE_ALLOC_COSTLY_ORDER will simply loop forever in the page allocator and -+oom kill processes as a result. -+ -+We don't want to kill processes so that we can allocate contiguous memory -+in situations when contiguous memory isn't necessary. -+ -+This patch does the kmalloc() allocation with __GFP_NORETRY for high-order -+allocations. This still utilizes memory compaction and direct reclaim in -+the allocation path, the only difference is that it will fail immediately -+instead of oom kill processes when out of memory. -+ -+[akpm@linux-foundation.org: add comment] -+Signed-off-by: David Rientjes -+Cc: Heiko Carstens -+Cc: Christoph Hellwig -+Cc: Al Viro -+Signed-off-by: Andrew Morton -+Signed-off-by: Linus Torvalds -+--- -+ fs/seq_file.c | 6 +++++- -+ 1 file changed, 5 insertions(+), 1 deletion(-) -+ -+--- a/fs/seq_file.c -++++ b/fs/seq_file.c -+@@ -36,7 +36,11 @@ static void *seq_buf_alloc(unsigned long -+ { -+ void *buf; -+ -+- buf = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); -++ /* -++ * __GFP_NORETRY to avoid oom-killings with high-order allocations - -++ * it's better to fall back to vmalloc() than to kill things. -++ */ -++ buf = kmalloc(size, GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); -+ if (!buf && size > PAGE_SIZE) -+ buf = vmalloc(size); -+ return buf; diff --git a/patches/openwrt/0014-fix-UBNT-XM-model-detection.patch b/patches/openwrt/0014-fix-UBNT-XM-model-detection.patch deleted file mode 100644 index 08240588..00000000 --- a/patches/openwrt/0014-fix-UBNT-XM-model-detection.patch +++ /dev/null @@ -1,74 +0,0 @@ -From: Neal Oakey -Date: Sun, 14 Feb 2016 20:58:20 +0100 -Subject: fix UBNT XM model detection - -Signed-off-by: Neal Oakey - -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index dab4d2c..e7b3cd2 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -64,6 +64,40 @@ wndr3700_board_detect() { - AR71XX_MODEL="$machine" - } - -+ubnt_get_mtd_part_magic() { -+ ar71xx_get_mtd_offset_size_format EEPROM 4118 2 %02x -+} -+ -+ubnt_xm_board_detect() { -+ local model -+ local magic -+ -+ magic="$(ubnt_get_mtd_part_magic)" -+ case ${magic:0:3} in -+ "e00"|\ -+ "e01"|\ -+ "e80") # It seams that there are different Versions of the Nanostation -+ model="Ubiquiti NanoStation M" -+ ;; -+ "e0a") -+ model="Ubiquiti NanoStation loco M" -+ ;; -+ "e1b") # Note: the M5 has not been tested! -+ # and the Ti Versions are still missing -+ model="Ubiquiti Rocket M" -+ ;; -+ "e20"|\ -+ "e2d") # Bullet Ti M -+ model="Ubiquiti Bullet M" -+ ;; -+ "e30") -+ model="Ubiquiti PicoStation M" -+ ;; -+ esac -+ -+ [ ! -z "$model" ] && AR71XX_MODEL="${model}${magic:3:1}" -+} -+ - cybertan_get_hw_magic() { - local part - -@@ -475,12 +509,14 @@ ar71xx_board_detect() { - ;; - *"Bullet M") - name="bullet-m" -+ ubnt_xm_board_detect - ;; - *"Loco M XW") - name="loco-m-xw" - ;; - *"Nanostation M") - name="nanostation-m" -+ ubnt_xm_board_detect - ;; - *"Nanostation M XW") - name="nanostation-m-xw" -@@ -667,6 +703,7 @@ ar71xx_board_detect() { - ;; - *"Rocket M") - name="rocket-m" -+ ubnt_xm_board_detect - ;; - *"Rocket M XW") - name="rocket-m-xw" diff --git a/patches/openwrt/0015-base-files-implemented-basic-GPIO-control.patch b/patches/openwrt/0015-base-files-implemented-basic-GPIO-control.patch deleted file mode 100644 index c3f6c8d5..00000000 --- a/patches/openwrt/0015-base-files-implemented-basic-GPIO-control.patch +++ /dev/null @@ -1,133 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 7 Mar 2016 06:07:21 +0100 -Subject: base-files: implemented basic GPIO control - -Internal GPIO pins are used for PoE passthrough setups in multi-port -routers. This patch implemnets control over this hardware feature for -Ubiquiti Nanostations and TP-Link CPE510. - -Signed-off-by: Lars Kruse - -Backport of r46271 - -diff --git a/package/base-files/files/etc/init.d/gpio_switch b/package/base-files/files/etc/init.d/gpio_switch -new file mode 100755 -index 0000000..1f1b44b ---- /dev/null -+++ b/package/base-files/files/etc/init.d/gpio_switch -@@ -0,0 +1,42 @@ -+#!/bin/sh /etc/rc.common -+# Copyright (C) 2015 OpenWrt.org -+ -+START=98 -+STOP=10 -+USE_PROCD=1 -+ -+ -+load_gpio_switch() -+{ -+ local name -+ local gpio_pin -+ local value -+ -+ config_get gpio_pin "$1" gpio_pin -+ config_get name "$1" name -+ config_get value "$1" value 0 -+ -+ local gpio_path="/sys/class/gpio/gpio${gpio_pin}" -+ # export GPIO pin for access -+ [ -d "$gpio_path" ] || { -+ echo "$gpio_pin" >/sys/class/gpio/export -+ # we need to wait a bit until the GPIO appears -+ [ -d "$gpio_path" ] || sleep 1 -+ echo out >"$gpio_path/direction" -+ } -+ # write 0 or 1 to the "value" field -+ { [ "$value" = "0" ] && echo "0" || echo "1"; } >"$gpio_path/value" -+} -+ -+service_triggers() -+{ -+ procd_add_reload_trigger "system" -+} -+ -+start_service() -+{ -+ [ -e /sys/class/gpio/ ] && { -+ config_load system -+ config_foreach load_gpio_switch gpio_switch -+ } -+} -diff --git a/package/base-files/files/lib/functions/uci-defaults.sh b/package/base-files/files/lib/functions/uci-defaults.sh -index 5a8809d..6577ecd 100644 ---- a/package/base-files/files/lib/functions/uci-defaults.sh -+++ b/package/base-files/files/lib/functions/uci-defaults.sh -@@ -2,6 +2,7 @@ - # Copyright (C) 2011 OpenWrt.org - - UCIDEF_LEDS_CHANGED=0 -+UCIDEF_GPIO_SWITCHES_CHANGED=0 - - ucidef_set_led_netdev() { - local cfg="led_$1" -@@ -180,6 +181,29 @@ ucidef_commit_leds() - [ "$UCIDEF_LEDS_CHANGED" = "1" ] && uci commit system - } - -+ucidef_set_gpio_switch() { -+ local cfg="gpio_switch_$1" -+ local name="$2" -+ local gpio_pin="$3" -+ # use "0" as default value -+ local default="${4:-0}" -+ -+ uci -q get "system.$cfg" && return 0 -+ -+ uci batch < -Date: Mon, 7 Mar 2016 06:07:59 +0100 -Subject: ar71xx: assign proper GPIO pin for Ubiquiti Nanostation models - -The GPIO pins for "POE passthrough" of Ubiquiti Nanostation models are the -following: -* Ubiquiti Nanostation M XM: Pin 8 -* Ubiquiti Nanostation M XW: Pin 2 - -The previous definition of the pins was mixed up between XM and XW model. - -Signed-off-by: Lars Kruse - -Backport of r46922 - -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_gpio-switches b/target/linux/ar71xx/base-files/etc/uci-defaults/01_gpio-switches -index 81d3982..b41f275 100644 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_gpio-switches -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_gpio-switches -@@ -10,10 +10,10 @@ board=$(ar71xx_board_name) - - case "$board" in - nanostation-m) -- ucidef_set_gpio_switch "poe_passthrough" "PoE Passthrough" "2" -+ ucidef_set_gpio_switch "poe_passthrough" "PoE Passthrough" "8" - ;; - nanostation-m-xw) -- ucidef_set_gpio_switch "poe_passthrough" "PoE Passthrough" "8" -+ ucidef_set_gpio_switch "poe_passthrough" "PoE Passthrough" "2" - ;; - cpe510) - ucidef_set_gpio_switch "poe_passthrough" "PoE Passthrough" "20" diff --git a/patches/openwrt/0017-netifd-update-to-latest-git-master.patch b/patches/openwrt/0017-netifd-update-to-latest-git-master.patch deleted file mode 100644 index 8128cfb0..00000000 --- a/patches/openwrt/0017-netifd-update-to-latest-git-master.patch +++ /dev/null @@ -1,182 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 9 Mar 2016 06:46:44 +0100 -Subject: netifd: update to latest git master - -diff --git a/package/network/config/netifd/Makefile b/package/network/config/netifd/Makefile -index 619024b..84a4592 100644 ---- a/package/network/config/netifd/Makefile -+++ b/package/network/config/netifd/Makefile -@@ -1,13 +1,13 @@ - include $(TOPDIR)/rules.mk - - PKG_NAME:=netifd --PKG_VERSION:=2015-12-16 -+PKG_VERSION:=2016-03-31 - PKG_RELEASE=$(PKG_SOURCE_VERSION) - - PKG_SOURCE_PROTO:=git --PKG_SOURCE_URL:=http://git.openwrt.org/project/netifd.git -+PKG_SOURCE_URL=$(OPENWRT_GIT)/project/netifd.git - PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) --PKG_SOURCE_VERSION:=245527193e90906451be35c2b8e972b8712ea6ab -+PKG_SOURCE_VERSION:=6fd6be6b7f3fc4883fdc464fcbcb2b5e8d8e8174 - PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz - PKG_MAINTAINER:=Felix Fietkau - # PKG_MIRROR_MD5SUM:= -diff --git a/package/network/config/netifd/files/etc/init.d/network b/package/network/config/netifd/files/etc/init.d/network -index 542fc08..bdadbbc 100755 ---- a/package/network/config/netifd/files/etc/init.d/network -+++ b/package/network/config/netifd/files/etc/init.d/network -@@ -21,7 +21,6 @@ start_service() { - procd_set_param watch network.interface - [ -e /proc/sys/kernel/core_pattern ] && { - procd_set_param limits core="unlimited" -- echo '/tmp/%e.%p.%s.%t.core' > /proc/sys/kernel/core_pattern - } - procd_close_instance - } -diff --git a/package/network/config/netifd/files/sbin/ifup b/package/network/config/netifd/files/sbin/ifup -index af3aaa8..5515b91 100755 ---- a/package/network/config/netifd/files/sbin/ifup -+++ b/package/network/config/netifd/files/sbin/ifup -@@ -67,12 +67,10 @@ if [ -n "$setup_wifi" ] && grep -sq config /etc/config/wireless; then - fi - } - -- local radio_devs -- local network="$1" -+ network="$1" - config_load wireless - config_foreach find_related_radios wifi-iface - -- local dev - for dev in $(echo "$radio_devs" | sort -u); do - /sbin/wifi up "$dev" - done -diff --git a/package/network/config/netifd/patches/0001-Revert-device-Don-t-process-link-events-anymore-in-d.patch b/package/network/config/netifd/patches/0001-Revert-device-Don-t-process-link-events-anymore-in-d.patch -new file mode 100644 -index 0000000..312964f ---- /dev/null -+++ b/package/network/config/netifd/patches/0001-Revert-device-Don-t-process-link-events-anymore-in-d.patch -@@ -0,0 +1,121 @@ -+From e0f19fdae88f3ef505e22533915f8328f4793980 Mon Sep 17 00:00:00 2001 -+Message-Id: -+From: Matthias Schiffer -+Date: Thu, 5 May 2016 21:49:33 +0200 -+Subject: [PATCH] Revert "device: Don't process link events anymore in device -+ user specific callback handlers" -+ -+This reverts commit 4902ba2999dec02e82066d70ab6096b852a33007. -+--- -+ device.h | 2 ++ -+ macvlan.c | 8 ++++++++ -+ system-linux.c | 2 +- -+ vlan.c | 6 ++++++ -+ vlandev.c | 8 ++++++++ -+ 5 files changed, 25 insertions(+), 1 deletion(-) -+ -+diff --git a/device.h b/device.h -+index ac77cfb..ef1c608 100644 -+--- a/device.h -++++ b/device.h -+@@ -59,6 +59,8 @@ struct device_type { -+ struct list_head list; -+ const char *name; -+ -++ bool keep_link_status; -++ -+ const struct uci_blob_param_list *config_params; -+ -+ struct device *(*create)(const char *name, struct blob_attr *attr); -+diff --git a/macvlan.c b/macvlan.c -+index a0f11ae..051fe05 100644 -+--- a/macvlan.c -++++ b/macvlan.c -+@@ -72,6 +72,12 @@ macvlan_base_cb(struct device_user *dev, enum device_event ev) -+ case DEV_EVENT_REMOVE: -+ device_set_present(&mvdev->dev, false); -+ break; -++ case DEV_EVENT_LINK_UP: -++ device_set_link(&mvdev->dev, true); -++ break; -++ case DEV_EVENT_LINK_DOWN: -++ device_set_link(&mvdev->dev, false); -++ break; -+ default: -+ return; -+ } -+@@ -255,6 +261,8 @@ macvlan_create(const char *name, struct blob_attr *attr) -+ const struct device_type macvlan_device_type = { -+ .name = "MAC VLAN", -+ .config_params = &macvlan_attr_list, -++ .keep_link_status = true, -++ -+ .create = macvlan_create, -+ .config_init = macvlan_config_init, -+ .reload = macvlan_reload, -+diff --git a/system-linux.c b/system-linux.c -+index 351a994..794c1dd 100644 -+--- a/system-linux.c -++++ b/system-linux.c -+@@ -464,7 +464,7 @@ static int cb_rtnl_event(struct nl_msg *msg, void *arg) -+ goto out; -+ -+ struct device *dev = device_get(nla_data(nla[IFLA_IFNAME]), false); -+- if (!dev) -++ if (!dev || dev->type->keep_link_status) -+ goto out; -+ -+ if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf))) -+diff --git a/vlan.c b/vlan.c -+index ac434ce..8d93799 100644 -+--- a/vlan.c -++++ b/vlan.c -+@@ -79,6 +79,11 @@ static void vlan_dev_cb(struct device_user *dep, enum device_event ev) -+ case DEV_EVENT_REMOVE: -+ device_set_present(&vldev->dev, new_state); -+ break; -++ case DEV_EVENT_LINK_UP: -++ new_state = true; -++ case DEV_EVENT_LINK_DOWN: -++ device_set_link(&vldev->dev, new_state); -++ break; -+ case DEV_EVENT_UPDATE_IFNAME: -+ vlan_dev_set_name(vldev, dep->dev); -+ device_broadcast_event(&vldev->dev, ev); -+@@ -97,6 +102,7 @@ static struct device *get_vlan_device(struct device *dev, int id, bool create) -+ static const struct device_type vlan_type = { -+ .name = "VLAN", -+ .config_params = &device_attr_list, -++ .keep_link_status = true, -+ .free = free_vlan_if, -+ }; -+ struct vlan_device *vldev; -+diff --git a/vlandev.c b/vlandev.c -+index b93527c..884e6ef 100644 -+--- a/vlandev.c -++++ b/vlandev.c -+@@ -63,6 +63,12 @@ vlandev_base_cb(struct device_user *dev, enum device_event ev) -+ case DEV_EVENT_REMOVE: -+ device_set_present(&mvdev->dev, false); -+ break; -++ case DEV_EVENT_LINK_UP: -++ device_set_link(&mvdev->dev, true); -++ break; -++ case DEV_EVENT_LINK_DOWN: -++ device_set_link(&mvdev->dev, false); -++ break; -+ default: -+ return; -+ } -+@@ -243,6 +249,8 @@ vlandev_create(const char *name, struct blob_attr *attr) -+ const struct device_type vlandev_device_type = { -+ .name = "VLANDEV", -+ .config_params = &vlandev_attr_list, -++ .keep_link_status = true, -++ -+ .create = vlandev_create, -+ .config_init = vlandev_config_init, -+ .reload = vlandev_reload, -+-- -+2.8.2 -+ diff --git a/patches/openwrt/0018-x86-fix-platform_export_bootpart-for-Xen-virtual-disks.patch b/patches/openwrt/0018-x86-fix-platform_export_bootpart-for-Xen-virtual-disks.patch deleted file mode 100644 index 4e0ce138..00000000 --- a/patches/openwrt/0018-x86-fix-platform_export_bootpart-for-Xen-virtual-disks.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Alexander Dahl -Date: Thu, 17 Mar 2016 15:04:09 +0100 -Subject: x86: fix platform_export_bootpart() for Xen virtual disks - -Virtual disk devices in a Xen virtual machine (DomU) can be /dev/xvda, -/dev/xvdb and so on with partitions like /dev/xdva1. Devices named like -this where not considered before. This resulted in a non working -sysupgrade, because the boot partition could not be found. - -Signed-off-by: Alexander Dahl -Suggested-by: Matthias Schiffer - -diff --git a/target/linux/x86/base-files/lib/upgrade/platform.sh b/target/linux/x86/base-files/lib/upgrade/platform.sh -index 73ab5ef..adc119c 100644 ---- a/target/linux/x86/base-files/lib/upgrade/platform.sh -+++ b/target/linux/x86/base-files/lib/upgrade/platform.sh -@@ -17,7 +17,7 @@ platform_export_bootpart() { - PARTUUID=[a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9][a-f0-9]-02) - uuid="${disk#PARTUUID=}" - uuid="${uuid%-02}" -- for disk in /dev/[hsv]d[a-z]; do -+ for disk in /dev/[hsv]d[a-z] /dev/xvd[a-z]; do - set -- $(dd if=$disk bs=1 skip=440 count=4 2>/dev/null | hexdump -v -e '4/1 "%02x "') - if [ "$4$3$2$1" = "$uuid" ]; then - export BOOTPART="${disk}1" diff --git a/patches/openwrt/0019-Support-LibreSSL-as-provider-of-openssl.patch b/patches/openwrt/0019-Support-LibreSSL-as-provider-of-openssl.patch deleted file mode 100644 index cf627622..00000000 --- a/patches/openwrt/0019-Support-LibreSSL-as-provider-of-openssl.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 30 Mar 2016 02:59:19 +0200 -Subject: Support LibreSSL as provider of openssl - -The build scripts check for openssl by grepping the string "OpenSSL" in -the output of openssl version command. LibreSSL fails this test as it -outputs something like "LibreSSL 2.2.4". This patch fix the -prereq-bulid.mk file so that it accepts LibreSSL as openssl provider as -well. - -Signed-off-by: Marek Behun - -Backport of r48267 - -diff --git a/include/prereq-build.mk b/include/prereq-build.mk -index 32c4ada..f36d57c 100644 ---- a/include/prereq-build.mk -+++ b/include/prereq-build.mk -@@ -151,7 +151,7 @@ $(eval $(call SetupHostCommand,file,Please install the 'file' package, \ - file --version 2>&1 | grep file)) - - $(eval $(call SetupHostCommand,openssl,Please install the 'openssl' utility, \ -- openssl version | grep OpenSSL)) -+ openssl version | grep '\(OpenSSL\|LibreSSL\)')) - - - # Install ldconfig stub diff --git a/patches/openwrt/0020-ar71xx-check-both-HWID-and-HWREV-on-upgrades-of-TP-LINK-devices.patch b/patches/openwrt/0020-ar71xx-check-both-HWID-and-HWREV-on-upgrades-of-TP-LINK-devices.patch deleted file mode 100644 index 77b47675..00000000 --- a/patches/openwrt/0020-ar71xx-check-both-HWID-and-HWREV-on-upgrades-of-TP-LINK-devices.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 1 Apr 2016 23:16:13 +0200 -Subject: ar71xx: check both HWID and HWREV on upgrades of TP-LINK devices - -There's no reason for us to be more lenient than the stock firmware, so -better check the HWREV as well to avoid bricked devices. - -Signed-off-by: Matthias Schiffer - -Backport of r49105 - -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index d025632..c5c1871 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -66,6 +66,10 @@ tplink_get_image_hwid() { - get_image "$@" | dd bs=4 count=1 skip=16 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' - } - -+tplink_get_image_mid() { -+ get_image "$@" | dd bs=4 count=1 skip=17 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' -+} -+ - tplink_get_image_boot_size() { - get_image "$@" | dd bs=4 count=1 skip=37 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' - } -@@ -366,13 +370,17 @@ platform_check_image() { - } - - local hwid -- local imageid -+ local mid -+ local imagehwid -+ local imagemid - - hwid=$(tplink_get_hwid) -- imageid=$(tplink_get_image_hwid "$1") -+ mid=$(tplink_get_mid) -+ imagehwid=$(tplink_get_image_hwid "$1") -+ imagemid=$(tplink_get_image_mid "$1") - -- [ "$hwid" != "$imageid" ] && { -- echo "Invalid image, hardware ID mismatch, hw:$hwid image:$imageid." -+ [ "$hwid" != "$imagehwid" -o "$mid" != "$imagemid" ] && { -+ echo "Invalid image, hardware ID mismatch, hw:$hwid $mid image:$imagehwid $imagemid." - return 1 - } - diff --git a/patches/openwrt/0021-ar71xx-avoid-AR71XX_MODEL-ending-with-a-space-on-some-TP-LINK-like-devices.patch b/patches/openwrt/0021-ar71xx-avoid-AR71XX_MODEL-ending-with-a-space-on-some-TP-LINK-like-devices.patch deleted file mode 100644 index 70b3a004..00000000 --- a/patches/openwrt/0021-ar71xx-avoid-AR71XX_MODEL-ending-with-a-space-on-some-TP-LINK-like-devices.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 1 Apr 2016 23:19:16 +0200 -Subject: ar71xx: avoid AR71XX_MODEL ending with a space on some TP-LINK-like devices - -Instead of adding the space when combining $model and $hwver, add the space -to the beginning of $hwver, so the resulting string won't end with a space -when $hwver is set to the empty string. - -Signed-off-by: Matthias Schiffer - -Backport of r49106 - -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index e7b3cd2..180a075 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -133,7 +133,7 @@ tplink_board_detect() { - hwid=$(tplink_get_hwid) - mid=$(tplink_get_mid) - hwver=${hwid:6:2} -- hwver="v${hwver#0}" -+ hwver=" v${hwver#0}" - - case "$hwid" in - "015000"*) -@@ -196,8 +196,8 @@ tplink_board_detect() { - "083000"*) - model="TP-Link TL-WA830RE" - -- if [ "$hwver" = 'v10' ]; then -- hwver='v1' -+ if [ "$hwver" = ' v10' ]; then -+ hwver=' v1' - fi - ;; - "084100"*) -@@ -296,7 +296,7 @@ tplink_board_detect() { - ;; - esac - -- AR71XX_MODEL="$model $hwver" -+ AR71XX_MODEL="$model$hwver" - } - - tplink_pharos_get_model_string() { diff --git a/patches/openwrt/0022-ar71xx-fix-the-revision-of-a-few-TP-LINK-devices-in-AR71XX_MODEL-to-match-labels-image-names.patch b/patches/openwrt/0022-ar71xx-fix-the-revision-of-a-few-TP-LINK-devices-in-AR71XX_MODEL-to-match-labels-image-names.patch deleted file mode 100644 index 9330e547..00000000 --- a/patches/openwrt/0022-ar71xx-fix-the-revision-of-a-few-TP-LINK-devices-in-AR71XX_MODEL-to-match-labels-image-names.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 1 Apr 2016 23:21:32 +0200 -Subject: ar71xx: fix the revision of a few TP-LINK devices in AR71XX_MODEL to match labels/image names - -Let's not confuse users about the revisions of their devices when we can -easily avoid it. - -Not tested on real hardware. - -Signed-off-by: Matthias Schiffer - -Backport of r49107 - -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index 180a075..ddd6611 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -162,6 +162,10 @@ tplink_board_detect() { - ;; - "071000"*) - model="TP-Link TL-WR710N" -+ -+ if [ "$hwid" = '07100002' -a "$mid" = '00000002' ]; then -+ hwver=' v2.1' -+ fi - ;; - "072001"*) - model="TP-Link TL-WR720N" -@@ -202,6 +206,10 @@ tplink_board_detect() { - ;; - "084100"*) - model="TP-Link TL-WR841N/ND" -+ -+ if [ "$hwid" = '08410002' -a "$mid" = '00000002' ]; then -+ hwver=' v1.5' -+ fi - ;; - "084200"*) - model="TP-Link TL-WR842N/ND" diff --git a/patches/openwrt/0023-ar71xx-build-image-for-TL-WR710N-v2.1.patch b/patches/openwrt/0023-ar71xx-build-image-for-TL-WR710N-v2.1.patch deleted file mode 100644 index 5a225d7d..00000000 --- a/patches/openwrt/0023-ar71xx-build-image-for-TL-WR710N-v2.1.patch +++ /dev/null @@ -1,41 +0,0 @@ -From: Matthias Schiffer -Date: Sat, 2 Apr 2016 00:56:50 +0200 -Subject: ar71xx: build image for TL-WR710N v2.1 - -This patch just extends target/linux/ar71xx/image/Makefile to build -images also for version 2.1 of TL-WR710N -patch against the latest git - -Signed off by: Norbert Wegener - -Backport of r47849 - -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index 9a7acbd..d42ceef 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -476,6 +476,15 @@ define Device/tl-wr710n-v2 - CONSOLE := ttyATH0,115200 - endef - -+define Device/tl-wr710n-v2.1 -+ $(Device/tplink-8mlzma) -+ BOARDNAME := TL-WR710N -+ DEVICE_PROFILE := TLWR710 -+ TPLINK_HWID := 0x07100002 -+ TPLINK_HWREV := 0x00000002 -+ CONSOLE := ttyATH0,115200 -+endef -+ - define Device/tl-wr720n-v3 - $(Device/tplink-4mlzma) - BOARDNAME := TL-WR720N-v3 -@@ -491,7 +500,7 @@ define Device/tl-wr720n-v4 - TPLINK_HWID := 0x07200104 - CONSOLE := ttyATH0,115200 - endef --TARGET_DEVICES += tl-wr703n-v1 tl-wr710n-v1 tl-wr710n-v2 tl-wr720n-v3 tl-wr720n-v4 -+TARGET_DEVICES += tl-wr703n-v1 tl-wr710n-v1 tl-wr710n-v2 tl-wr710n-v2.1 tl-wr720n-v3 tl-wr720n-v4 - - define Device/tl-wr740n-v4 - $(Device/tplink-4mlzma) diff --git a/patches/openwrt/0024-xtables-addons-build-fix-configure-compatiblity-with-POSIX-shells.patch b/patches/openwrt/0024-xtables-addons-build-fix-configure-compatiblity-with-POSIX-shells.patch deleted file mode 100644 index fa4b76a5..00000000 --- a/patches/openwrt/0024-xtables-addons-build-fix-configure-compatiblity-with-POSIX-shells.patch +++ /dev/null @@ -1,2026 +0,0 @@ -From: Matthias Schiffer -Date: Tue, 5 Apr 2016 20:30:56 +0200 -Subject: xtables-addons: build: fix configure compatiblity with POSIX shells - -diff --git a/package/network/utils/xtables-addons/patches/001-build-fix-configure-compatiblity-with-POSIX-shells.patch b/package/network/utils/xtables-addons/patches/001-build-fix-configure-compatiblity-with-POSIX-shells.patch -new file mode 100644 -index 0000000..e0b11b5 ---- /dev/null -+++ b/package/network/utils/xtables-addons/patches/001-build-fix-configure-compatiblity-with-POSIX-shells.patch -@@ -0,0 +1,51 @@ -+From f07a0a5cb8b3c5e1aee8b30c7fa21ccfbf24a95a Mon Sep 17 00:00:00 2001 -+Message-Id: -+From: Matthias Schiffer -+Date: Fri, 1 Apr 2016 22:24:00 +0200 -+Subject: [PATCH] build: fix configure compatiblity with POSIX shells -+ -+The kernel version detection code uses some bashisms, which makes the build -+fail on Debian systems where /bin/sh links to dash. Replace with POSIX- -+conforming commands at the cost of requiring awk. -+--- -+ configure.ac | 24 +++++++++--------------- -+ 1 file changed, 9 insertions(+), 15 deletions(-) -+ -+diff --git a/configure.ac b/configure.ac -+index 82a1355..5a5ea57 100644 -+--- a/configure.ac -++++ b/configure.ac -+@@ -44,21 +44,15 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ -+ -+ if test -n "$kbuilddir"; then -+ AC_MSG_CHECKING([kernel version that we will build against]) -+- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)"; -+- kmajor="${krel%%[[^0-9]]*}"; -+- kmajor="$(($kmajor+0))"; -+- krel="${krel:${#kmajor}}"; -+- krel="${krel#.}"; -+- kminor="${krel%%[[^0-9]]*}"; -+- kminor="$(($kminor+0))"; -+- krel="${krel:${#kminor}}"; -+- krel="${krel#.}"; -+- kmicro="${krel%%[[^0-9]]*}"; -+- kmicro="$(($kmicro+0))"; -+- krel="${krel:${#kmicro}}"; -+- krel="${krel#.}"; -+- kstable="${krel%%[[^0-9]]*}"; -+- kstable="$(($kstable+0))"; -++ krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')"; -++ save_IFS=$IFS; -++ IFS='.'; -++ set x $krel; -++ IFS=$save_IFS; -++ kmajor="$(($2+0))"; -++ kminor="$(($3+0))"; -++ kmicro="$(($4+0))"; -++ kstable="$(($5+0))"; -+ if test -z "$kmajor" -o -z "$kminor" -o -z "$kmicro"; then -+ echo "WARNING: Version detection did not succeed. Continue at own luck."; -+ else -+-- -+2.8.0 -+ -diff --git a/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch b/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch -index d3b7caa..6a7a099 100644 ---- a/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch -+++ b/package/network/utils/xtables-addons/patches/002-fix-kernel-version-detection.patch -@@ -1,1954 +1,11 @@ ----- a/configure --+++ b/configure --@@ -1,9 +1,11 @@ -- #! /bin/sh -- # Guess values for system-dependent variables and create Makefiles. ---# Generated by GNU Autoconf 2.69 for xtables-addons 2.5. --+# Generated by GNU Autoconf 2.68 for xtables-addons 2.5. -- # -- # ---# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. --+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, --+# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software --+# Foundation, Inc. -- # -- # -- # This configure script is free software; the Free Software Foundation --@@ -132,31 +134,6 @@ export LANGUAGE -- # CDPATH. -- (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -- ---# Use a proper internal environment variable to ensure we don't fall --- # into an infinite loop, continuously re-executing ourselves. --- if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then --- _as_can_reexec=no; export _as_can_reexec; --- # We cannot yet assume a decent shell, so we have to provide a ---# neutralization value for shells without unset; and this also ---# works around shells that cannot unset nonexistent variables. ---# Preserve -v and -x to the replacement shell. ---BASH_ENV=/dev/null ---ENV=/dev/null ---(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV ---case $- in # (((( --- *v*x* | *x*v* ) as_opts=-vx ;; --- *v* ) as_opts=-v ;; --- *x* ) as_opts=-x ;; --- * ) as_opts= ;; ---esac ---exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} ---# Admittedly, this is quite paranoid, since all the known shells bail ---# out after a failed `exec'. ---$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 ---as_fn_exit 255 --- fi --- # We don't want this to propagate to other subprocesses. --- { _as_can_reexec=; unset _as_can_reexec;} -- if test "x$CONFIG_SHELL" = x; then -- as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : -- emulate sh --@@ -190,8 +167,7 @@ if ( set x; as_fn_ret_success y && test -- else -- exitcode=1; echo positional parameters were not saved. -- fi ---test x\$exitcode = x0 || exit 1 ---test -x / || exit 1" --+test x\$exitcode = x0 || exit 1" -- as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO -- as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO -- eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && --@@ -244,25 +220,21 @@ IFS=$as_save_IFS -- -- -- if test "x$CONFIG_SHELL" != x; then : --- export CONFIG_SHELL --- # We cannot yet assume a decent shell, so we have to provide a ---# neutralization value for shells without unset; and this also ---# works around shells that cannot unset nonexistent variables. ---# Preserve -v and -x to the replacement shell. ---BASH_ENV=/dev/null ---ENV=/dev/null ---(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV ---case $- in # (((( --- *v*x* | *x*v* ) as_opts=-vx ;; --- *v* ) as_opts=-v ;; --- *x* ) as_opts=-x ;; --- * ) as_opts= ;; ---esac ---exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} ---# Admittedly, this is quite paranoid, since all the known shells bail ---# out after a failed `exec'. ---$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 ---exit 255 --+ # We cannot yet assume a decent shell, so we have to provide a --+ # neutralization value for shells without unset; and this also --+ # works around shells that cannot unset nonexistent variables. --+ # Preserve -v and -x to the replacement shell. --+ BASH_ENV=/dev/null --+ ENV=/dev/null --+ (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV --+ export CONFIG_SHELL --+ case $- in # (((( --+ *v*x* | *x*v* ) as_opts=-vx ;; --+ *v* ) as_opts=-v ;; --+ *x* ) as_opts=-x ;; --+ * ) as_opts= ;; --+ esac --+ exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} -- fi -- -- if test x$as_have_required = xno; then : --@@ -364,14 +336,6 @@ $as_echo X"$as_dir" | -- -- -- } # as_fn_mkdir_p --- ---# as_fn_executable_p FILE ---# ----------------------- ---# Test if FILE is an executable regular file. ---as_fn_executable_p () ---{ --- test -f "$1" && test -x "$1" ---} # as_fn_executable_p -- # as_fn_append VAR VALUE -- # ---------------------- -- # Append the text in VALUE to the end of the definition contained in VAR. Take --@@ -493,10 +457,6 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits -- chmod +x "$as_me.lineno" || -- { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } -- --- # If we had to re-execute with $CONFIG_SHELL, we're ensured to have --- # already done that, so ensure we don't try to do so again and fall --- # in an infinite loop. This has already happened in practice. --- _as_can_reexec=no; export _as_can_reexec -- # Don't try to exec as it changes $[0], causing all sort of problems -- # (the dirname of $[0] is not the place where we might find the -- # original and so on. Autoconf is especially sensitive to this). --@@ -531,16 +491,16 @@ if (echo >conf$$.file) 2>/dev/null; then -- # ... but there are two gotchas: -- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. -- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. --- # In both cases, we have to default to `cp -pR'. --+ # In both cases, we have to default to `cp -p'. -- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- elif ln conf$$.file conf$$ 2>/dev/null; then -- as_ln_s=ln -- else --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- fi -- else --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- fi -- rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -- rmdir conf$$.dir 2>/dev/null --@@ -552,8 +512,28 @@ else -- as_mkdir_p=false -- fi -- ---as_test_x='test -x' ---as_executable_p=as_fn_executable_p --+if test -x / >/dev/null 2>&1; then --+ as_test_x='test -x' --+else --+ if ls -dL / >/dev/null 2>&1; then --+ as_ls_L_option=L --+ else --+ as_ls_L_option= --+ fi --+ as_test_x=' --+ eval sh -c '\'' --+ if test -d "$1"; then --+ test -d "$1/."; --+ else --+ case $1 in #( --+ -*)set "./$1";; --+ esac; --+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( --+ ???[sx]*):;;*)false;;esac;fi --+ '\'' sh --+ ' --+fi --+as_executable_p=$as_test_x -- -- # Sed expression to map a string onto a valid CPP name. -- as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" --@@ -688,10 +668,6 @@ CPPFLAGS -- LDFLAGS -- CFLAGS -- CC ---AM_BACKSLASH ---AM_DEFAULT_VERBOSITY ---AM_DEFAULT_V ---AM_V -- am__untar -- am__tar -- AMTAR --@@ -756,7 +732,6 @@ SHELL' -- ac_subst_files='' -- ac_user_opts=' -- enable_option_checking ---enable_silent_rules -- enable_dependency_tracking -- enable_static -- enable_shared --@@ -1237,6 +1212,8 @@ target=$target_alias -- if test "x$host_alias" != x; then -- if test "x$build_alias" = x; then -- cross_compiling=maybe --+ $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. --+ If a cross compiler is detected then cross compile mode will be used" >&2 -- elif test "x$build_alias" != "x$host_alias"; then -- cross_compiling=yes -- fi --@@ -1400,12 +1377,8 @@ Optional Features: -- --disable-option-checking ignore unrecognized --enable/--with options -- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) -- --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --- --enable-silent-rules less verbose build output (undo: "make V=1") --- --disable-silent-rules verbose build output (undo: "make V=0") --- --enable-dependency-tracking --- do not reject slow dependency extractors --- --disable-dependency-tracking --- speeds up one-time build --+ --disable-dependency-tracking speeds up one-time build --+ --enable-dependency-tracking do not reject slow dependency extractors -- --enable-static[=PKGS] build static libraries [default=no] -- --enable-shared[=PKGS] build shared libraries [default=yes] -- --enable-fast-install[=PKGS] --@@ -1415,7 +1388,7 @@ Optional Features: -- Optional Packages: -- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] -- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --- --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use --+ --with-pic try to use only PIC/non-PIC objects [default=use -- both] -- --with-gnu-ld assume the C compiler uses GNU ld [default=no] -- --with-sysroot=DIR Search for dependent libraries within DIR --@@ -1512,9 +1485,9 @@ test -n "$ac_init_help" && exit $ac_stat -- if $ac_init_version; then -- cat <<\_ACEOF -- xtables-addons configure 2.5 ---generated by GNU Autoconf 2.69 --+generated by GNU Autoconf 2.68 -- ---Copyright (C) 2012 Free Software Foundation, Inc. --+Copyright (C) 2010 Free Software Foundation, Inc. -- This configure script is free software; the Free Software Foundation -- gives unlimited permission to copy, distribute and modify it. -- _ACEOF --@@ -1590,7 +1563,7 @@ $as_echo "$ac_try_echo"; } >&5 -- test ! -s conftest.err -- } && test -s conftest$ac_exeext && { -- test "$cross_compiling" = yes || --- test -x conftest$ac_exeext --+ $as_test_x conftest$ac_exeext -- }; then : -- ac_retval=0 -- else --@@ -1877,7 +1850,7 @@ This file contains any messages produced -- running configure, to aid debugging if configure makes a mistake. -- -- It was created by xtables-addons $as_me 2.5, which was ---generated by GNU Autoconf 2.69. Invocation command line was --+generated by GNU Autoconf 2.68. Invocation command line was -- -- $ $0 $@ -- --@@ -2293,7 +2266,7 @@ case $as_dir/ in #(( -- # by default. -- for ac_prog in ginstall scoinst install; do -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then -- if test $ac_prog = install && -- grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then -- # AIX install. It has an incompatible calling convention. --@@ -2349,10 +2322,13 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCR -- -- test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' -- ---am__api_version='1.14' --+am__api_version='1.11' -- -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 -- $as_echo_n "checking whether build environment is sane... " >&6; } --+# Just in case --+sleep 1 --+echo timestamp > conftest.file -- # Reject unsafe characters in $srcdir or the absolute working directory -- # name. Accept space and tab only in the latter. -- am_lf=' --@@ -2363,40 +2339,32 @@ case `pwd` in -- esac -- case $srcdir in -- *[\\\"\#\$\&\'\`$am_lf\ \ ]*) --- as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; --+ as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; -- esac -- ---# Do 'set' in a subshell so we don't clobber the current shell's --+# Do `set' in a subshell so we don't clobber the current shell's -- # arguments. Must try -L first in case configure is actually a -- # symlink; some systems play weird games with the mod time of symlinks -- # (eg FreeBSD returns the mod time of the symlink's containing -- # directory). -- if ( --- am_has_slept=no --- for am_try in 1 2; do --- echo "timestamp, slept: $am_has_slept" > conftest.file --- set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` --- if test "$*" = "X"; then --- # -L didn't work. --- set X `ls -t "$srcdir/configure" conftest.file` --- fi --- if test "$*" != "X $srcdir/configure conftest.file" \ --- && test "$*" != "X conftest.file $srcdir/configure"; then --+ set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` --+ if test "$*" = "X"; then --+ # -L didn't work. --+ set X `ls -t "$srcdir/configure" conftest.file` --+ fi --+ rm -f conftest.file --+ if test "$*" != "X $srcdir/configure conftest.file" \ --+ && test "$*" != "X conftest.file $srcdir/configure"; then --+ --+ # If neither matched, then we have a broken ls. This can happen --+ # if, for instance, CONFIG_SHELL is bash and it inherits a --+ # broken ls alias from the environment. This has actually --+ # happened. Such a system could not be considered "sane". --+ as_fn_error $? "ls -t appears to fail. Make sure there is not a broken --+alias in your environment" "$LINENO" 5 --+ fi -- --- # If neither matched, then we have a broken ls. This can happen --- # if, for instance, CONFIG_SHELL is bash and it inherits a --- # broken ls alias from the environment. This has actually --- # happened. Such a system could not be considered "sane". --- as_fn_error $? "ls -t appears to fail. Make sure there is not a broken --- alias in your environment" "$LINENO" 5 --- fi --- if test "$2" = conftest.file || test $am_try -eq 2; then --- break --- fi --- # Just in case. --- sleep 1 --- am_has_slept=yes --- done -- test "$2" = conftest.file -- ) -- then --@@ -2408,16 +2376,6 @@ Check your system clock" "$LINENO" 5 -- fi -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -- $as_echo "yes" >&6; } ---# If we didn't sleep, we still need to ensure time stamps of config.status and ---# generated files are strictly newer. ---am_sleep_pid= ---if grep 'slept: no' conftest.file >/dev/null 2>&1; then --- ( sleep 1 ) & --- am_sleep_pid=$! ---fi --- ---rm -f conftest.file --- -- test "$program_prefix" != NONE && -- program_transform_name="s&^&$program_prefix&;$program_transform_name" -- # Use a double $ so make ignores it. --@@ -2440,12 +2398,12 @@ if test x"${MISSING+set}" != xset; then -- esac -- fi -- # Use eval to expand $SHELL ---if eval "$MISSING --is-lightweight"; then --- am_missing_run="$MISSING " --+if eval "$MISSING --run true"; then --+ am_missing_run="$MISSING --run " -- else -- am_missing_run= --- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 ---$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} --+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 --+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} -- fi -- -- if test x"${install_sh}" != xset; then --@@ -2457,10 +2415,10 @@ if test x"${install_sh}" != xset; then -- esac -- fi -- ---# Installed binaries are usually stripped using 'strip' when the user ---# run "make install-strip". However 'strip' might not be the right --+# Installed binaries are usually stripped using `strip' when the user --+# run `make install-strip'. However `strip' might not be the right -- # tool to use in cross-compilation environments, therefore Automake ---# will honor the 'STRIP' environment variable to overrule this program. --+# will honor the `STRIP' environment variable to overrule this program. -- if test "$cross_compiling" != no; then -- if test -n "$ac_tool_prefix"; then -- # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. --@@ -2479,7 +2437,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_STRIP="${ac_tool_prefix}strip" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -2519,7 +2477,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_STRIP="strip" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -2570,7 +2528,7 @@ do -- test -z "$as_dir" && as_dir=. -- for ac_prog in mkdir gmkdir; do -- for ac_exec_ext in '' $ac_executable_extensions; do --- as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue --+ { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue -- case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( -- 'mkdir (GNU coreutils) '* | \ -- 'mkdir (coreutils) '* | \ --@@ -2599,6 +2557,12 @@ fi -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 -- $as_echo "$MKDIR_P" >&6; } -- --+mkdir_p="$MKDIR_P" --+case $mkdir_p in --+ [\\/$]* | ?:[\\/]*) ;; --+ */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; --+esac --+ -- for ac_prog in gawk mawk nawk awk -- do -- # Extract the first word of "$ac_prog", so it can be a program name with args. --@@ -2617,7 +2581,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_AWK="$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -2681,45 +2645,6 @@ else -- fi -- rmdir .tst 2>/dev/null -- ---# Check whether --enable-silent-rules was given. ---if test "${enable_silent_rules+set}" = set; then : --- enableval=$enable_silent_rules; ---fi --- ---case $enable_silent_rules in # ((( --- yes) AM_DEFAULT_VERBOSITY=0;; --- no) AM_DEFAULT_VERBOSITY=1;; --- *) AM_DEFAULT_VERBOSITY=1;; ---esac ---am_make=${MAKE-make} ---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 ---$as_echo_n "checking whether $am_make supports nested variables... " >&6; } ---if ${am_cv_make_support_nested_variables+:} false; then : --- $as_echo_n "(cached) " >&6 ---else --- if $as_echo 'TRUE=$(BAR$(V)) ---BAR0=false ---BAR1=true ---V=1 ---am__doit: --- @$(TRUE) ---.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then --- am_cv_make_support_nested_variables=yes ---else --- am_cv_make_support_nested_variables=no ---fi ---fi ---{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 ---$as_echo "$am_cv_make_support_nested_variables" >&6; } ---if test $am_cv_make_support_nested_variables = yes; then --- AM_V='$(V)' --- AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' ---else --- AM_V=$AM_DEFAULT_VERBOSITY --- AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY ---fi ---AM_BACKSLASH='\' --- -- if test "`cd $srcdir && pwd`" != "`pwd`"; then -- # Use -I$(srcdir) only when $(srcdir) != ., so that make's output -- # is not polluted with repeated "-I." --@@ -2770,111 +2695,18 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_ru -- -- MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -- ---# For better backward compatibility. To be removed once Automake 1.9.x ---# dies out for good. For more background, see: ---# ---# ---mkdir_p='$(MKDIR_P)' --- -- # We need awk for the "check" target. The system "awk" is bad on -- # some platforms. -- # Always define AMTAR for backward compatibility. Yes, it's still used -- # in the wild :-( We should find a proper way to deprecate it ... -- AMTAR='$${TAR-tar}' -- --- ---# We'll loop over all known methods to create a tar archive until one works. ---_am_tools='gnutar pax cpio none' --- -- am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' -- -- -- -- -- --- ---# POSIX will say in a future version that running "rm -f" with no argument ---# is OK; and we want to be able to make that assumption in our Makefile ---# recipes. So use an aggressive probe to check that the usage we want is ---# actually supported "in the wild" to an acceptable degree. ---# See automake bug#10828. ---# To make any issue more visible, cause the running configure to be aborted ---# by default if the 'rm' program in use doesn't match our expectations; the ---# user can still override this though. ---if rm -f && rm -fr && rm -rf; then : OK; else --- cat >&2 <<'END' ---Oops! --- ---Your 'rm' program seems unable to run without file operands specified ---on the command line, even when the '-f' option is present. This is contrary ---to the behaviour of most rm programs out there, and not conforming with ---the upcoming POSIX standard: --- ---Please tell bug-automake@gnu.org about your system, including the value ---of your $PATH and any error possibly output before this message. This ---can help us improve future automake versions. --- ---END --- if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then --- echo 'Configuration will proceed anyway, since you have set the' >&2 --- echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 --- echo >&2 --- else --- cat >&2 <<'END' ---Aborting the configuration process, to ensure you take notice of the issue. --- ---You can download and install GNU coreutils to get an 'rm' implementation ---that behaves properly: . --- ---If you want to complete the configuration process using your problematic ---'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM ---to "yes", and re-run configure. --- ---END --- as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 --- fi ---fi --- ---# Check whether --enable-silent-rules was given. ---if test "${enable_silent_rules+set}" = set; then : --- enableval=$enable_silent_rules; ---fi --- ---case $enable_silent_rules in # ((( --- yes) AM_DEFAULT_VERBOSITY=0;; --- no) AM_DEFAULT_VERBOSITY=1;; --- *) AM_DEFAULT_VERBOSITY=0;; ---esac ---am_make=${MAKE-make} ---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 ---$as_echo_n "checking whether $am_make supports nested variables... " >&6; } ---if ${am_cv_make_support_nested_variables+:} false; then : --- $as_echo_n "(cached) " >&6 ---else --- if $as_echo 'TRUE=$(BAR$(V)) ---BAR0=false ---BAR1=true ---V=1 ---am__doit: --- @$(TRUE) ---.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then --- am_cv_make_support_nested_variables=yes ---else --- am_cv_make_support_nested_variables=no ---fi ---fi ---{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 ---$as_echo "$am_cv_make_support_nested_variables" >&6; } ---if test $am_cv_make_support_nested_variables = yes; then --- AM_V='$(V)' --- AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' ---else --- AM_V=$AM_DEFAULT_VERBOSITY --- AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY ---fi ---AM_BACKSLASH='\' --- --- -- ac_ext=c -- ac_cpp='$CPP $CPPFLAGS' -- ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' --@@ -2897,7 +2729,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_CC="${ac_tool_prefix}gcc" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -2937,7 +2769,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_CC="gcc" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -2990,7 +2822,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_CC="${ac_tool_prefix}cc" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -3031,7 +2863,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then -- ac_prog_rejected=yes -- continue --@@ -3089,7 +2921,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_CC="$ac_tool_prefix$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -3133,7 +2965,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_CC="$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -3579,7 +3411,8 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ -- /* end confdefs.h. */ -- #include -- #include ---struct stat; --+#include --+#include -- /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -- struct buf { int x; }; -- FILE * (*rcsopen) (struct buf *, struct stat *, int); --@@ -3663,65 +3496,6 @@ ac_cpp='$CPP $CPPFLAGS' -- ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -- ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -- ac_compiler_gnu=$ac_cv_c_compiler_gnu --- ---ac_ext=c ---ac_cpp='$CPP $CPPFLAGS' ---ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ---ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ---ac_compiler_gnu=$ac_cv_c_compiler_gnu ---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 ---$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } ---if ${am_cv_prog_cc_c_o+:} false; then : --- $as_echo_n "(cached) " >&6 ---else --- cat confdefs.h - <<_ACEOF >conftest.$ac_ext ---/* end confdefs.h. */ --- ---int ---main () ---{ --- --- ; --- return 0; ---} ---_ACEOF --- # Make sure it works both with $CC and with simple cc. --- # Following AC_PROG_CC_C_O, we do the test twice because some --- # compilers refuse to overwrite an existing .o file with -o, --- # though they will create one. --- am_cv_prog_cc_c_o=yes --- for am_i in 1 2; do --- if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 --- ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 --- ac_status=$? --- echo "$as_me:$LINENO: \$? = $ac_status" >&5 --- (exit $ac_status); } \ --- && test -f conftest2.$ac_objext; then --- : OK --- else --- am_cv_prog_cc_c_o=no --- break --- fi --- done --- rm -f core conftest* --- unset am_i ---fi ---{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 ---$as_echo "$am_cv_prog_cc_c_o" >&6; } ---if test "$am_cv_prog_cc_c_o" != yes; then --- # Losing compiler, so override with the script. --- # FIXME: It is wrong to rewrite CC. --- # But if we don't then we get into trouble of one sort or another. --- # A longer-term fix would be to have automake use am__CC in this case, --- # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" --- CC="$am_aux_dir/compile $CC" ---fi ---ac_ext=c ---ac_cpp='$CPP $CPPFLAGS' ---ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ---ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ---ac_compiler_gnu=$ac_cv_c_compiler_gnu --- -- DEPDIR="${am__leading_dot}deps" -- -- ac_config_commands="$ac_config_commands depfiles" --@@ -3741,7 +3515,7 @@ am__quote= -- _am_result=none -- # First try GNU make style include. -- echo "include confinc" > confmf ---# Ignore all kinds of additional output from 'make'. --+# Ignore all kinds of additional output from `make'. -- case `$am_make -s -f confmf 2> /dev/null` in #( -- *the\ am__doit\ target*) -- am__include=include --@@ -3797,8 +3571,8 @@ else -- # We make a subdir and do the tests there. Otherwise we can end up -- # making bogus files that we don't know about and never remove. For -- # instance it was reported that on HP-UX the gcc test will end up --- # making a dummy file named 'D' -- because '-MD' means "put the output --- # in D". --+ # making a dummy file named `D' -- because `-MD' means `put the output --+ # in D'. -- rm -rf conftest.dir -- mkdir conftest.dir -- # Copy depcomp to subdir because otherwise we won't find it if we're --@@ -3833,16 +3607,16 @@ else -- : > sub/conftest.c -- for i in 1 2 3 4 5 6; do -- echo '#include "conftst'$i'.h"' >> sub/conftest.c --- # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with --- # Solaris 10 /bin/sh. --- echo '/* dummy */' > sub/conftst$i.h --+ # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with --+ # Solaris 8's {/usr,}/bin/sh. --+ touch sub/conftst$i.h -- done -- echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf -- --- # We check with '-c' and '-o' for the sake of the "dashmstdout" --+ # We check with `-c' and `-o' for the sake of the "dashmstdout" -- # mode. It turns out that the SunPro C++ compiler does not properly --- # handle '-M -o', and we need to detect this. Also, some Intel --- # versions had trouble with output in subdirs. --+ # handle `-M -o', and we need to detect this. Also, some Intel --+ # versions had trouble with output in subdirs -- am__obj=sub/conftest.${OBJEXT-o} -- am__minus_obj="-o $am__obj" -- case $depmode in --@@ -3851,8 +3625,8 @@ else -- test "$am__universal" = false || continue -- ;; -- nosideeffect) --- # After this tag, mechanisms are not by side-effect, so they'll --- # only be used when explicitly requested. --+ # after this tag, mechanisms are not by side-effect, so they'll --+ # only be used when explicitly requested -- if test "x$enable_dependency_tracking" = xyes; then -- continue -- else --@@ -3860,7 +3634,7 @@ else -- fi -- ;; -- msvc7 | msvc7msys | msvisualcpp | msvcmsys) --- # This compiler won't grok '-c -o', but also, the minuso test has --+ # This compiler won't grok `-c -o', but also, the minuso test has -- # not run yet. These depmodes are late enough in the game, and -- # so weak that their functioning should not be impacted. -- am__obj=conftest.${OBJEXT-o} --@@ -3914,6 +3688,131 @@ else -- fi -- -- --+if test "x$CC" != xcc; then --+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 --+$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } --+else --+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 --+$as_echo_n "checking whether cc understands -c and -o together... " >&6; } --+fi --+set dummy $CC; ac_cc=`$as_echo "$2" | --+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` --+if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : --+ $as_echo_n "(cached) " >&6 --+else --+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext --+/* end confdefs.h. */ --+ --+int --+main () --+{ --+ --+ ; --+ return 0; --+} --+_ACEOF --+# Make sure it works both with $CC and with simple cc. --+# We do the test twice because some compilers refuse to overwrite an --+# existing .o file with -o, though they will create one. --+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' --+rm -f conftest2.* --+if { { case "(($ac_try" in --+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; --+ *) ac_try_echo=$ac_try;; --+esac --+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" --+$as_echo "$ac_try_echo"; } >&5 --+ (eval "$ac_try") 2>&5 --+ ac_status=$? --+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 --+ test $ac_status = 0; } && --+ test -f conftest2.$ac_objext && { { case "(($ac_try" in --+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; --+ *) ac_try_echo=$ac_try;; --+esac --+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" --+$as_echo "$ac_try_echo"; } >&5 --+ (eval "$ac_try") 2>&5 --+ ac_status=$? --+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 --+ test $ac_status = 0; }; --+then --+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes --+ if test "x$CC" != xcc; then --+ # Test first that cc exists at all. --+ if { ac_try='cc -c conftest.$ac_ext >&5' --+ { { case "(($ac_try" in --+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; --+ *) ac_try_echo=$ac_try;; --+esac --+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" --+$as_echo "$ac_try_echo"; } >&5 --+ (eval "$ac_try") 2>&5 --+ ac_status=$? --+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 --+ test $ac_status = 0; }; }; then --+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' --+ rm -f conftest2.* --+ if { { case "(($ac_try" in --+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; --+ *) ac_try_echo=$ac_try;; --+esac --+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" --+$as_echo "$ac_try_echo"; } >&5 --+ (eval "$ac_try") 2>&5 --+ ac_status=$? --+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 --+ test $ac_status = 0; } && --+ test -f conftest2.$ac_objext && { { case "(($ac_try" in --+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; --+ *) ac_try_echo=$ac_try;; --+esac --+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" --+$as_echo "$ac_try_echo"; } >&5 --+ (eval "$ac_try") 2>&5 --+ ac_status=$? --+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 --+ test $ac_status = 0; }; --+ then --+ # cc works too. --+ : --+ else --+ # cc exists but doesn't like -o. --+ eval ac_cv_prog_cc_${ac_cc}_c_o=no --+ fi --+ fi --+ fi --+else --+ eval ac_cv_prog_cc_${ac_cc}_c_o=no --+fi --+rm -f core conftest* --+ --+fi --+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then --+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 --+$as_echo "yes" >&6; } --+else --+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 --+$as_echo "no" >&6; } --+ --+$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h --+ --+fi --+ --+# FIXME: we rely on the cache variable name because --+# there is no other way. --+set dummy $CC --+am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` --+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o --+if test "$am_t" != yes; then --+ # Losing compiler, so override with the script. --+ # FIXME: It is wrong to rewrite CC. --+ # But if we don't then we get into trouble of one sort or another. --+ # A longer-term fix would be to have automake use am__CC in this case, --+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" --+ CC="$am_aux_dir/compile $CC" --+fi --+ -- -- -- if test -n "$ac_tool_prefix"; then --@@ -3935,7 +3834,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_AR="$ac_tool_prefix$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -3979,7 +3878,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_AR="$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -4023,13 +3922,7 @@ $as_echo_n "checking the archiver ($AR) -- if ${am_cv_ar_interface+:} false; then : -- $as_echo_n "(cached) " >&6 -- else --- ac_ext=c ---ac_cpp='$CPP $CPPFLAGS' ---ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ---ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ---ac_compiler_gnu=$ac_cv_c_compiler_gnu --- --- am_cv_ar_interface=ar --+ am_cv_ar_interface=ar -- cat confdefs.h - <<_ACEOF >conftest.$ac_ext -- /* end confdefs.h. */ -- int some_variable = 0; --@@ -4060,11 +3953,6 @@ if ac_fn_c_try_compile "$LINENO"; then : -- -- fi -- rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext --- ac_ext=c ---ac_cpp='$CPP $CPPFLAGS' ---ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ---ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ---ac_compiler_gnu=$ac_cv_c_compiler_gnu -- -- fi -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 --@@ -4126,8 +4014,8 @@ esac -- -- -- ---macro_version='2.4.2' ---macro_revision='1.3337' --+macro_version='2.4' --+macro_revision='1.3293' -- -- -- --@@ -4305,7 +4193,7 @@ do -- for ac_prog in sed gsed; do -- for ac_exec_ext in '' $ac_executable_extensions; do -- ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" --- as_fn_executable_p "$ac_path_SED" || continue --+ { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue -- # Check for GNU ac_path_SED and select it if it is found. -- # Check for GNU $ac_path_SED -- case `"$ac_path_SED" --version 2>&1` in --@@ -4381,7 +4269,7 @@ do -- for ac_prog in grep ggrep; do -- for ac_exec_ext in '' $ac_executable_extensions; do -- ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" --- as_fn_executable_p "$ac_path_GREP" || continue --+ { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue -- # Check for GNU ac_path_GREP and select it if it is found. -- # Check for GNU $ac_path_GREP -- case `"$ac_path_GREP" --version 2>&1` in --@@ -4447,7 +4335,7 @@ do -- for ac_prog in egrep; do -- for ac_exec_ext in '' $ac_executable_extensions; do -- ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" --- as_fn_executable_p "$ac_path_EGREP" || continue --+ { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue -- # Check for GNU ac_path_EGREP and select it if it is found. -- # Check for GNU $ac_path_EGREP -- case `"$ac_path_EGREP" --version 2>&1` in --@@ -4514,7 +4402,7 @@ do -- for ac_prog in fgrep; do -- for ac_exec_ext in '' $ac_executable_extensions; do -- ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" --- as_fn_executable_p "$ac_path_FGREP" || continue --+ { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue -- # Check for GNU ac_path_FGREP and select it if it is found. -- # Check for GNU $ac_path_FGREP -- case `"$ac_path_FGREP" --version 2>&1` in --@@ -4770,7 +4658,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -4814,7 +4702,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -4972,11 +4860,6 @@ else -- lt_cv_sys_max_cmd_len=196608 -- ;; -- --- os2*) --- # The test takes a long time on OS/2. --- lt_cv_sys_max_cmd_len=8192 --- ;; --- -- osf*) -- # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure -- # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not --@@ -5016,7 +4899,7 @@ else -- # If test is not a shell built-in, we'll probably end up computing a -- # maximum length that is only half of the actual maximum length, but -- # we can't tell. --- while { test "X"`env echo "$teststring$teststring" 2>/dev/null` \ --+ while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ -- = "X$teststring$teststring"; } >/dev/null 2>&1 && -- test $i != 17 # 1/2 MB should be enough -- do --@@ -5238,7 +5121,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5278,7 +5161,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_OBJDUMP="objdump" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5445,7 +5328,7 @@ irix5* | irix6* | nonstopux*) -- lt_cv_deplibs_check_method=pass_all -- ;; -- ---# This must be glibc/ELF. --+# This must be Linux ELF. -- linux* | k*bsd*-gnu | kopensolaris*-gnu) -- lt_cv_deplibs_check_method=pass_all -- ;; --@@ -5584,7 +5467,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5624,7 +5507,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_DLLTOOL="dlltool" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5727,7 +5610,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_AR="$ac_tool_prefix$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5771,7 +5654,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_AR="$ac_prog" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5896,7 +5779,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_STRIP="${ac_tool_prefix}strip" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5936,7 +5819,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_STRIP="strip" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -5995,7 +5878,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6035,7 +5918,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_RANLIB="ranlib" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6085,13 +5968,13 @@ old_postuninstall_cmds= -- if test -n "$RANLIB"; then -- case $host_os in -- openbsd*) --- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" --+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" -- ;; -- *) --- old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" --+ old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" -- ;; -- esac --- old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" --+ old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -- fi -- -- case $host_os in --@@ -6238,7 +6121,6 @@ for ac_symprfx in "" "_"; do -- # which start with @ or ?. -- lt_cv_sys_global_symbol_pipe="$AWK '"\ -- " {last_section=section; section=\$ 3};"\ ---" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ -- " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -- " \$ 0!~/External *\|/{next};"\ -- " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ --@@ -6627,7 +6509,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } -- CFLAGS="$SAVE_CFLAGS" -- fi -- ;; ---*-*solaris*) --+sparc*-*solaris*) -- # Find out which ABI we are using. -- echo 'int i;' > conftest.$ac_ext -- if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 --@@ -6638,20 +6520,7 @@ $as_echo "$lt_cv_cc_needs_belf" >&6; } -- case `/usr/bin/file conftest.o` in -- *64-bit*) -- case $lt_cv_prog_gnu_ld in --- yes*) --- case $host in --- i?86-*-solaris*) --- LD="${LD-ld} -m elf_x86_64" --- ;; --- sparc*-*-solaris*) --- LD="${LD-ld} -m elf64_sparc" --- ;; --- esac --- # GNU ld 2.21 introduced _sol2 emulations. Use them if available. --- if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then --- LD="${LD-ld}_sol2" --- fi --- ;; --+ yes*) LD="${LD-ld} -m elf64_sparc" ;; -- *) -- if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then -- LD="${LD-ld} -64" --@@ -6684,7 +6553,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6724,7 +6593,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6804,7 +6673,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6844,7 +6713,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6896,7 +6765,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6936,7 +6805,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_NMEDIT="nmedit" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -6988,7 +6857,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_LIPO="${ac_tool_prefix}lipo" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7028,7 +6897,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_LIPO="lipo" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7080,7 +6949,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_OTOOL="${ac_tool_prefix}otool" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7120,7 +6989,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_OTOOL="otool" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7172,7 +7041,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7212,7 +7081,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_prog_ac_ct_OTOOL64="otool64" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -7291,13 +7160,7 @@ else -- $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -- -dynamiclib -Wl,-single_module conftest.c 2>conftest.err -- _lt_result=$? --- # If there is a non-empty error log, and "single_module" --- # appears in it, assume the flag caused a linker warning --- if test -s conftest.err && $GREP single_module conftest.err; then --- cat conftest.err >&5 --- # Otherwise, if the output was created with a 0 exit code from --- # the compiler, it worked. --- elif test -f libconftest.dylib && test $_lt_result -eq 0; then --+ if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then -- lt_cv_apple_cc_single_mod=yes -- else -- cat conftest.err >&5 --@@ -7308,7 +7171,6 @@ else -- fi -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 -- $as_echo "$lt_cv_apple_cc_single_mod" >&6; } --- -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 -- $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -- if ${lt_cv_ld_exported_symbols_list+:} false; then : --@@ -7341,7 +7203,6 @@ rm -f core conftest.err conftest.$ac_obj -- fi -- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 -- $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } --- -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 -- $as_echo_n "checking for -force_load linker flag... " >&6; } -- if ${lt_cv_ld_force_load+:} false; then : --@@ -7363,9 +7224,7 @@ _LT_EOF -- echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 -- $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err -- _lt_result=$? --- if test -s conftest.err && $GREP force_load conftest.err; then --- cat conftest.err >&5 --- elif test -f conftest && test $_lt_result -eq 0 && $GREP forced_load conftest >/dev/null 2>&1 ; then --+ if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then -- lt_cv_ld_force_load=yes -- else -- cat conftest.err >&5 --@@ -7740,22 +7599,7 @@ fi -- -- # Check whether --with-pic was given. -- if test "${with_pic+set}" = set; then : --- withval=$with_pic; lt_p=${PACKAGE-default} --- case $withval in --- yes|no) pic_mode=$withval ;; --- *) --- pic_mode=default --- # Look at the argument we got. We use all the common list separators. --- lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," --- for lt_pkg in $withval; do --- IFS="$lt_save_ifs" --- if test "X$lt_pkg" = "X$lt_p"; then --- pic_mode=yes --- fi --- done --- IFS="$lt_save_ifs" --- ;; --- esac --+ withval=$with_pic; pic_mode="$withval" -- else -- pic_mode=default -- fi --@@ -7833,10 +7677,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtoo -- -- -- --- --- --- --- -- test -z "$LN_S" && LN_S="ln -s" -- -- --@@ -8126,10 +7966,6 @@ _lt_linker_boilerplate=`cat conftest.err -- $RM -r conftest* -- -- ---## CAVEAT EMPTOR: ---## There is no encapsulation within the following macros, do not change ---## the running order or otherwise move them around unless you know exactly ---## what you are doing... -- if test -n "$compiler"; then -- -- lt_prog_compiler_no_builtin_flag= --@@ -8296,9 +8132,7 @@ lt_prog_compiler_static= -- case $cc_basename in -- nvcc*) # Cuda Compiler Driver 2.2 -- lt_prog_compiler_wl='-Xlinker ' --- if test -n "$lt_prog_compiler_pic"; then --- lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" --- fi --+ lt_prog_compiler_pic='-Xcompiler -fPIC' -- ;; -- esac -- else --@@ -8389,33 +8223,18 @@ lt_prog_compiler_static= -- ;; -- *) -- case `$CC -V 2>&1 | sed 5q` in --- *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) --+ *Sun\ F* | *Sun*Fortran*) -- # Sun Fortran 8.3 passes all unrecognized flags to the linker -- lt_prog_compiler_pic='-KPIC' -- lt_prog_compiler_static='-Bstatic' -- lt_prog_compiler_wl='' -- ;; --- *Sun\ F* | *Sun*Fortran*) --- lt_prog_compiler_pic='-KPIC' --- lt_prog_compiler_static='-Bstatic' --- lt_prog_compiler_wl='-Qoption ld ' --- ;; -- *Sun\ C*) -- # Sun C 5.9 -- lt_prog_compiler_pic='-KPIC' -- lt_prog_compiler_static='-Bstatic' -- lt_prog_compiler_wl='-Wl,' -- ;; --- *Intel*\ [CF]*Compiler*) --- lt_prog_compiler_wl='-Wl,' --- lt_prog_compiler_pic='-fPIC' --- lt_prog_compiler_static='-static' --- ;; --- *Portland\ Group*) --- lt_prog_compiler_wl='-Wl,' --- lt_prog_compiler_pic='-fpic' --- lt_prog_compiler_static='-Bstatic' --- ;; -- esac -- ;; -- esac --@@ -8777,6 +8596,7 @@ $as_echo_n "checking whether the $compil -- hardcode_direct=no -- hardcode_direct_absolute=no -- hardcode_libdir_flag_spec= --+ hardcode_libdir_flag_spec_ld= -- hardcode_libdir_separator= -- hardcode_minus_L=no -- hardcode_shlibpath_var=unsupported --@@ -9026,7 +8846,8 @@ _LT_EOF -- xlf* | bgf* | bgxlf* | mpixlf*) -- # IBM XL Fortran 10.1 on PPC cannot create shared libs itself -- whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' --- hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' --+ hardcode_libdir_flag_spec= --+ hardcode_libdir_flag_spec_ld='-rpath $libdir' -- archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' -- if test "x$supports_anon_versioning" = xyes; then -- archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ --@@ -9405,7 +9226,6 @@ fi -- # The linker will not automatically build a static lib if we build a DLL. -- # _LT_TAGVAR(old_archive_from_new_cmds, )='true' -- enable_shared_with_static_runtimes=yes --- exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' -- export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' -- # Don't use ranlib -- old_postinstall_cmds='chmod 644 $oldlib' --@@ -9451,7 +9271,6 @@ fi -- hardcode_shlibpath_var=unsupported -- if test "$lt_cv_ld_force_load" = "yes"; then -- whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' --- -- else -- whole_archive_flag_spec='' -- fi --@@ -9480,6 +9299,10 @@ fi -- hardcode_shlibpath_var=no -- ;; -- --+ freebsd1*) --+ ld_shlibs=no --+ ;; --+ -- # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor -- # support. Future versions do this automatically, but an explicit c++rt0.o -- # does not break anything, and helps significantly (at the cost of a little --@@ -9492,7 +9315,7 @@ fi -- ;; -- -- # Unfortunately, older versions of FreeBSD 2 do not have this feature. --- freebsd2.*) --+ freebsd2*) -- archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' -- hardcode_direct=yes -- hardcode_minus_L=yes --@@ -9531,6 +9354,7 @@ fi -- fi -- if test "$with_gnu_ld" = no; then -- hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' --+ hardcode_libdir_flag_spec_ld='+b $libdir' -- hardcode_libdir_separator=: -- hardcode_direct=yes -- hardcode_direct_absolute=yes --@@ -10154,6 +9978,11 @@ esac -- -- -- --+ --+ --+ --+ --+ -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 -- $as_echo_n "checking dynamic linker characteristics... " >&6; } -- --@@ -10243,7 +10072,7 @@ need_version=unknown -- -- case $host_os in -- aix3*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' -- shlibpath_var=LIBPATH -- --@@ -10252,7 +10081,7 @@ aix3*) -- ;; -- -- aix[4-9]*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- hardcode_into_libs=yes --@@ -10317,7 +10146,7 @@ beos*) -- ;; -- -- bsdi[45]*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' -- soname_spec='${libname}${release}${shared_ext}$major' --@@ -10456,7 +10285,7 @@ darwin* | rhapsody*) -- ;; -- -- dgux*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' --@@ -10464,6 +10293,10 @@ dgux*) -- shlibpath_var=LD_LIBRARY_PATH -- ;; -- --+freebsd1*) --+ dynamic_linker=no --+ ;; --+ -- freebsd* | dragonfly*) -- # DragonFly does not have aout. When/if they implement a new -- # versioning mechanism, adjust this. --@@ -10471,7 +10304,7 @@ freebsd* | dragonfly*) -- objformat=`/usr/bin/objformat` -- else -- case $host_os in --- freebsd[23].*) objformat=aout ;; --+ freebsd[123]*) objformat=aout ;; -- *) objformat=elf ;; -- esac -- fi --@@ -10489,7 +10322,7 @@ freebsd* | dragonfly*) -- esac -- shlibpath_var=LD_LIBRARY_PATH -- case $host_os in --- freebsd2.*) --+ freebsd2*) -- shlibpath_overrides_runpath=yes -- ;; -- freebsd3.[01]* | freebsdelf3.[01]*) --@@ -10509,18 +10342,17 @@ freebsd* | dragonfly*) -- ;; -- -- gnu*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' -- soname_spec='${libname}${release}${shared_ext}$major' -- shlibpath_var=LD_LIBRARY_PATH --- shlibpath_overrides_runpath=no -- hardcode_into_libs=yes -- ;; -- -- haiku*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- dynamic_linker="$host_os runtime_loader" --@@ -10581,7 +10413,7 @@ hpux9* | hpux10* | hpux11*) -- ;; -- -- interix[3-9]*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' --@@ -10597,7 +10429,7 @@ irix5* | irix6* | nonstopux*) -- nonstopux*) version_type=nonstopux ;; -- *) -- if test "$lt_cv_prog_gnu_ld" = yes; then --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- else -- version_type=irix -- fi ;; --@@ -10634,9 +10466,9 @@ linux*oldld* | linux*aout* | linux*coff* -- dynamic_linker=no -- ;; -- ---# This must be glibc/ELF. --+# This must be Linux ELF. -- linux* | k*bsd*-gnu | kopensolaris*-gnu) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' --@@ -10718,7 +10550,7 @@ netbsd*) -- ;; -- -- newsos6) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' -- shlibpath_var=LD_LIBRARY_PATH -- shlibpath_overrides_runpath=yes --@@ -10787,7 +10619,7 @@ rdos*) -- ;; -- -- solaris*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' --@@ -10812,7 +10644,7 @@ sunos4*) -- ;; -- -- sysv4 | sysv4.3*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' -- soname_spec='${libname}${release}${shared_ext}$major' -- shlibpath_var=LD_LIBRARY_PATH --@@ -10836,7 +10668,7 @@ sysv4 | sysv4.3*) -- -- sysv4*MP*) -- if test -d /usr/nec ;then --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' -- soname_spec='$libname${shared_ext}.$major' -- shlibpath_var=LD_LIBRARY_PATH --@@ -10867,7 +10699,7 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* -- -- tpf*) -- # TPF is a cross-target only. Preferred cross-host = GNU/Linux. --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- need_lib_prefix=no -- need_version=no -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' --@@ -10877,7 +10709,7 @@ tpf*) -- ;; -- -- uts4*) --- version_type=linux # correct to gnu/linux during the next big refactor --+ version_type=linux -- library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' -- soname_spec='${libname}${release}${shared_ext}$major' -- shlibpath_var=LD_LIBRARY_PATH --@@ -11659,8 +11491,6 @@ CC="$lt_save_CC" -- -- -- --- --- -- ac_config_commands="$ac_config_commands libtool" -- -- --@@ -11726,7 +11556,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -11769,7 +11599,7 @@ do -- IFS=$as_save_IFS -- test -z "$as_dir" && as_dir=. -- for ac_exec_ext in '' $ac_executable_extensions; do --- if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then --+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then -- ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" -- $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 -- break 2 --@@ -11932,7 +11762,7 @@ regular_CFLAGS="-Wall -Waggregate-return -- if test -n "$kbuilddir"; then -- { $as_echo "$as_me:${as_lineno-$LINENO}: checking kernel version that we will build against" >&5 -- $as_echo_n "checking kernel version that we will build against... " >&6; } --- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)"; --+ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion)"; -- kmajor="${krel%%[^0-9]*}"; -- kmajor="$(($kmajor+0))"; -- krel="${krel:${#kmajor}}"; --@@ -12076,14 +11906,6 @@ LIBOBJS=$ac_libobjs -- LTLIBOBJS=$ac_ltlibobjs -- -- ---{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 ---$as_echo_n "checking that generated files are newer than configure... " >&6; } --- if test -n "$am_sleep_pid"; then --- # Hide warnings about reused PIDs. --- wait $am_sleep_pid 2>/dev/null --- fi --- { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 ---$as_echo "done" >&6; } -- if test -n "$EXEEXT"; then -- am__EXEEXT_TRUE= -- am__EXEEXT_FALSE='#' --@@ -12398,16 +12220,16 @@ if (echo >conf$$.file) 2>/dev/null; then -- # ... but there are two gotchas: -- # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. -- # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. --- # In both cases, we have to default to `cp -pR'. --+ # In both cases, we have to default to `cp -p'. -- ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- elif ln conf$$.file conf$$ 2>/dev/null; then -- as_ln_s=ln -- else --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- fi -- else --- as_ln_s='cp -pR' --+ as_ln_s='cp -p' -- fi -- rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file -- rmdir conf$$.dir 2>/dev/null --@@ -12467,16 +12289,28 @@ else -- as_mkdir_p=false -- fi -- --- ---# as_fn_executable_p FILE ---# ----------------------- ---# Test if FILE is an executable regular file. ---as_fn_executable_p () ---{ --- test -f "$1" && test -x "$1" ---} # as_fn_executable_p ---as_test_x='test -x' ---as_executable_p=as_fn_executable_p --+if test -x / >/dev/null 2>&1; then --+ as_test_x='test -x' --+else --+ if ls -dL / >/dev/null 2>&1; then --+ as_ls_L_option=L --+ else --+ as_ls_L_option= --+ fi --+ as_test_x=' --+ eval sh -c '\'' --+ if test -d "$1"; then --+ test -d "$1/."; --+ else --+ case $1 in #( --+ -*)set "./$1";; --+ esac; --+ case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( --+ ???[sx]*):;;*)false;;esac;fi --+ '\'' sh --+ ' --+fi --+as_executable_p=$as_test_x -- -- # Sed expression to map a string onto a valid CPP name. -- as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" --@@ -12498,7 +12332,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri -- # values after options handling. -- ac_log=" -- This file was extended by xtables-addons $as_me 2.5, which was ---generated by GNU Autoconf 2.69. Invocation command line was --+generated by GNU Autoconf 2.68. Invocation command line was -- -- CONFIG_FILES = $CONFIG_FILES -- CONFIG_HEADERS = $CONFIG_HEADERS --@@ -12564,10 +12398,10 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_writ -- ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -- ac_cs_version="\\ -- xtables-addons config.status 2.5 ---configured by $0, generated by GNU Autoconf 2.69, --+configured by $0, generated by GNU Autoconf 2.68, -- with options \\"\$ac_cs_config\\" -- ---Copyright (C) 2012 Free Software Foundation, Inc. --+Copyright (C) 2010 Free Software Foundation, Inc. -- This config.status script is free software; the Free Software Foundation -- gives unlimited permission to copy, distribute and modify it." -- --@@ -12658,7 +12492,7 @@ fi -- _ACEOF -- cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -- if \$ac_cs_recheck; then --- set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion --+ set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion -- shift -- \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 -- CONFIG_SHELL='$SHELL' --@@ -12700,7 +12534,6 @@ pic_mode='`$ECHO "$pic_mode" | $SED "$de -- enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' -- SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' -- ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' ---PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' -- host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' -- host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' -- host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' --@@ -12783,6 +12616,7 @@ with_gnu_ld='`$ECHO "$with_gnu_ld" | $SE -- allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' -- no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' -- hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' --+hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' -- hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' -- hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' -- hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' --@@ -12838,7 +12672,6 @@ _LTECHO_EOF' -- # Quote evaled strings. -- for var in SHELL \ -- ECHO \ ---PATH_SEPARATOR \ -- SED \ -- GREP \ -- EGREP \ --@@ -12889,6 +12722,7 @@ with_gnu_ld \ -- allow_undefined_flag \ -- no_undefined_flag \ -- hardcode_libdir_flag_spec \ --+hardcode_libdir_flag_spec_ld \ -- hardcode_libdir_separator \ -- exclude_expsyms \ -- include_expsyms \ --@@ -13575,7 +13409,7 @@ $as_echo "$as_me: executing $ac_file com -- -- case $ac_file$ac_mode in -- "depfiles":C) test x"$AMDEP_TRUE" != x"" || { --- # Older Autoconf quotes --file arguments for eval, but not when files --+ # Autoconf 2.62 quotes --file arguments for eval, but not when files -- # are listed without --file. Let's play safe and only enable the eval -- # if we detect the quoting. -- case $CONFIG_FILES in --@@ -13588,7 +13422,7 @@ $as_echo "$as_me: executing $ac_file com -- # Strip MF so we end up with the name of the file. -- mf=`echo "$mf" | sed -e 's/:.*$//'` -- # Check whether this is an Automake generated Makefile or not. --- # We used to match only the files named 'Makefile.in', but --+ # We used to match only the files named `Makefile.in', but -- # some people rename them; so instead we look at the file content. -- # Grep'ing the first line is not enough: some people post-process -- # each Makefile.in and add a new line on top of each file to say so. --@@ -13622,19 +13456,21 @@ $as_echo X"$mf" | -- continue -- fi -- # Extract the definition of DEPDIR, am__include, and am__quote --- # from the Makefile without running 'make'. --+ # from the Makefile without running `make'. -- DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` -- test -z "$DEPDIR" && continue -- am__include=`sed -n 's/^am__include = //p' < "$mf"` --- test -z "$am__include" && continue --+ test -z "am__include" && continue -- am__quote=`sed -n 's/^am__quote = //p' < "$mf"` --+ # When using ansi2knr, U may be empty or an underscore; expand it --+ U=`sed -n 's/^U = //p' < "$mf"` -- # Find all dependency output files, they are included files with -- # $(DEPDIR) in their names. We invoke sed twice because it is the -- # simplest approach to changing $(DEPDIR) to its actual value in the -- # expansion. -- for file in `sed -n " -- s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ --- sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do --+ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do -- # Make sure the directory exists. -- test -f "$dirpart/$file" && continue -- fdir=`$as_dirname -- "$file" || --@@ -13688,8 +13524,8 @@ $as_echo X"$file" | -- # NOTE: Changes made to this file will be lost: look at ltmain.sh. -- # -- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, ---# 2006, 2007, 2008, 2009, 2010, 2011 Free Software ---# Foundation, Inc. --+# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, --+# Inc. -- # Written by Gordon Matzigkeit, 1996 -- # -- # This file is part of GNU Libtool. --@@ -13743,9 +13579,6 @@ SHELL=$lt_SHELL -- # An echo program that protects backslashes. -- ECHO=$lt_ECHO -- ---# The PATH separator for the build system. ---PATH_SEPARATOR=$lt_PATH_SEPARATOR --- -- # The host system. -- host_alias=$host_alias -- host=$host --@@ -14047,6 +13880,10 @@ no_undefined_flag=$lt_no_undefined_flag -- # This must work even if \$libdir does not exist -- hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec -- --+# If ld is used when linking, flag to hardcode \$libdir into a binary --+# during linking. This must work even if \$libdir does not exist. --+hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld --+ -- # Whether we need a single "-rpath" flag with a separated argument. -- hardcode_libdir_separator=$lt_hardcode_libdir_separator -- - --- a/configure.ac - +++ b/configure.ac --@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return -+@@ -44,7 +44,7 @@ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \ - - if test -n "$kbuilddir"; then - AC_MSG_CHECKING([kernel version that we will build against]) --- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease)"; --+ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion)"; -- kmajor="${krel%%[[^0-9]]*}"; -- kmajor="$(($kmajor+0))"; -- krel="${krel:${#kmajor}}"; -+- krel="$(make -sC "$kbuilddir" M=$PWD kernelrelease | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')"; -++ krel="$(make -sC "$kbuilddir" M=$PWD kernelversion | $AWK -v 'FS=[[^0-9.]]' '{print $1; exit}')"; -+ save_IFS=$IFS; -+ IFS='.'; -+ set x $krel; diff --git a/patches/openwrt/0025-tools-add-tar-host-build-required-for-sort-name-which-was-only-added-in-the-latest-version.patch b/patches/openwrt/0025-tools-add-tar-host-build-required-for-sort-name-which-was-only-added-in-the-latest-version.patch deleted file mode 100644 index 52fb08db..00000000 --- a/patches/openwrt/0025-tools-add-tar-host-build-required-for-sort-name-which-was-only-added-in-the-latest-version.patch +++ /dev/null @@ -1,81 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 24 Apr 2016 08:44:30 +0200 -Subject: tools: add tar host build, required for --sort=name which was only added in the latest version - -Signed-off-by: Felix Fietkau - -Backport of r46876 - -diff --git a/tools/Makefile b/tools/Makefile -index c6cded8..98ce8c5 100644 ---- a/tools/Makefile -+++ b/tools/Makefile -@@ -81,6 +81,9 @@ endif - # dependency for tools which have patches directory - $(foreach tool, $(tools-y), $(if $(wildcard $(curdir)/$(tool)/patches),$(eval $(curdir)/$(tool)/compile += $(curdir)/patch/install))) - -+$(foreach tool, $(tools-y), $(eval $(curdir)/$(tool)/compile += $(curdir)/tar/install)) -+tools-y += tar -+ - $(curdir)/builddirs := $(tools-y) $(tools-dep) $(tools-) - $(curdir)/builddirs-default := $(tools-y) - -diff --git a/tools/tar/Makefile b/tools/tar/Makefile -new file mode 100644 -index 0000000..975e783 ---- /dev/null -+++ b/tools/tar/Makefile -@@ -0,0 +1,30 @@ -+# -+# Copyright (C) 2015 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:=tar -+PKG_VERSION:=1.28 -+ -+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -+PKG_SOURCE_URL:=@GNU/tar -+PKG_MD5SUM:=49b6306167724fe48f419a33a5beb857 -+ -+HOST_BUILD_PARALLEL := 1 -+ -+include $(INCLUDE_DIR)/host-build.mk -+ -+HOSTCC := $(HOSTCC_NOCACHE) -+HOSTCXX := $(HOSTCXX_NOCACHE) -+ -+HOST_CONFIGURE_ARGS += \ -+ --without-posix-acls \ -+ --without-selinux \ -+ --without-xattrs \ -+ --disable-acl \ -+ --disable-nls -+ -+$(eval $(call HostBuild)) -diff --git a/tools/tar/patches/100-fix_xattr_disable.patch b/tools/tar/patches/100-fix_xattr_disable.patch -new file mode 100644 -index 0000000..5735bd2 ---- /dev/null -+++ b/tools/tar/patches/100-fix_xattr_disable.patch -@@ -0,0 +1,17 @@ -+--- a/lib/xattr-at.c -++++ b/lib/xattr-at.c -+@@ -18,6 +18,8 @@ -+ -+ #include -+ -++#ifdef HAVE_XATTRS -++ -+ #include "xattr-at.h" -+ #include "openat.h" -+ -+@@ -108,3 +110,5 @@ -+ #undef AT_FUNC_RESULT -+ #undef AT_FUNC_POST_FILE_PARAM_DECLS -+ #undef AT_FUNC_POST_FILE_ARGS -++ -++#endif diff --git a/patches/openwrt/0026-tools-compile-flock-before-everything-else.patch b/patches/openwrt/0026-tools-compile-flock-before-everything-else.patch deleted file mode 100644 index c9291166..00000000 --- a/patches/openwrt/0026-tools-compile-flock-before-everything-else.patch +++ /dev/null @@ -1,31 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 24 Apr 2016 08:44:47 +0200 -Subject: tools: compile flock before everything else - -Signed-off-by: Felix Fietkau - -Backport of r48413 - -diff --git a/tools/Makefile b/tools/Makefile -index 98ce8c5..3402c08 100644 ---- a/tools/Makefile -+++ b/tools/Makefile -@@ -26,7 +26,7 @@ endif - tools-$(BUILD_TOOLCHAIN) += gmp mpfr mpc libelf - tools-y += m4 libtool autoconf automake flex bison pkg-config sed mklibs - tools-y += sstrip make-ext4fs e2fsprogs mtd-utils mkimage --tools-y += firmware-utils patch-image patch quilt yaffs2 flock padjffs2 -+tools-y += firmware-utils patch-image patch quilt yaffs2 padjffs2 - tools-y += mm-macros missing-macros xz cmake scons bc findutils gengetopt patchelf - tools-$(CONFIG_TARGET_orion_generic) += wrt350nv2-builder upslug2 - tools-$(CONFIG_powerpc) += upx -@@ -84,6 +84,9 @@ $(foreach tool, $(tools-y), $(if $(wildcard $(curdir)/$(tool)/patches),$(eval $( - $(foreach tool, $(tools-y), $(eval $(curdir)/$(tool)/compile += $(curdir)/tar/install)) - tools-y += tar - -+$(curdir)/tar/compile := $(curdir)/flock/install -+tools-y += flock -+ - $(curdir)/builddirs := $(tools-y) $(tools-dep) $(tools-) - $(curdir)/builddirs-default := $(tools-y) - diff --git a/patches/openwrt/0027-rules.mk-make-the-locked-template-available-even-if-flock-has-not-been-built-yet-fall-back-to-unlocked-shell-command.patch b/patches/openwrt/0027-rules.mk-make-the-locked-template-available-even-if-flock-has-not-been-built-yet-fall-back-to-unlocked-shell-command.patch deleted file mode 100644 index 5e851cdf..00000000 --- a/patches/openwrt/0027-rules.mk-make-the-locked-template-available-even-if-flock-has-not-been-built-yet-fall-back-to-unlocked-shell-command.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 24 Apr 2016 08:45:44 +0200 -Subject: rules.mk: make the locked template available even if flock has not been built yet (fall back to unlocked shell command) - -Signed-off-by: Felix Fietkau - -Backport of r48414 - -diff --git a/rules.mk b/rules.mk -index 9d0134d..ece5026 100644 ---- a/rules.mk -+++ b/rules.mk -@@ -310,12 +310,16 @@ endef - # Execute commands under flock - # $(1) => The shell expression. - # $(2) => The lock name. If not given, the global lock will be used. --define locked -+ifneq ($(wildcard $(STAGING_DIR_HOST)/bin/flock),) -+ define locked - SHELL= \ -- $(STAGING_DIR_HOST)/bin/flock \ -+ flock \ - $(TMP_DIR)/.$(if $(2),$(strip $(2)),global).flock \ - -c '$(subst ','\'',$(1))' --endef -+ endef -+else -+ locked=$(1) -+endif - - # Recursively copy paths into another directory, purge dangling - # symlinks before. diff --git a/patches/openwrt/0028-build-add-locking-for-downloads-fixes-race-conditions-with-multiple-variants.patch b/patches/openwrt/0028-build-add-locking-for-downloads-fixes-race-conditions-with-multiple-variants.patch deleted file mode 100644 index ffa18527..00000000 --- a/patches/openwrt/0028-build-add-locking-for-downloads-fixes-race-conditions-with-multiple-variants.patch +++ /dev/null @@ -1,20 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 24 Apr 2016 08:48:45 +0200 -Subject: build: add locking for downloads (fixes race conditions with multiple variants) - -Signed-off-by: Felix Fietkau - -Backport of r48416 - -diff --git a/include/download.mk b/include/download.mk -index e518cce..9176b11 100644 ---- a/include/download.mk -+++ b/include/download.mk -@@ -182,6 +182,6 @@ define Download - - $(DL_DIR)/$(FILE): - mkdir -p $(DL_DIR) -- $(if $(DownloadMethod/$(call dl_method,$(URL),$(PROTO))),$(DownloadMethod/$(call dl_method,$(URL),$(PROTO))),$(DownloadMethod/unknown)) -+ $(call locked,$(if $(DownloadMethod/$(call dl_method,$(URL),$(PROTO))),$(DownloadMethod/$(call dl_method,$(URL),$(PROTO))),$(DownloadMethod/unknown)),$(FILE)) - - endef diff --git a/patches/openwrt/0029-download.mk-fix-packed-checkout-mirroring-support.patch b/patches/openwrt/0029-download.mk-fix-packed-checkout-mirroring-support.patch deleted file mode 100644 index 5c0572c1..00000000 --- a/patches/openwrt/0029-download.mk-fix-packed-checkout-mirroring-support.patch +++ /dev/null @@ -1,26 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 24 Apr 2016 08:49:27 +0200 -Subject: download.mk: fix packed checkout mirroring support - -Changeset r48416 broke the downloading of mirrored, packed scm checkouts. - -Fix this by removing the "@" sign in front of the download command which is -now executed as part of a larger shell command under flock. - -Signed-off-by: Jo-Philipp Wich - -Backport of r48733 - -diff --git a/include/download.mk b/include/download.mk -index 9176b11..130bbc5 100644 ---- a/include/download.mk -+++ b/include/download.mk -@@ -48,7 +48,7 @@ define DownloadMethod/default - endef - - define wrap_mirror -- $(if $(if $(MIRROR),$(filter-out x,$(MIRROR_MD5SUM))),@$(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(FILE)" "$(MIRROR_MD5SUM)" "" || ( $(1) ),$(1)) -+$(if $(if $(MIRROR),$(filter-out x,$(MIRROR_MD5SUM))),$(SCRIPT_DIR)/download.pl "$(DL_DIR)" "$(FILE)" "$(MIRROR_MD5SUM)" "" || ( $(1) ),$(1)) - endef - - define DownloadMethod/cvs diff --git a/patches/openwrt/0030-kernel-backport-spi-nor-driver-from-4.4.9.patch b/patches/openwrt/0030-kernel-backport-spi-nor-driver-from-4.4.9.patch deleted file mode 100644 index 7e3ca845..00000000 --- a/patches/openwrt/0030-kernel-backport-spi-nor-driver-from-4.4.9.patch +++ /dev/null @@ -1,2025 +0,0 @@ -From: Matthias Schiffer -Date: Sat, 7 May 2016 00:07:51 +0200 -Subject: kernel: backport spi-nor driver from 4.4.9 - -diff --git a/target/linux/ar71xx/patches-3.18/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch b/target/linux/ar71xx/patches-3.18/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch -index 568f516..6a91320 100644 ---- a/target/linux/ar71xx/patches-3.18/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch -+++ b/target/linux/ar71xx/patches-3.18/407-mtd-m25p80-allow-to-pass-probe-types-via-platform-data.patch -@@ -1,11 +1,11 @@ - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -246,7 +246,9 @@ static int m25p_probe(struct spi_device -+@@ -229,7 +229,9 @@ static int m25p_probe(struct spi_device - - ppdata.of_node = spi->dev.of_node; - --- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, --+ return mtd_device_parse_register(&flash->mtd, -+- return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, -++ return mtd_device_parse_register(&nor->mtd, - + data ? data->part_probes : NULL, - + &ppdata, - data ? data->parts : NULL, -diff --git a/target/linux/ar71xx/patches-3.18/412-mtd-m25p80-zero-partition-parser-data.patch b/target/linux/ar71xx/patches-3.18/412-mtd-m25p80-zero-partition-parser-data.patch -index d51694d..175acf6 100644 ---- a/target/linux/ar71xx/patches-3.18/412-mtd-m25p80-zero-partition-parser-data.patch -+++ b/target/linux/ar71xx/patches-3.18/412-mtd-m25p80-zero-partition-parser-data.patch -@@ -1,10 +1,10 @@ - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -244,6 +244,7 @@ static int m25p_probe(struct spi_device -+@@ -227,6 +227,7 @@ static int m25p_probe(struct spi_device - if (ret) - return ret; - - + memset(&ppdata, '\0', sizeof(ppdata)); - ppdata.of_node = spi->dev.of_node; - -- return mtd_device_parse_register(&flash->mtd, -+ return mtd_device_parse_register(&nor->mtd, -diff --git a/target/linux/ar71xx/patches-3.18/462-mtd-m25p80-set-spi-transfer-type.patch b/target/linux/ar71xx/patches-3.18/462-mtd-m25p80-set-spi-transfer-type.patch -index 3320e5b..11bf9ff 100644 ---- a/target/linux/ar71xx/patches-3.18/462-mtd-m25p80-set-spi-transfer-type.patch -+++ b/target/linux/ar71xx/patches-3.18/462-mtd-m25p80-set-spi-transfer-type.patch -@@ -1,6 +1,6 @@ - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -142,10 +142,12 @@ static int m25p80_read(struct spi_nor *n -+@@ -137,10 +137,12 @@ static int m25p80_read(struct spi_nor *n - flash->command[0] = nor->read_opcode; - m25p_addr2cmd(nor, from, flash->command); - -diff --git a/target/linux/ar71xx/patches-3.18/464-spi-ath79-fix-fast-flash-read.patch b/target/linux/ar71xx/patches-3.18/464-spi-ath79-fix-fast-flash-read.patch -index e48665d..758d231 100644 ---- a/target/linux/ar71xx/patches-3.18/464-spi-ath79-fix-fast-flash-read.patch -+++ b/target/linux/ar71xx/patches-3.18/464-spi-ath79-fix-fast-flash-read.patch -@@ -1,6 +1,6 @@ - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -142,6 +142,9 @@ static int m25p80_read(struct spi_nor *n -+@@ -137,6 +137,9 @@ static int m25p80_read(struct spi_nor *n - flash->command[0] = nor->read_opcode; - m25p_addr2cmd(nor, from, flash->command); - -@@ -25,7 +25,7 @@ - while (len--) { - --- a/include/linux/spi/spi.h - +++ b/include/linux/spi/spi.h --@@ -637,6 +637,7 @@ struct spi_transfer { -+@@ -633,6 +633,7 @@ struct spi_transfer { - u16 delay_usecs; - u32 speed_hz; - enum spi_transfer_type type; -diff --git a/target/linux/brcm63xx/patches-3.18/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch b/target/linux/brcm63xx/patches-3.18/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch -index b949694..be62e67 100644 ---- a/target/linux/brcm63xx/patches-3.18/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch -+++ b/target/linux/brcm63xx/patches-3.18/202-MTD-DEVICES-m25p80-use-parsers-if-provided-in-flash-.patch -@@ -11,12 +11,12 @@ Signed-off-by: Jonas Gorski - - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -246,7 +246,8 @@ static int m25p_probe(struct spi_device -+@@ -229,7 +229,8 @@ static int m25p_probe(struct spi_device - - ppdata.of_node = spi->dev.of_node; - --- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, --+ return mtd_device_parse_register(&flash->mtd, -+- return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, -++ return mtd_device_parse_register(&nor->mtd, - + data ? data->part_probe_types : NULL, &ppdata, - data ? data->parts : NULL, - data ? data->nr_parts : 0); -diff --git a/target/linux/brcm63xx/patches-3.18/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch b/target/linux/brcm63xx/patches-3.18/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch -index 740fb2d..3877442 100644 ---- a/target/linux/brcm63xx/patches-3.18/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch -+++ b/target/linux/brcm63xx/patches-3.18/203-MTD-DEVICES-m25p80-add-support-for-limiting-reads.patch -@@ -11,15 +11,15 @@ Signed-off-by: Jonas Gorski - - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -32,6 +32,7 @@ struct m25p { -+@@ -31,6 +31,7 @@ -+ struct m25p { - struct spi_device *spi; - struct spi_nor spi_nor; -- struct mtd_info mtd; - + int max_transfer_len; - u8 command[MAX_CMD_SIZE]; - }; - --@@ -121,7 +122,7 @@ static inline unsigned int m25p80_rx_nbi -+@@ -119,7 +120,7 @@ static inline unsigned int m25p80_rx_nbi - * Read an address range from the nor chip. The address range - * may be any size provided it is within the physical boundaries. - */ -@@ -28,7 +28,7 @@ Signed-off-by: Jonas Gorski - size_t *retlen, u_char *buf) - { - struct m25p *flash = nor->priv; --@@ -157,6 +158,29 @@ static int m25p80_read(struct spi_nor *n -+@@ -152,6 +153,29 @@ static int m25p80_read(struct spi_nor *n - return 0; - } - -@@ -58,7 +58,7 @@ Signed-off-by: Jonas Gorski - static int m25p80_erase(struct spi_nor *nor, loff_t offset) - { - struct m25p *flash = nor->priv; --@@ -240,6 +264,9 @@ static int m25p_probe(struct spi_device -+@@ -223,6 +247,9 @@ static int m25p_probe(struct spi_device - else - flash_name = spi->modalias; - -diff --git a/target/linux/brcm63xx/patches-3.18/414-MTD-m25p80-allow-passing-pp_data.patch b/target/linux/brcm63xx/patches-3.18/414-MTD-m25p80-allow-passing-pp_data.patch -index b7bf57f..e421e9a 100644 ---- a/target/linux/brcm63xx/patches-3.18/414-MTD-m25p80-allow-passing-pp_data.patch -+++ b/target/linux/brcm63xx/patches-3.18/414-MTD-m25p80-allow-passing-pp_data.patch -@@ -10,7 +10,7 @@ Subject: [PATCH 64/79] MTD: m25p80: allow passing pp_data - - --- a/drivers/mtd/devices/m25p80.c - +++ b/drivers/mtd/devices/m25p80.c --@@ -267,6 +267,9 @@ static int m25p_probe(struct spi_device -+@@ -250,6 +250,9 @@ static int m25p_probe(struct spi_device - if (data) - flash->max_transfer_len = data->max_transfer_len; - -diff --git a/target/linux/generic/patches-3.18/043-mtd_GD25Q128B_support_backport_from_3.19.patch b/target/linux/generic/patches-3.18/043-mtd_GD25Q128B_support_backport_from_3.19.patch -deleted file mode 100644 -index 4d0403b..0000000 ---- a/target/linux/generic/patches-3.18/043-mtd_GD25Q128B_support_backport_from_3.19.patch -+++ /dev/null -@@ -1,10 +0,0 @@ ----- a/drivers/mtd/spi-nor/spi-nor.c --+++ b/drivers/mtd/spi-nor/spi-nor.c --@@ -510,6 +510,7 @@ static const struct spi_device_id spi_no -- /* GigaDevice */ -- { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, -- { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, --+ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, -- -- /* Intel/Numonyx -- xxxs33b */ -- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -diff --git a/target/linux/generic/patches-3.18/093-m25p80_spi-nor_update_to_4.4.9.patch b/target/linux/generic/patches-3.18/093-m25p80_spi-nor_update_to_4.4.9.patch -new file mode 100644 -index 0000000..5f74d3a ---- /dev/null -+++ b/target/linux/generic/patches-3.18/093-m25p80_spi-nor_update_to_4.4.9.patch -@@ -0,0 +1,1579 @@ -+--- a/drivers/mtd/devices/m25p80.c -++++ b/drivers/mtd/devices/m25p80.c -+@@ -31,7 +31,6 @@ -+ struct m25p { -+ struct spi_device *spi; -+ struct spi_nor spi_nor; -+- struct mtd_info mtd; -+ u8 command[MAX_CMD_SIZE]; -+ }; -+ -+@@ -62,8 +61,7 @@ static int m25p_cmdsz(struct spi_nor *no -+ return 1 + nor->addr_width; -+ } -+ -+-static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+- int wr_en) -++static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -+ { -+ struct m25p *flash = nor->priv; -+ struct spi_device *spi = flash->spi; -+@@ -128,13 +126,10 @@ static int m25p80_read(struct spi_nor *n -+ struct spi_device *spi = flash->spi; -+ struct spi_transfer t[2]; -+ struct spi_message m; -+- int dummy = nor->read_dummy; -+- int ret; -++ unsigned int dummy = nor->read_dummy; -+ -+- /* Wait till previous write/erase is done. */ -+- ret = nor->wait_till_ready(nor); -+- if (ret) -+- return ret; -++ /* convert the dummy cycles to the number of bytes */ -++ dummy /= 8; -+ -+ spi_message_init(&m); -+ memset(t, 0, (sizeof t)); -+@@ -160,20 +155,9 @@ static int m25p80_read(struct spi_nor *n -+ static int m25p80_erase(struct spi_nor *nor, loff_t offset) -+ { -+ struct m25p *flash = nor->priv; -+- int ret; -+ -+ dev_dbg(nor->dev, "%dKiB at 0x%08x\n", -+- flash->mtd.erasesize / 1024, (u32)offset); -+- -+- /* Wait until finished previous write command. */ -+- ret = nor->wait_till_ready(nor); -+- if (ret) -+- return ret; -+- -+- /* Send write enable, then erase commands. */ -+- ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -+- if (ret) -+- return ret; -++ flash->spi_nor.mtd.erasesize / 1024, (u32)offset); -+ -+ /* Set up command buffer. */ -+ flash->command[0] = nor->erase_opcode; -+@@ -215,11 +199,10 @@ static int m25p_probe(struct spi_device -+ nor->read_reg = m25p80_read_reg; -+ -+ nor->dev = &spi->dev; -+- nor->mtd = &flash->mtd; -++ nor->flash_node = spi->dev.of_node; -+ nor->priv = flash; -+ -+ spi_set_drvdata(spi, flash); -+- flash->mtd.priv = nor; -+ flash->spi = spi; -+ -+ if (spi->mode & SPI_RX_QUAD) -+@@ -228,7 +211,7 @@ static int m25p_probe(struct spi_device -+ mode = SPI_NOR_DUAL; -+ -+ if (data && data->name) -+- flash->mtd.name = data->name; -++ nor->mtd.name = data->name; -+ -+ /* For some (historical?) reason many platforms provide two different -+ * names in flash_platform_data: "name" and "type". Quite often name is -+@@ -246,7 +229,7 @@ static int m25p_probe(struct spi_device -+ -+ ppdata.of_node = spi->dev.of_node; -+ -+- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, -++ return mtd_device_parse_register(&nor->mtd, NULL, &ppdata, -+ data ? data->parts : NULL, -+ data ? data->nr_parts : 0); -+ } -+@@ -257,64 +240,68 @@ static int m25p_remove(struct spi_device -+ struct m25p *flash = spi_get_drvdata(spi); -+ -+ /* Clean up MTD stuff. */ -+- return mtd_device_unregister(&flash->mtd); -++ return mtd_device_unregister(&flash->spi_nor.mtd); -+ } -+ -+- -+ /* -+- * XXX This needs to be kept in sync with spi_nor_ids. We can't share -+- * it with spi-nor, because if this is built as a module then modpost -+- * won't be able to read it and add appropriate aliases. -++ * Do NOT add to this array without reading the following: -++ * -++ * Historically, many flash devices are bound to this driver by their name. But -++ * since most of these flash are compatible to some extent, and their -++ * differences can often be differentiated by the JEDEC read-ID command, we -++ * encourage new users to add support to the spi-nor library, and simply bind -++ * against a generic string here (e.g., "jedec,spi-nor"). -++ * -++ * Many flash names are kept here in this list (as well as in spi-nor.c) to -++ * keep them available as module aliases for existing platforms. -+ */ -+ static const struct spi_device_id m25p_ids[] = { -+- {"at25fs010"}, {"at25fs040"}, {"at25df041a"}, {"at25df321a"}, -+- {"at25df641"}, {"at26f004"}, {"at26df081a"}, {"at26df161a"}, -+- {"at26df321"}, {"at45db081d"}, -+- {"en25f32"}, {"en25p32"}, {"en25q32b"}, {"en25p64"}, -+- {"en25q64"}, {"en25qh128"}, {"en25qh256"}, -+- {"f25l32pa"}, -+- {"mr25h256"}, {"mr25h10"}, -+- {"gd25q32"}, {"gd25q64"}, -+- {"160s33b"}, {"320s33b"}, {"640s33b"}, -+- {"mx25l2005a"}, {"mx25l4005a"}, {"mx25l8005"}, {"mx25l1606e"}, -+- {"mx25l3205d"}, {"mx25l3255e"}, {"mx25l6405d"}, {"mx25l12805d"}, -+- {"mx25l12855e"},{"mx25l25635e"},{"mx25l25655e"},{"mx66l51235l"}, -+- {"mx66l1g55g"}, -+- {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q256a"}, -+- {"n25q512a"}, {"n25q512ax3"}, {"n25q00"}, -+- {"pm25lv512"}, {"pm25lv010"}, {"pm25lq032"}, -+- {"s25sl032p"}, {"s25sl064p"}, {"s25fl256s0"}, {"s25fl256s1"}, -+- {"s25fl512s"}, {"s70fl01gs"}, {"s25sl12800"}, {"s25sl12801"}, -+- {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"}, {"s25sl008a"}, -+- {"s25sl016a"}, {"s25sl032a"}, {"s25sl064a"}, {"s25fl008k"}, -+- {"s25fl016k"}, {"s25fl064k"}, -+- {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"}, -+- {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"}, -+- {"sst25wf040"}, -+- {"m25p05"}, {"m25p10"}, {"m25p20"}, {"m25p40"}, -+- {"m25p80"}, {"m25p16"}, {"m25p32"}, {"m25p64"}, -+- {"m25p128"}, {"n25q032"}, -++ /* -++ * Entries not used in DTs that should be safe to drop after replacing -++ * them with "nor-jedec" in platform data. -++ */ -++ {"s25sl064a"}, {"w25x16"}, {"m25p10"}, {"m25px64"}, -++ -++ /* -++ * Entries that were used in DTs without "nor-jedec" fallback and should -++ * be kept for backward compatibility. -++ */ -++ {"at25df321a"}, {"at25df641"}, {"at26df081a"}, -++ {"mr25h256"}, -++ {"mx25l4005a"}, {"mx25l1606e"}, {"mx25l6405d"}, {"mx25l12805d"}, -++ {"mx25l25635e"},{"mx66l51235l"}, -++ {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q512a"}, -++ {"s25fl256s1"}, {"s25fl512s"}, {"s25sl12801"}, {"s25fl008k"}, -++ {"s25fl064k"}, -++ {"sst25vf040b"},{"sst25vf016b"},{"sst25vf032b"},{"sst25wf040"}, -++ {"m25p40"}, {"m25p80"}, {"m25p16"}, {"m25p32"}, -++ {"m25p64"}, {"m25p128"}, -++ {"w25x80"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, -++ {"w25q80bl"}, {"w25q128"}, {"w25q256"}, -++ -++ /* Flashes that can't be detected using JEDEC */ -+ {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"}, -+ {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"}, -+ {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"}, -+- {"m45pe10"}, {"m45pe80"}, {"m45pe16"}, -+- {"m25pe20"}, {"m25pe80"}, {"m25pe16"}, -+- {"m25px16"}, {"m25px32"}, {"m25px32-s0"}, {"m25px32-s1"}, -+- {"m25px64"}, {"m25px80"}, -+- {"w25x10"}, {"w25x20"}, {"w25x40"}, {"w25x80"}, -+- {"w25x16"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"}, -+- {"w25x64"}, {"w25q64"}, {"w25q80"}, {"w25q80bl"}, -+- {"w25q128"}, {"w25q256"}, {"cat25c11"}, -+- {"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"}, -++ -+ { }, -+ }; -+ MODULE_DEVICE_TABLE(spi, m25p_ids); -+ -++static const struct of_device_id m25p_of_table[] = { -++ /* -++ * Generic compatibility for SPI NOR that can be identified by the -++ * JEDEC READ ID opcode (0x9F). Use this, if possible. -++ */ -++ { .compatible = "jedec,spi-nor" }, -++ {} -++}; -++MODULE_DEVICE_TABLE(of, m25p_of_table); -+ -+ static struct spi_driver m25p80_driver = { -+ .driver = { -+ .name = "m25p80", -+- .owner = THIS_MODULE, -++ .of_match_table = m25p_of_table, -+ }, -+ .id_table = m25p_ids, -+ .probe = m25p_probe, -+--- a/drivers/mtd/spi-nor/spi-nor.c -++++ b/drivers/mtd/spi-nor/spi-nor.c -+@@ -16,19 +16,63 @@ -+ #include -+ #include -+ #include -++#include -+ -+-#include -+ #include -+ #include -+ #include -+ #include -+ -+ /* Define max times to check status register before we give up. */ -+-#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ -+ -+-#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) -++/* -++ * For everything but full-chip erase; probably could be much smaller, but kept -++ * around for safety for now -++ */ -++#define DEFAULT_READY_WAIT_JIFFIES (40UL * HZ) -++ -++/* -++ * For full-chip erase, calibrated to a 2MB flash (M25P16); should be scaled up -++ * for larger flash -++ */ -++#define CHIP_ERASE_2MB_READY_WAIT_JIFFIES (40UL * HZ) -++ -++#define SPI_NOR_MAX_ID_LEN 6 -++ -++struct flash_info { -++ char *name; -++ -++ /* -++ * This array stores the ID bytes. -++ * The first three bytes are the JEDIC ID. -++ * JEDEC ID zero means "no ID" (mostly older chips). -++ */ -++ u8 id[SPI_NOR_MAX_ID_LEN]; -++ u8 id_len; -++ -++ /* The size listed here is what works with SPINOR_OP_SE, which isn't -++ * necessarily called a "sector" by the vendor. -++ */ -++ unsigned sector_size; -++ u16 n_sectors; -++ -++ u16 page_size; -++ u16 addr_width; -++ -++ u16 flags; -++#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -++#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -++#define SST_WRITE 0x04 /* use SST byte programming */ -++#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -++#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -++#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -++#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -++#define USE_FSR 0x80 /* use flag status register */ -++}; -+ -+-static const struct spi_device_id *spi_nor_match_id(const char *name); -++#define JEDEC_MFR(info) ((info)->id[0]) -++ -++static const struct flash_info *spi_nor_match_id(const char *name); -+ -+ /* -+ * Read the status register, returning its value in the location -+@@ -98,7 +142,7 @@ static inline int spi_nor_read_dummy_cyc -+ case SPI_NOR_FAST: -+ case SPI_NOR_DUAL: -+ case SPI_NOR_QUAD: -+- return 1; -++ return 8; -+ case SPI_NOR_NORMAL: -+ return 0; -+ } -+@@ -112,7 +156,7 @@ static inline int spi_nor_read_dummy_cyc -+ static inline int write_sr(struct spi_nor *nor, u8 val) -+ { -+ nor->cmd_buf[0] = val; -+- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -++ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1); -+ } -+ -+ /* -+@@ -121,7 +165,7 @@ static inline int write_sr(struct spi_no -+ */ -+ static inline int write_enable(struct spi_nor *nor) -+ { -+- return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -++ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0); -+ } -+ -+ /* -+@@ -129,7 +173,7 @@ static inline int write_enable(struct sp -+ */ -+ static inline int write_disable(struct spi_nor *nor) -+ { -+- return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0); -++ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0); -+ } -+ -+ static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) -+@@ -138,23 +182,24 @@ static inline struct spi_nor *mtd_to_spi -+ } -+ -+ /* Enable/disable 4-byte addressing mode. */ -+-static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) -++static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info, -++ int enable) -+ { -+ int status; -+ bool need_wren = false; -+ u8 cmd; -+ -+- switch (JEDEC_MFR(jedec_id)) { -+- case CFI_MFR_ST: /* Micron, actually */ -++ switch (JEDEC_MFR(info)) { -++ case SNOR_MFR_MICRON: -+ /* Some Micron need WREN command; all will accept it */ -+ need_wren = true; -+- case CFI_MFR_MACRONIX: -+- case 0xEF /* winbond */: -++ case SNOR_MFR_MACRONIX: -++ case SNOR_MFR_WINBOND: -+ if (need_wren) -+ write_enable(nor); -+ -+ cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; -+- status = nor->write_reg(nor, cmd, NULL, 0, 0); -++ status = nor->write_reg(nor, cmd, NULL, 0); -+ if (need_wren) -+ write_disable(nor); -+ -+@@ -162,63 +207,73 @@ static inline int set_4byte(struct spi_n -+ default: -+ /* Spansion style */ -+ nor->cmd_buf[0] = enable << 7; -+- return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); -++ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1); -+ } -+ } -+- -+-static int spi_nor_wait_till_ready(struct spi_nor *nor) -++static inline int spi_nor_sr_ready(struct spi_nor *nor) -+ { -+- unsigned long deadline; -+- int sr; -+- -+- deadline = jiffies + MAX_READY_WAIT_JIFFIES; -+- -+- do { -+- cond_resched(); -++ int sr = read_sr(nor); -++ if (sr < 0) -++ return sr; -++ else -++ return !(sr & SR_WIP); -++} -+ -+- sr = read_sr(nor); -+- if (sr < 0) -+- break; -+- else if (!(sr & SR_WIP)) -+- return 0; -+- } while (!time_after_eq(jiffies, deadline)); -++static inline int spi_nor_fsr_ready(struct spi_nor *nor) -++{ -++ int fsr = read_fsr(nor); -++ if (fsr < 0) -++ return fsr; -++ else -++ return fsr & FSR_READY; -++} -+ -+- return -ETIMEDOUT; -++static int spi_nor_ready(struct spi_nor *nor) -++{ -++ int sr, fsr; -++ sr = spi_nor_sr_ready(nor); -++ if (sr < 0) -++ return sr; -++ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; -++ if (fsr < 0) -++ return fsr; -++ return sr && fsr; -+ } -+ -+-static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) -++/* -++ * Service routine to read status register until ready, or timeout occurs. -++ * Returns non-zero if error. -++ */ -++static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor, -++ unsigned long timeout_jiffies) -+ { -+ unsigned long deadline; -+- int sr; -+- int fsr; -++ int timeout = 0, ret; -+ -+- deadline = jiffies + MAX_READY_WAIT_JIFFIES; -++ deadline = jiffies + timeout_jiffies; -++ -++ while (!timeout) { -++ if (time_after_eq(jiffies, deadline)) -++ timeout = 1; -++ -++ ret = spi_nor_ready(nor); -++ if (ret < 0) -++ return ret; -++ if (ret) -++ return 0; -+ -+- do { -+ cond_resched(); -++ } -+ -+- sr = read_sr(nor); -+- if (sr < 0) { -+- break; -+- } else if (!(sr & SR_WIP)) { -+- fsr = read_fsr(nor); -+- if (fsr < 0) -+- break; -+- if (fsr & FSR_READY) -+- return 0; -+- } -+- } while (!time_after_eq(jiffies, deadline)); -++ dev_err(nor->dev, "flash operation timed out\n"); -+ -+ return -ETIMEDOUT; -+ } -+ -+-/* -+- * Service routine to read status register until ready, or timeout occurs. -+- * Returns non-zero if error. -+- */ -+-static int wait_till_ready(struct spi_nor *nor) -++static int spi_nor_wait_till_ready(struct spi_nor *nor) -+ { -+- return nor->wait_till_ready(nor); -++ return spi_nor_wait_till_ready_with_timeout(nor, -++ DEFAULT_READY_WAIT_JIFFIES); -+ } -+ -+ /* -+@@ -228,19 +283,9 @@ static int wait_till_ready(struct spi_no -+ */ -+ static int erase_chip(struct spi_nor *nor) -+ { -+- int ret; -+- -+- dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); -++ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10)); -+ -+- /* Wait until finished previous write command. */ -+- ret = wait_till_ready(nor); -+- if (ret) -+- return ret; -+- -+- /* Send write enable, then erase commands. */ -+- write_enable(nor); -+- -+- return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); -++ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0); -+ } -+ -+ static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+@@ -294,11 +339,28 @@ static int spi_nor_erase(struct mtd_info -+ -+ /* whole-chip erase? */ -+ if (len == mtd->size) { -++ unsigned long timeout; -++ -++ write_enable(nor); -++ -+ if (erase_chip(nor)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -++ /* -++ * Scale the timeout linearly with the size of the flash, with -++ * a minimum calibrated to an old 2MB flash. We could try to -++ * pull these from CFI/SFDP, but these values should be good -++ * enough for now. -++ */ -++ timeout = max(CHIP_ERASE_2MB_READY_WAIT_JIFFIES, -++ CHIP_ERASE_2MB_READY_WAIT_JIFFIES * -++ (unsigned long)(mtd->size / SZ_2M)); -++ ret = spi_nor_wait_till_ready_with_timeout(nor, timeout); -++ if (ret) -++ goto erase_err; -++ -+ /* REVISIT in some cases we could speed up erasing large regions -+ * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up -+ * to use "small sector erase", but that's not always optimal. -+@@ -307,6 +369,8 @@ static int spi_nor_erase(struct mtd_info -+ /* "sector"-at-a-time erase */ -+ } else { -+ while (len) { -++ write_enable(nor); -++ -+ if (nor->erase(nor, addr)) { -+ ret = -EIO; -+ goto erase_err; -+@@ -314,9 +378,15 @@ static int spi_nor_erase(struct mtd_info -+ -+ addr += mtd->erasesize; -+ len -= mtd->erasesize; -++ -++ ret = spi_nor_wait_till_ready(nor); -++ if (ret) -++ goto erase_err; -+ } -+ } -+ -++ write_disable(nor); -++ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ -+ instr->state = MTD_ERASE_DONE; -+@@ -330,152 +400,267 @@ erase_err: -+ return ret; -+ } -+ -+-static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -++static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs, -++ uint64_t *len) -+ { -+- struct spi_nor *nor = mtd_to_spi_nor(mtd); -+- uint32_t offset = ofs; -+- uint8_t status_old, status_new; -+- int ret = 0; -++ struct mtd_info *mtd = &nor->mtd; -++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -++ int shift = ffs(mask) - 1; -++ int pow; -++ -++ if (!(sr & mask)) { -++ /* No protection */ -++ *ofs = 0; -++ *len = 0; -++ } else { -++ pow = ((sr & mask) ^ mask) >> shift; -++ *len = mtd->size >> pow; -++ *ofs = mtd->size - *len; -++ } -++} -+ -+- ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); -+- if (ret) -+- return ret; -++/* -++ * Return 1 if the entire region is locked, 0 otherwise -++ */ -++static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len, -++ u8 sr) -++{ -++ loff_t lock_offs; -++ uint64_t lock_len; -+ -+- /* Wait until finished previous command */ -+- ret = wait_till_ready(nor); -+- if (ret) -+- goto err; -++ stm_get_locked_range(nor, sr, &lock_offs, &lock_len); -++ -++ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); -++} -++ -++/* -++ * Lock a region of the flash. Compatible with ST Micro and similar flash. -++ * Supports only the block protection bits BP{0,1,2} in the status register -++ * (SR). Does not support these features found in newer SR bitfields: -++ * - TB: top/bottom protect - only handle TB=0 (top protect) -++ * - SEC: sector/block protect - only handle SEC=0 (block protect) -++ * - CMP: complement protect - only support CMP=0 (range is not complemented) -++ * -++ * Sample table portion for 8MB flash (Winbond w25q64fw): -++ * -++ * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion -++ * -------------------------------------------------------------------------- -++ * X | X | 0 | 0 | 0 | NONE | NONE -++ * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 -++ * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 -++ * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 -++ * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 -++ * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 -++ * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 -++ * X | X | 1 | 1 | 1 | 8 MB | ALL -++ * -++ * Returns negative on errors, 0 on success. -++ */ -++static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len) -++{ -++ struct mtd_info *mtd = &nor->mtd; -++ u8 status_old, status_new; -++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -++ u8 shift = ffs(mask) - 1, pow, val; -+ -+ status_old = read_sr(nor); -+ -+- if (offset < mtd->size - (mtd->size / 2)) -+- status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; -+- else if (offset < mtd->size - (mtd->size / 4)) -+- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -+- else if (offset < mtd->size - (mtd->size / 8)) -+- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+- else if (offset < mtd->size - (mtd->size / 16)) -+- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+- else if (offset < mtd->size - (mtd->size / 32)) -+- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+- else if (offset < mtd->size - (mtd->size / 64)) -+- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+- else -+- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -++ /* SPI NOR always locks to the end */ -++ if (ofs + len != mtd->size) { -++ /* Does combined region extend to end? */ -++ if (!stm_is_locked_sr(nor, ofs + len, mtd->size - ofs - len, -++ status_old)) -++ return -EINVAL; -++ len = mtd->size - ofs; -++ } -++ -++ /* -++ * Need smallest pow such that: -++ * -++ * 1 / (2^pow) <= (len / size) -++ * -++ * so (assuming power-of-2 size) we do: -++ * -++ * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) -++ */ -++ pow = ilog2(mtd->size) - ilog2(len); -++ val = mask - (pow << shift); -++ if (val & ~mask) -++ return -EINVAL; -++ /* Don't "lock" with no region! */ -++ if (!(val & mask)) -++ return -EINVAL; -++ -++ status_new = (status_old & ~mask) | val; -+ -+ /* Only modify protection if it will not unlock other areas */ -+- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) > -+- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+- write_enable(nor); -+- ret = write_sr(nor, status_new); -+- if (ret) -+- goto err; -++ if ((status_new & mask) <= (status_old & mask)) -++ return -EINVAL; -++ -++ write_enable(nor); -++ return write_sr(nor, status_new); -++} -++ -++/* -++ * Unlock a region of the flash. See stm_lock() for more info -++ * -++ * Returns negative on errors, 0 on success. -++ */ -++static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) -++{ -++ struct mtd_info *mtd = &nor->mtd; -++ uint8_t status_old, status_new; -++ u8 mask = SR_BP2 | SR_BP1 | SR_BP0; -++ u8 shift = ffs(mask) - 1, pow, val; -++ -++ status_old = read_sr(nor); -++ -++ /* Cannot unlock; would unlock larger region than requested */ -++ if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, -++ status_old)) -++ return -EINVAL; -++ -++ /* -++ * Need largest pow such that: -++ * -++ * 1 / (2^pow) >= (len / size) -++ * -++ * so (assuming power-of-2 size) we do: -++ * -++ * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) -++ */ -++ pow = ilog2(mtd->size) - order_base_2(mtd->size - (ofs + len)); -++ if (ofs + len == mtd->size) { -++ val = 0; /* fully unlocked */ -++ } else { -++ val = mask - (pow << shift); -++ /* Some power-of-two sizes are not supported */ -++ if (val & ~mask) -++ return -EINVAL; -+ } -+ -+-err: -+- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+- return ret; -++ status_new = (status_old & ~mask) | val; -++ -++ /* Only modify protection if it will not lock other areas */ -++ if ((status_new & mask) >= (status_old & mask)) -++ return -EINVAL; -++ -++ write_enable(nor); -++ return write_sr(nor, status_new); -+ } -+ -+-static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -++/* -++ * Check if a region of the flash is (completely) locked. See stm_lock() for -++ * more info. -++ * -++ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and -++ * negative on errors. -++ */ -++static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len) -++{ -++ int status; -++ -++ status = read_sr(nor); -++ if (status < 0) -++ return status; -++ -++ return stm_is_locked_sr(nor, ofs, len, status); -++} -++ -++static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+ { -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+- uint32_t offset = ofs; -+- uint8_t status_old, status_new; -+- int ret = 0; -++ int ret; -+ -+- ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); -+ if (ret) -+ return ret; -+ -+- /* Wait until finished previous command */ -+- ret = wait_till_ready(nor); -+- if (ret) -+- goto err; -++ ret = nor->flash_lock(nor, ofs, len); -+ -+- status_old = read_sr(nor); -++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); -++ return ret; -++} -+ -+- if (offset+len > mtd->size - (mtd->size / 64)) -+- status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); -+- else if (offset+len > mtd->size - (mtd->size / 32)) -+- status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -+- else if (offset+len > mtd->size - (mtd->size / 16)) -+- status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+- else if (offset+len > mtd->size - (mtd->size / 8)) -+- status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+- else if (offset+len > mtd->size - (mtd->size / 4)) -+- status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+- else if (offset+len > mtd->size - (mtd->size / 2)) -+- status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+- else -+- status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -++static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -++{ -++ struct spi_nor *nor = mtd_to_spi_nor(mtd); -++ int ret; -+ -+- /* Only modify protection if it will not lock other areas */ -+- if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < -+- (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+- write_enable(nor); -+- ret = write_sr(nor, status_new); -+- if (ret) -+- goto err; -+- } -++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -++ if (ret) -++ return ret; -+ -+-err: -+- spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); -++ ret = nor->flash_unlock(nor, ofs, len); -++ -++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+ return ret; -+ } -+ -+-struct flash_info { -+- /* JEDEC id zero means "no ID" (most older chips); otherwise it has -+- * a high byte of zero plus three data bytes: the manufacturer id, -+- * then a two byte device id. -+- */ -+- u32 jedec_id; -+- u16 ext_id; -++static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) -++{ -++ struct spi_nor *nor = mtd_to_spi_nor(mtd); -++ int ret; -+ -+- /* The size listed here is what works with SPINOR_OP_SE, which isn't -+- * necessarily called a "sector" by the vendor. -+- */ -+- unsigned sector_size; -+- u16 n_sectors; -++ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -++ if (ret) -++ return ret; -+ -+- u16 page_size; -+- u16 addr_width; -++ ret = nor->flash_is_locked(nor, ofs, len); -+ -+- u16 flags; -+-#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -+-#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -+-#define SST_WRITE 0x04 /* use SST byte programming */ -+-#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -+-#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -+-#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -+-#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -+-#define USE_FSR 0x80 /* use flag status register */ -+-}; -++ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -++ return ret; -++} -+ -++/* Used when the "_ext_id" is two bytes at most */ -+ #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+- ((kernel_ulong_t)&(struct flash_info) { \ -+- .jedec_id = (_jedec_id), \ -+- .ext_id = (_ext_id), \ -++ .id = { \ -++ ((_jedec_id) >> 16) & 0xff, \ -++ ((_jedec_id) >> 8) & 0xff, \ -++ (_jedec_id) & 0xff, \ -++ ((_ext_id) >> 8) & 0xff, \ -++ (_ext_id) & 0xff, \ -++ }, \ -++ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ -++ .sector_size = (_sector_size), \ -++ .n_sectors = (_n_sectors), \ -++ .page_size = 256, \ -++ .flags = (_flags), -++ -++#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -++ .id = { \ -++ ((_jedec_id) >> 16) & 0xff, \ -++ ((_jedec_id) >> 8) & 0xff, \ -++ (_jedec_id) & 0xff, \ -++ ((_ext_id) >> 16) & 0xff, \ -++ ((_ext_id) >> 8) & 0xff, \ -++ (_ext_id) & 0xff, \ -++ }, \ -++ .id_len = 6, \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+- .flags = (_flags), \ -+- }) -++ .flags = (_flags), -+ -+ #define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ -+- ((kernel_ulong_t)&(struct flash_info) { \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = (_page_size), \ -+ .addr_width = (_addr_width), \ -+- .flags = (_flags), \ -+- }) -++ .flags = (_flags), -+ -+ /* NOTE: double check command sets and memory organization when you add -+ * more nor chips. This current list focusses on newer chips, which -+ * have been converging on command sets which including JEDEC ID. -++ * -++ * All newly added entries should describe *hardware* and should use SECT_4K -++ * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage -++ * scenarios excluding small sectors there is config option that can be -++ * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS. -++ * For historical (and compatibility) reasons (before we got above config) some -++ * old entries may be missing 4K flag. -+ */ -+-static const struct spi_device_id spi_nor_ids[] = { -++static const struct flash_info spi_nor_ids[] = { -+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */ -+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, -+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, -+@@ -499,6 +684,7 @@ static const struct spi_device_id spi_no -+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, -+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, -++ { "en25s64", INFO(0x1c3817, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* ESMT */ -+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, -+@@ -507,16 +693,24 @@ static const struct spi_device_id spi_no -+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ -++ /* Fujitsu */ -++ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, -++ -+ /* GigaDevice */ -+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -++ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, -+ -+ /* Intel/Numonyx -- xxxs33b */ -+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -+ -++ /* ISSI */ -++ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, -++ -+ /* Macronix */ -++ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, -+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, -+@@ -524,6 +718,7 @@ static const struct spi_device_id spi_no -+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, -+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, -+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, -++ { "mx25u6435f", INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) }, -+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, -+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, -+@@ -532,13 +727,16 @@ static const struct spi_device_id spi_no -+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -+ -+ /* Micron */ -+- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, -+- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, -+- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, -+- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, -+- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, -+- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, -+- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, -++ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, -++ { "n25q032a", INFO(0x20bb16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, -++ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, -++ { "n25q064a", INFO(0x20bb17, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_QUAD_READ) }, -++ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -++ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -++ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, -++ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -++ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -++ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ -+ /* PMC */ -+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -+@@ -549,23 +747,28 @@ static const struct spi_device_id spi_no -+ * for the chips listed here (without boot sectors). -+ */ -+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+- { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, -++ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, -+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, -+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, -+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -+- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, -+- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, -++ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) }, -++ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -++ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, -+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, -+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, -+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, -+- { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, -++ { "s25fl004k", INFO(0xef4013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -++ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -++ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -++ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, SECT_4K) }, -++ { "s25fl164k", INFO(0x014017, 0, 64 * 1024, 128, SECT_4K) }, -++ { "s25fl204k", INFO(0x014013, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_DUAL_READ) }, -+ -+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */ -+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+@@ -576,7 +779,10 @@ static const struct spi_device_id spi_no -+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, -+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, -+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, -++ { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) }, -++ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) }, -+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -++ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, -+ -+ /* ST Microelectronics -- newer production may have feature updates */ -+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, -+@@ -588,7 +794,6 @@ static const struct spi_device_id spi_no -+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, -+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, -+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, -+- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, -+ -+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, -+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, -+@@ -616,6 +821,7 @@ static const struct spi_device_id spi_no -+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, -+ -+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ -++ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, -+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, -+@@ -623,9 +829,11 @@ static const struct spi_device_id spi_no -+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, -+- { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, -++ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -++ { "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -++ { "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+@@ -640,35 +848,27 @@ static const struct spi_device_id spi_no -+ { }, -+ }; -+ -+-static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) -++static const struct flash_info *spi_nor_read_id(struct spi_nor *nor) -+ { -+ int tmp; -+- u8 id[5]; -+- u32 jedec; -+- u16 ext_jedec; -+- struct flash_info *info; -++ u8 id[SPI_NOR_MAX_ID_LEN]; -++ const struct flash_info *info; -+ -+- tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); -++ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); -+ if (tmp < 0) { -+ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); -+ return ERR_PTR(tmp); -+ } -+- jedec = id[0]; -+- jedec = jedec << 8; -+- jedec |= id[1]; -+- jedec = jedec << 8; -+- jedec |= id[2]; -+- -+- ext_jedec = id[3] << 8 | id[4]; -+ -+ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { -+- info = (void *)spi_nor_ids[tmp].driver_data; -+- if (info->jedec_id == jedec) { -+- if (info->ext_id == 0 || info->ext_id == ext_jedec) -++ info = &spi_nor_ids[tmp]; -++ if (info->id_len) { -++ if (!memcmp(info->id, id, info->id_len)) -+ return &spi_nor_ids[tmp]; -+ } -+ } -+- dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); -++ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", -++ id[0], id[1], id[2]); -+ return ERR_PTR(-ENODEV); -+ } -+ -+@@ -703,11 +903,6 @@ static int sst_write(struct mtd_info *mt -+ if (ret) -+ return ret; -+ -+- /* Wait until finished previous write command. */ -+- ret = wait_till_ready(nor); -+- if (ret) -+- goto time_out; -+- -+ write_enable(nor); -+ -+ nor->sst_write_second = false; -+@@ -719,7 +914,7 @@ static int sst_write(struct mtd_info *mt -+ -+ /* write one byte. */ -+ nor->write(nor, to, 1, retlen, buf); -+- ret = wait_till_ready(nor); -++ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ } -+@@ -731,7 +926,7 @@ static int sst_write(struct mtd_info *mt -+ -+ /* write two bytes. */ -+ nor->write(nor, to, 2, retlen, buf + actual); -+- ret = wait_till_ready(nor); -++ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ to += 2; -+@@ -740,7 +935,7 @@ static int sst_write(struct mtd_info *mt -+ nor->sst_write_second = false; -+ -+ write_disable(nor); -+- ret = wait_till_ready(nor); -++ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+@@ -751,7 +946,7 @@ static int sst_write(struct mtd_info *mt -+ nor->program_opcode = SPINOR_OP_BP; -+ nor->write(nor, to, 1, retlen, buf + actual); -+ -+- ret = wait_till_ready(nor); -++ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ write_disable(nor); -+@@ -779,11 +974,6 @@ static int spi_nor_write(struct mtd_info -+ if (ret) -+ return ret; -+ -+- /* Wait until finished previous write command. */ -+- ret = wait_till_ready(nor); -+- if (ret) -+- goto write_err; -+- -+ write_enable(nor); -+ -+ page_offset = to & (nor->page_size - 1); -+@@ -802,16 +992,20 @@ static int spi_nor_write(struct mtd_info -+ if (page_size > nor->page_size) -+ page_size = nor->page_size; -+ -+- wait_till_ready(nor); -++ ret = spi_nor_wait_till_ready(nor); -++ if (ret) -++ goto write_err; -++ -+ write_enable(nor); -+ -+ nor->write(nor, to + i, page_size, retlen, buf + i); -+ } -+ } -+ -++ ret = spi_nor_wait_till_ready(nor); -+ write_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+- return 0; -++ return ret; -+ } -+ -+ static int macronix_quad_enable(struct spi_nor *nor) -+@@ -821,10 +1015,9 @@ static int macronix_quad_enable(struct s -+ val = read_sr(nor); -+ write_enable(nor); -+ -+- nor->cmd_buf[0] = val | SR_QUAD_EN_MX; -+- nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -++ write_sr(nor, val | SR_QUAD_EN_MX); -+ -+- if (wait_till_ready(nor)) -++ if (spi_nor_wait_till_ready(nor)) -+ return 1; -+ -+ ret = read_sr(nor); -+@@ -847,7 +1040,7 @@ static int write_sr_cr(struct spi_nor *n -+ nor->cmd_buf[0] = val & 0xff; -+ nor->cmd_buf[1] = (val >> 8); -+ -+- return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0); -++ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2); -+ } -+ -+ static int spansion_quad_enable(struct spi_nor *nor) -+@@ -874,18 +1067,20 @@ static int spansion_quad_enable(struct s -+ return 0; -+ } -+ -+-static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) -++static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info) -+ { -+ int status; -+ -+- switch (JEDEC_MFR(jedec_id)) { -+- case CFI_MFR_MACRONIX: -++ switch (JEDEC_MFR(info)) { -++ case SNOR_MFR_MACRONIX: -+ status = macronix_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Macronix quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -++ case SNOR_MFR_MICRON: -++ return 0; -+ default: -+ status = spansion_quad_enable(nor); -+ if (status) { -+@@ -904,21 +1099,15 @@ static int spi_nor_check(struct spi_nor -+ return -EINVAL; -+ } -+ -+- if (!nor->read_id) -+- nor->read_id = spi_nor_read_id; -+- if (!nor->wait_till_ready) -+- nor->wait_till_ready = spi_nor_wait_till_ready; -+- -+ return 0; -+ } -+ -+ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) -+ { -+- const struct spi_device_id *id = NULL; -+- struct flash_info *info; -++ const struct flash_info *info = NULL; -+ struct device *dev = nor->dev; -+- struct mtd_info *mtd = nor->mtd; -+- struct device_node *np = dev->of_node; -++ struct mtd_info *mtd = &nor->mtd; -++ struct device_node *np = nor->flash_node; -+ int ret; -+ int i; -+ -+@@ -926,19 +1115,25 @@ int spi_nor_scan(struct spi_nor *nor, co -+ if (ret) -+ return ret; -+ -+- id = spi_nor_match_id(name); -+- if (!id) -++ if (name) -++ info = spi_nor_match_id(name); -++ /* Try to auto-detect if chip name wasn't specified or not found */ -++ if (!info) -++ info = spi_nor_read_id(nor); -++ if (IS_ERR_OR_NULL(info)) -+ return -ENOENT; -+ -+- info = (void *)id->driver_data; -+- -+- if (info->jedec_id) { -+- const struct spi_device_id *jid; -++ /* -++ * If caller has specified name of flash model that can normally be -++ * detected using JEDEC, let's verify it. -++ */ -++ if (name && info->id_len) { -++ const struct flash_info *jinfo; -+ -+- jid = nor->read_id(nor); -+- if (IS_ERR(jid)) { -+- return PTR_ERR(jid); -+- } else if (jid != id) { -++ jinfo = spi_nor_read_id(nor); -++ if (IS_ERR(jinfo)) { -++ return PTR_ERR(jinfo); -++ } else if (jinfo != info) { -+ /* -+ * JEDEC knows better, so overwrite platform ID. We -+ * can't trust partitions any longer, but we'll let -+@@ -947,28 +1142,28 @@ int spi_nor_scan(struct spi_nor *nor, co -+ * information, even if it's not 100% accurate. -+ */ -+ dev_warn(dev, "found %s, expected %s\n", -+- jid->name, id->name); -+- id = jid; -+- info = (void *)jid->driver_data; -++ jinfo->name, info->name); -++ info = jinfo; -+ } -+ } -+ -+ mutex_init(&nor->lock); -+ -+ /* -+- * Atmel, SST and Intel/Numonyx serial nor tend to power -+- * up with the software protection bits set -++ * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up -++ * with the software protection bits set -+ */ -+ -+- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || -+- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || -+- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { -++ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || -++ JEDEC_MFR(info) == SNOR_MFR_INTEL || -++ JEDEC_MFR(info) == SNOR_MFR_SST) { -+ write_enable(nor); -+ write_sr(nor, 0); -+ } -+ -+ if (!mtd->name) -+ mtd->name = dev_name(dev); -++ mtd->priv = nor; -+ mtd->type = MTD_NORFLASH; -+ mtd->writesize = 1; -+ mtd->flags = MTD_CAP_NORFLASH; -+@@ -976,10 +1171,17 @@ int spi_nor_scan(struct spi_nor *nor, co -+ mtd->_erase = spi_nor_erase; -+ mtd->_read = spi_nor_read; -+ -+- /* nor protection support for STmicro chips */ -+- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { -++ /* NOR protection support for STmicro/Micron chips and similar */ -++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { -++ nor->flash_lock = stm_lock; -++ nor->flash_unlock = stm_unlock; -++ nor->flash_is_locked = stm_is_locked; -++ } -++ -++ if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) { -+ mtd->_lock = spi_nor_lock; -+ mtd->_unlock = spi_nor_unlock; -++ mtd->_is_locked = spi_nor_is_locked; -+ } -+ -+ /* sst nor chips use AAI word program */ -+@@ -988,9 +1190,8 @@ int spi_nor_scan(struct spi_nor *nor, co -+ else -+ mtd->_write = spi_nor_write; -+ -+- if ((info->flags & USE_FSR) && -+- nor->wait_till_ready == spi_nor_wait_till_ready) -+- nor->wait_till_ready = spi_nor_wait_till_fsr_ready; -++ if (info->flags & USE_FSR) -++ nor->flags |= SNOR_F_USE_FSR; -+ -+ #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS -+ /* prefer "small sector" erase if possible */ -+@@ -1031,7 +1232,7 @@ int spi_nor_scan(struct spi_nor *nor, co -+ -+ /* Quad/Dual-read mode takes precedence over fast/normal */ -+ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -+- ret = set_quad_mode(nor, info->jedec_id); -++ ret = set_quad_mode(nor, info); -+ if (ret) { -+ dev_err(dev, "quad mode not supported\n"); -+ return ret; -+@@ -1067,7 +1268,7 @@ int spi_nor_scan(struct spi_nor *nor, co -+ else if (mtd->size > 0x1000000) { -+ /* enable 4-byte addressing if the device exceeds 16MiB */ -+ nor->addr_width = 4; -+- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { -++ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { -+ /* Dedicated 4-byte command set */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+@@ -1088,14 +1289,14 @@ int spi_nor_scan(struct spi_nor *nor, co -+ nor->erase_opcode = SPINOR_OP_SE_4B; -+ mtd->erasesize = info->sector_size; -+ } else -+- set_4byte(nor, info->jedec_id, 1); -++ set_4byte(nor, info, 1); -+ } else { -+ nor->addr_width = 3; -+ } -+ -+ nor->read_dummy = spi_nor_read_dummy_cycles(nor); -+ -+- dev_info(dev, "%s (%lld Kbytes)\n", id->name, -++ dev_info(dev, "%s (%lld Kbytes)\n", info->name, -+ (long long)mtd->size >> 10); -+ -+ dev_dbg(dev, -+@@ -1118,11 +1319,11 @@ int spi_nor_scan(struct spi_nor *nor, co -+ } -+ EXPORT_SYMBOL_GPL(spi_nor_scan); -+ -+-static const struct spi_device_id *spi_nor_match_id(const char *name) -++static const struct flash_info *spi_nor_match_id(const char *name) -+ { -+- const struct spi_device_id *id = spi_nor_ids; -++ const struct flash_info *id = spi_nor_ids; -+ -+- while (id->name[0]) { -++ while (id->name) { -+ if (!strcmp(name, id->name)) -+ return id; -+ id++; -+--- a/include/linux/mtd/spi-nor.h -++++ b/include/linux/mtd/spi-nor.h -+@@ -10,6 +10,23 @@ -+ #ifndef __LINUX_MTD_SPI_NOR_H -+ #define __LINUX_MTD_SPI_NOR_H -+ -++#include -++#include -++ -++/* -++ * Manufacturer IDs -++ * -++ * The first byte returned from the flash after sending opcode SPINOR_OP_RDID. -++ * Sometimes these are the same as CFI IDs, but sometimes they aren't. -++ */ -++#define SNOR_MFR_ATMEL CFI_MFR_ATMEL -++#define SNOR_MFR_INTEL CFI_MFR_INTEL -++#define SNOR_MFR_MICRON CFI_MFR_ST /* ST Micro <--> Micron */ -++#define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX -++#define SNOR_MFR_SPANSION CFI_MFR_AMD -++#define SNOR_MFR_SST CFI_MFR_SST -++#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ -++ -+ /* -+ * Note on opcode nomenclature: some opcodes have a format like -+ * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number -+@@ -56,22 +73,29 @@ -+ /* Used for Spansion flashes only. */ -+ #define SPINOR_OP_BRWR 0x17 /* Bank register write */ -+ -++/* Used for Micron flashes only. */ -++#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ -++#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ -++ -+ /* Status Register bits. */ -+-#define SR_WIP 1 /* Write in progress */ -+-#define SR_WEL 2 /* Write enable latch */ -++#define SR_WIP BIT(0) /* Write in progress */ -++#define SR_WEL BIT(1) /* Write enable latch */ -+ /* meaning of other SR_* bits may differ between vendors */ -+-#define SR_BP0 4 /* Block protect 0 */ -+-#define SR_BP1 8 /* Block protect 1 */ -+-#define SR_BP2 0x10 /* Block protect 2 */ -+-#define SR_SRWD 0x80 /* SR write protect */ -++#define SR_BP0 BIT(2) /* Block protect 0 */ -++#define SR_BP1 BIT(3) /* Block protect 1 */ -++#define SR_BP2 BIT(4) /* Block protect 2 */ -++#define SR_SRWD BIT(7) /* SR write protect */ -++ -++#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ -+ -+-#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ -++/* Enhanced Volatile Configuration Register bits */ -++#define EVCR_QUAD_EN_MICRON BIT(7) /* Micron Quad I/O */ -+ -+ /* Flag Status Register bits */ -+-#define FSR_READY 0x80 -++#define FSR_READY BIT(7) -+ -+ /* Configuration Register bits. */ -+-#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ -++#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ -+ -+ enum read_mode { -+ SPI_NOR_NORMAL = 0, -+@@ -80,33 +104,6 @@ enum read_mode { -+ SPI_NOR_QUAD, -+ }; -+ -+-/** -+- * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer -+- * @wren: command for "Write Enable", or 0x00 for not required -+- * @cmd: command for operation -+- * @cmd_pins: number of pins to send @cmd (1, 2, 4) -+- * @addr: address for operation -+- * @addr_pins: number of pins to send @addr (1, 2, 4) -+- * @addr_width: number of address bytes -+- * (3,4, or 0 for address not required) -+- * @mode: mode data -+- * @mode_pins: number of pins to send @mode (1, 2, 4) -+- * @mode_cycles: number of mode cycles (0 for mode not required) -+- * @dummy_cycles: number of dummy cycles (0 for dummy not required) -+- */ -+-struct spi_nor_xfer_cfg { -+- u8 wren; -+- u8 cmd; -+- u8 cmd_pins; -+- u32 addr; -+- u8 addr_pins; -+- u8 addr_width; -+- u8 mode; -+- u8 mode_pins; -+- u8 mode_cycles; -+- u8 dummy_cycles; -+-}; -+- -+ #define SPI_NOR_MAX_CMD_SIZE 8 -+ enum spi_nor_ops { -+ SPI_NOR_OPS_READ = 0, -+@@ -116,11 +113,18 @@ enum spi_nor_ops { -+ SPI_NOR_OPS_UNLOCK, -+ }; -+ -++enum spi_nor_option_flags { -++ SNOR_F_USE_FSR = BIT(0), -++}; -++ -++struct mtd_info; -++ -+ /** -+ * struct spi_nor - Structure for defining a the SPI NOR layer -+ * @mtd: point to a mtd_info structure -+ * @lock: the lock for the read/write/erase/lock/unlock operations -+ * @dev: point to a spi device, or a spi nor controller device. -++ * @flash_node: point to a device node describing this flash instance. -+ * @page_size: the page size of the SPI NOR -+ * @addr_width: number of address bytes -+ * @erase_opcode: the opcode for erasing a sector -+@@ -129,29 +133,29 @@ enum spi_nor_ops { -+ * @program_opcode: the program opcode -+ * @flash_read: the mode of the read -+ * @sst_write_second: used by the SST write operation -+- * @cfg: used by the read_xfer/write_xfer -++ * @flags: flag options for the current SPI-NOR (SNOR_F_*) -+ * @cmd_buf: used by the write_reg -+ * @prepare: [OPTIONAL] do some preparations for the -+ * read/write/erase/lock/unlock operations -+ * @unprepare: [OPTIONAL] do some post work after the -+ * read/write/erase/lock/unlock operations -+- * @read_xfer: [OPTIONAL] the read fundamental primitive -+- * @write_xfer: [OPTIONAL] the writefundamental primitive -+ * @read_reg: [DRIVER-SPECIFIC] read out the register -+ * @write_reg: [DRIVER-SPECIFIC] write data to the register -+- * @read_id: [REPLACEABLE] read out the ID data, and find -+- * the proper spi_device_id -+- * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready -+ * @read: [DRIVER-SPECIFIC] read data from the SPI NOR -+ * @write: [DRIVER-SPECIFIC] write data to the SPI NOR -+ * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR -+ * at the offset @offs -++ * @flash_lock: [FLASH-SPECIFIC] lock a region of the SPI NOR -++ * @flash_unlock: [FLASH-SPECIFIC] unlock a region of the SPI NOR -++ * @flash_is_locked: [FLASH-SPECIFIC] check if a region of the SPI NOR is -++ * completely locked -+ * @priv: the private data -+ */ -+ struct spi_nor { -+- struct mtd_info *mtd; -++ struct mtd_info mtd; -+ struct mutex lock; -+ struct device *dev; -++ struct device_node *flash_node; -+ u32 page_size; -+ u8 addr_width; -+ u8 erase_opcode; -+@@ -160,20 +164,13 @@ struct spi_nor { -+ u8 program_opcode; -+ enum read_mode flash_read; -+ bool sst_write_second; -+- struct spi_nor_xfer_cfg cfg; -++ u32 flags; -+ u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; -+ -+ int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+ void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+- int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+- u8 *buf, size_t len); -+- int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+- u8 *buf, size_t len); -+ int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); -+- int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+- int write_enable); -+- const struct spi_device_id *(*read_id)(struct spi_nor *nor); -+- int (*wait_till_ready)(struct spi_nor *nor); -++ int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); -+ -+ int (*read)(struct spi_nor *nor, loff_t from, -+ size_t len, size_t *retlen, u_char *read_buf); -+@@ -181,6 +178,10 @@ struct spi_nor { -+ size_t len, size_t *retlen, const u_char *write_buf); -+ int (*erase)(struct spi_nor *nor, loff_t offs); -+ -++ int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len); -++ int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len); -++ int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len); -++ -+ void *priv; -+ }; -+ -diff --git a/target/linux/generic/patches-3.18/462-m25p80-mx-disable-software-protection.patch b/target/linux/generic/patches-3.18/462-m25p80-mx-disable-software-protection.patch -index fef483a..eb99609 100644 ---- a/target/linux/generic/patches-3.18/462-m25p80-mx-disable-software-protection.patch -+++ b/target/linux/generic/patches-3.18/462-m25p80-mx-disable-software-protection.patch -@@ -1,10 +1,14 @@ -+Disable software protection bits for Macronix flashes. -+ -+Signed-off-by: Felix Fietkau -+ - --- a/drivers/mtd/spi-nor/spi-nor.c - +++ b/drivers/mtd/spi-nor/spi-nor.c --@@ -963,6 +963,7 @@ int spi_nor_scan(struct spi_nor *nor, co -+@@ -1164,6 +1164,7 @@ int spi_nor_scan(struct spi_nor *nor, co - -- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || -- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || --+ JEDEC_MFR(info->jedec_id) == CFI_MFR_MACRONIX || -- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { -+ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || -+ JEDEC_MFR(info) == SNOR_MFR_INTEL || -++ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || -+ JEDEC_MFR(info) == SNOR_MFR_SST) { - write_enable(nor); - write_sr(nor, 0); -diff --git a/target/linux/generic/patches-3.18/472-mtd-m25p80-add-support-for-Winbond-W25X05-flash.patch b/target/linux/generic/patches-3.18/472-mtd-m25p80-add-support-for-Winbond-W25X05-flash.patch -deleted file mode 100644 -index dca6895..0000000 ---- a/target/linux/generic/patches-3.18/472-mtd-m25p80-add-support-for-Winbond-W25X05-flash.patch -+++ /dev/null -@@ -1,20 +0,0 @@ --From eef9dfc4e821408af1af13aa0cc707fc496fb7c6 Mon Sep 17 00:00:00 2001 --From: Gabor Juhos --Date: Wed, 11 Dec 2013 19:05:59 +0100 --Subject: [PATCH] m25p80: add support for the Winbond W25X05 flash -- --Signed-off-by: Gabor Juhos ----- -- drivers/mtd/devices/m25p80.c | 1 + -- 1 file changed, 1 insertion(+) -- ----- a/drivers/mtd/spi-nor/spi-nor.c --+++ b/drivers/mtd/spi-nor/spi-nor.c --@@ -617,6 +617,7 @@ static const struct spi_device_id spi_no -- { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, -- -- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ --+ { "w25x05", INFO(0xef3010, 0, 64 * 1024, 1, SECT_4K) }, -- { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -- { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -- { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, -diff --git a/target/linux/generic/patches-3.18/473-mtd-spi-nor-add-support-for-the-Macronix-MX25L512E-S.patch b/target/linux/generic/patches-3.18/473-mtd-spi-nor-add-support-for-the-Macronix-MX25L512E-S.patch -deleted file mode 100644 -index 9ba7a4a..0000000 ---- a/target/linux/generic/patches-3.18/473-mtd-spi-nor-add-support-for-the-Macronix-MX25L512E-S.patch -+++ /dev/null -@@ -1,21 +0,0 @@ --From 0d7388de0911c1a4fc4a8a3898ef9d0ab818ca08 Mon Sep 17 00:00:00 2001 --From: Gabor Juhos --Date: Tue, 7 Apr 2015 18:35:15 +0200 --Subject: [PATCH] mtd: spi-nor: add support for the Macronix MX25L512E SPI -- flash chip -- --Signed-off-by: Gabor Juhos ----- -- drivers/mtd/spi-nor/spi-nor.c | 1 + -- 1 file changed, 1 insertion(+) -- ----- a/drivers/mtd/spi-nor/spi-nor.c --+++ b/drivers/mtd/spi-nor/spi-nor.c --@@ -518,6 +518,7 @@ static const struct spi_device_id spi_no -- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -- -- /* Macronix */ --+ { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, -- { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -- { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, -- { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, -diff --git a/target/linux/generic/patches-3.18/474-mtd-spi-nor-add-support-for-the-ISSI-SI25CD512-SPI-f.patch b/target/linux/generic/patches-3.18/474-mtd-spi-nor-add-support-for-the-ISSI-SI25CD512-SPI-f.patch -deleted file mode 100644 -index b06ac73..0000000 ---- a/target/linux/generic/patches-3.18/474-mtd-spi-nor-add-support-for-the-ISSI-SI25CD512-SPI-f.patch -+++ /dev/null -@@ -1,22 +0,0 @@ --From 34e2b403040a2f9d3ba071d95a7f42457e2950f9 Mon Sep 17 00:00:00 2001 --From: Gabor Juhos --Date: Tue, 7 Apr 2015 18:35:15 +0200 --Subject: [PATCH] mtd: spi-nor: add support for the ISSI SI25CD512 SPI flash -- --Signed-off-by: Gabor Juhos ----- -- drivers/mtd/spi-nor/spi-nor.c | 3 +++ -- 1 file changed, 3 insertions(+) -- ----- a/drivers/mtd/spi-nor/spi-nor.c --+++ b/drivers/mtd/spi-nor/spi-nor.c --@@ -517,6 +517,9 @@ static const struct spi_device_id spi_no -- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -- --+ /* ISSI */ --+ { "is25cd512", INFO(0x7f9d20, 0, 32 * 1024, 2, SECT_4K) }, --+ -- /* Macronix */ -- { "mx25l512e", INFO(0xc22010, 0, 64 * 1024, 1, SECT_4K) }, -- { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -diff --git a/target/linux/lantiq/patches-3.18/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch b/target/linux/lantiq/patches-3.18/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch -deleted file mode 100644 -index 203eb94..0000000 ---- a/target/linux/lantiq/patches-3.18/0022-MTD-m25p80-allow-loading-mtd-name-from-OF.patch -+++ /dev/null -@@ -1,44 +0,0 @@ --From 4400e1f593ea40a51912128adb4f53d59e62cad8 Mon Sep 17 00:00:00 2001 --From: John Crispin --Date: Wed, 10 Sep 2014 22:40:18 +0200 --Subject: [PATCH 22/36] MTD: m25p80: allow loading mtd name from OF -- --In accordance with the physmap flash we should honour the linux,mtd-name --property when deciding what name the mtd device has. -- --Signed-off-by: Thomas Langer --Signed-off-by: John Crispin ----- -- drivers/mtd/devices/m25p80.c | 6 ++++++ -- 1 file changed, 6 insertions(+) -- ----- a/drivers/mtd/devices/m25p80.c --+++ b/drivers/mtd/devices/m25p80.c --@@ -19,6 +19,7 @@ -- #include -- #include -- #include --+#include -- -- #include -- #include --@@ -198,6 +199,10 @@ static int m25p_probe(struct spi_device -- enum read_mode mode = SPI_NOR_NORMAL; -- char *flash_name = NULL; -- int ret; --+ const char __maybe_unused *of_mtd_name = NULL; --+ --+ of_property_read_string(spi->dev.of_node, --+ "linux,mtd-name", &of_mtd_name); -- -- data = dev_get_platdata(&spi->dev); -- --@@ -229,6 +234,8 @@ static int m25p_probe(struct spi_device -- -- if (data && data->name) -- flash->mtd.name = data->name; --+ else if (of_mtd_name) --+ flash->mtd.name = of_mtd_name; -- -- /* For some (historical?) reason many platforms provide two different -- * names in flash_platform_data: "name" and "type". Quite often name is -diff --git a/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts -index 2beb39c..21f823d 100644 ---- a/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts -+++ b/target/linux/mpc85xx/files/arch/powerpc/boot/dts/tl-wdr4900-v1.dts -@@ -37,7 +37,7 @@ - flash@0 { - #address-cells = <1>; - #size-cells = <1>; -- compatible = "spansion,s25fl129p1"; -+ compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <25000000>; - -diff --git a/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch -deleted file mode 100644 -index 1716e1c..0000000 ---- a/target/linux/ramips/patches-3.18/0044-mtd-add-chunked-read-io-to-m25p80.patch -+++ /dev/null -@@ -1,103 +0,0 @@ ----- a/drivers/mtd/devices/m25p80.c --+++ b/drivers/mtd/devices/m25p80.c --@@ -19,6 +19,7 @@ -- #include -- #include -- #include --+#include -- -- #include -- #include --@@ -32,6 +33,7 @@ struct m25p { -- struct spi_device *spi; -- struct spi_nor spi_nor; -- struct mtd_info mtd; --+ u16 chunk_size; -- u8 command[MAX_CMD_SIZE]; -- }; -- --@@ -157,6 +159,61 @@ static int m25p80_read(struct spi_nor *n -- return 0; -- } -- --+static void m25p80_chunked_write(struct spi_nor *nor, loff_t _from, size_t _len, --+ size_t *_retlen, const u_char *_buf) --+{ --+ struct m25p *flash = nor->priv; --+ int chunk_size; --+ int retlen = 0; --+ --+ chunk_size = flash->chunk_size; --+ if (!chunk_size) --+ chunk_size = _len; --+ --+ if (nor->addr_width > 3) --+ chunk_size -= nor->addr_width - 3; --+ --+ while (retlen < _len) { --+ size_t len = min_t(int, chunk_size, _len - retlen); --+ const u_char *buf = _buf + retlen; --+ loff_t from = _from + retlen; --+ --+ nor->wait_till_ready(nor); --+ nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); --+ --+ m25p80_write(nor, from, len, &retlen, buf); --+ } --+ *_retlen += retlen; --+} --+ --+static int m25p80_chunked_read(struct spi_nor *nor, loff_t _from, size_t _len, --+ size_t *_retlen, u_char *_buf) --+{ --+ struct m25p *flash = nor->priv; --+ int chunk_size; --+ --+ chunk_size = flash->chunk_size; --+ if (!chunk_size) --+ chunk_size = _len; --+ --+ *_retlen = 0; --+ --+ while (*_retlen < _len) { --+ size_t len = min_t(int, chunk_size, _len - *_retlen); --+ u_char *buf = _buf + *_retlen; --+ loff_t from = _from + *_retlen; --+ int retlen = 0; --+ int ret = m25p80_read(nor, from, len, &retlen, buf); --+ --+ if (ret) --+ return ret; --+ --+ *_retlen += retlen; --+ } --+ --+ return 0; --+} --+ -- static int m25p80_erase(struct spi_nor *nor, loff_t offset) -- { -- struct m25p *flash = nor->priv; --@@ -197,6 +254,7 @@ static int m25p_probe(struct spi_device -- struct spi_nor *nor; -- enum read_mode mode = SPI_NOR_NORMAL; -- char *flash_name = NULL; --+ u32 val; -- int ret; -- -- data = dev_get_platdata(&spi->dev); --@@ -244,6 +302,14 @@ static int m25p_probe(struct spi_device -- if (ret) -- return ret; -- --+ if (spi->dev.of_node && --+ !of_property_read_u32(spi->dev.of_node, "m25p,chunked-io", &val)) { --+ dev_warn(&spi->dev, "using chunked io\n"); --+ nor->read = m25p80_chunked_read; --+ nor->write = m25p80_chunked_write; --+ flash->chunk_size = val; --+ } --+ -- ppdata.of_node = spi->dev.of_node; -- -- return mtd_device_parse_register(&flash->mtd, NULL, &ppdata, diff --git a/patches/openwrt/0032-kernel-mtd-spi-nor-unlock-Winbond-flashs.patch b/patches/openwrt/0032-kernel-mtd-spi-nor-unlock-Winbond-flashs.patch deleted file mode 100644 index 655f9ab1..00000000 --- a/patches/openwrt/0032-kernel-mtd-spi-nor-unlock-Winbond-flashs.patch +++ /dev/null @@ -1,56 +0,0 @@ -From: Matthias Schiffer -Date: Sat, 7 May 2016 00:29:06 +0200 -Subject: kernel: mtd: spi-nor: unlock Winbond flashs - -diff --git a/target/linux/generic/patches-3.18/463-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch b/target/linux/generic/patches-3.18/463-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch -new file mode 100644 -index 0000000..4682b7a ---- /dev/null -+++ b/target/linux/generic/patches-3.18/463-Revert-mtd-spi-nor-fix-Spansion-regressions-aliased-.patch -@@ -0,0 +1,46 @@ -+From 20bbd73b6b04677a73933830363ab3178adc2ce9 Mon Sep 17 00:00:00 2001 -+Message-Id: <20bbd73b6b04677a73933830363ab3178adc2ce9.1462573588.git.mschiffer@universe-factory.net> -+From: Matthias Schiffer -+Date: Sat, 7 May 2016 00:26:23 +0200 -+Subject: [PATCH] Revert "mtd: spi-nor: fix Spansion regressions (aliased with -+ Winbond)" -+ -+This reverts commit 67b9bcd36906e12a15ffec19463afbbd6a41660e. -+--- -+ drivers/mtd/spi-nor/spi-nor.c | 6 ++++-- -+ include/linux/mtd/spi-nor.h | 2 +- -+ 2 files changed, 5 insertions(+), 3 deletions(-) -+ -+--- a/drivers/mtd/spi-nor/spi-nor.c -++++ b/drivers/mtd/spi-nor/spi-nor.c -+@@ -1165,7 +1165,8 @@ int spi_nor_scan(struct spi_nor *nor, co -+ if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || -+ JEDEC_MFR(info) == SNOR_MFR_INTEL || -+ JEDEC_MFR(info) == SNOR_MFR_MACRONIX || -+- JEDEC_MFR(info) == SNOR_MFR_SST) { -++ JEDEC_MFR(info) == SNOR_MFR_SST || -++ JEDEC_MFR(info) == SNOR_MFR_WINBOND) { -+ write_enable(nor); -+ write_sr(nor, 0); -+ spi_nor_wait_till_ready(nor); -+@@ -1182,7 +1183,8 @@ int spi_nor_scan(struct spi_nor *nor, co -+ mtd->_read = spi_nor_read; -+ -+ /* NOR protection support for STmicro/Micron chips and similar */ -+- if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { -++ if (JEDEC_MFR(info) == SNOR_MFR_MICRON || -++ JEDEC_MFR(info) == SNOR_MFR_WINBOND) { -+ nor->flash_lock = stm_lock; -+ nor->flash_unlock = stm_unlock; -+ nor->flash_is_locked = stm_is_locked; -+--- a/include/linux/mtd/spi-nor.h -++++ b/include/linux/mtd/spi-nor.h -+@@ -25,7 +25,7 @@ -+ #define SNOR_MFR_MACRONIX CFI_MFR_MACRONIX -+ #define SNOR_MFR_SPANSION CFI_MFR_AMD -+ #define SNOR_MFR_SST CFI_MFR_SST -+-#define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */ -++#define SNOR_MFR_WINBOND 0xef -+ -+ /* -+ * Note on opcode nomenclature: some opcodes have a format like diff --git a/patches/openwrt/0033-tools-pkg-config-fix-build-with-GCC-6.patch b/patches/openwrt/0033-tools-pkg-config-fix-build-with-GCC-6.patch deleted file mode 100644 index 840b8b60..00000000 --- a/patches/openwrt/0033-tools-pkg-config-fix-build-with-GCC-6.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 8 May 2016 15:53:14 +0200 -Subject: tools: pkg-config: fix build with GCC 6 - -Fixes the following error: - -gdate.c: In function ‘g_date_strftime’: -gdate.c:2497:7: error: format not a string literal, format string not checked [-Werror=format-nonliteral] - tmplen = strftime (tmpbuf, tmpbufsize, locale_format, &tm); - ^~~~~~ - -Signed-off-by: Matthias Schiffer - -diff --git a/tools/pkg-config/patches/001-glib-gdate-suppress-string-format-literal-warning.patch b/tools/pkg-config/patches/001-glib-gdate-suppress-string-format-literal-warning.patch -new file mode 100644 -index 0000000..6849299 ---- /dev/null -+++ b/tools/pkg-config/patches/001-glib-gdate-suppress-string-format-literal-warning.patch -@@ -0,0 +1,18 @@ -+--- a/glib/glib/gdate.c -++++ b/glib/glib/gdate.c -+@@ -2439,6 +2439,9 @@ win32_strftime_helper (const GDate *d, -+ * -+ * Returns: number of characters written to the buffer, or 0 the buffer was too small -+ */ -++#pragma GCC diagnostic push -++#pragma GCC diagnostic ignored "-Wformat-nonliteral" -++ -+ gsize -+ g_date_strftime (gchar *s, -+ gsize slen, -+@@ -2549,3 +2552,5 @@ g_date_strftime (gchar *s, -+ return retval; -+ #endif -+ } -++ -++#pragma GCC diagnostic pop diff --git a/patches/openwrt/0034-tools-mkimage-sync-include-linux-compiler-.h-with-u-boot-master.patch b/patches/openwrt/0034-tools-mkimage-sync-include-linux-compiler-.h-with-u-boot-master.patch deleted file mode 100644 index edca566c..00000000 --- a/patches/openwrt/0034-tools-mkimage-sync-include-linux-compiler-.h-with-u-boot-master.patch +++ /dev/null @@ -1,815 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 8 May 2016 22:06:51 +0200 -Subject: tools: mkimage: sync include/linux/compiler*.h with u-boot master - -Fixes build with GCC 6. - -Signed-off-by: Matthias Schiffer - -diff --git a/tools/mkimage/patches/200-compiler-support.patch b/tools/mkimage/patches/200-compiler-support.patch -new file mode 100644 -index 0000000..ca9c5b5 ---- /dev/null -+++ b/tools/mkimage/patches/200-compiler-support.patch -@@ -0,0 +1,702 @@ -+diff --git b/include/linux/compiler-gcc.h a/include/linux/compiler-gcc.h -+index e057bd2..22ab246 100644 -+--- b/include/linux/compiler-gcc.h -++++ a/include/linux/compiler-gcc.h -+@@ -5,14 +5,28 @@ -+ /* -+ * Common definitions for all gcc versions go here. -+ */ -+-#define GCC_VERSION (__GNUC__ * 10000 \ -+- + __GNUC_MINOR__ * 100 \ -+- + __GNUC_PATCHLEVEL__) -+- -++#define GCC_VERSION (__GNUC__ * 10000 \ -++ + __GNUC_MINOR__ * 100 \ -++ + __GNUC_PATCHLEVEL__) -+ -+ /* Optimization barrier */ -++ -+ /* The "volatile" is due to gcc bugs */ -+ #define barrier() __asm__ __volatile__("": : :"memory") -++/* -++ * This version is i.e. to prevent dead stores elimination on @ptr -++ * where gcc and llvm may behave differently when otherwise using -++ * normal barrier(): while gcc behavior gets along with a normal -++ * barrier(), llvm needs an explicit input variable to be assumed -++ * clobbered. The issue is as follows: while the inline asm might -++ * access any memory it wants, the compiler could have fit all of -++ * @ptr into memory registers instead, and since @ptr never escaped -++ * from that, it proofed that the inline asm wasn't touching any of -++ * it. This version works well with both compilers, i.e. we're telling -++ * the compiler that the inline asm absolutely may see the contents -++ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495 -++ */ -++#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory") -+ -+ /* -+ * This macro obfuscates arithmetic on a variable address so that gcc -+@@ -32,58 +46,63 @@ -+ * the inline assembly constraint from =g to =r, in this particular -+ * case either is valid. -+ */ -+-#define RELOC_HIDE(ptr, off) \ -+- ({ unsigned long __ptr; \ -+- __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \ -+- (typeof(ptr)) (__ptr + (off)); }) -++#define RELOC_HIDE(ptr, off) \ -++({ \ -++ unsigned long __ptr; \ -++ __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \ -++ (typeof(ptr)) (__ptr + (off)); \ -++}) -+ -+ /* Make the optimizer believe the variable can be manipulated arbitrarily. */ -+-#define OPTIMIZER_HIDE_VAR(var) __asm__ ("" : "=r" (var) : "0" (var)) -++#define OPTIMIZER_HIDE_VAR(var) \ -++ __asm__ ("" : "=r" (var) : "0" (var)) -+ -+ #ifdef __CHECKER__ -+-#define __must_be_array(arr) 0 -++#define __must_be_array(a) 0 -+ #else -+ /* &a[0] degrades to a pointer: a different type from an array */ -+-#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -++#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -+ #endif -+ -+ /* -+ * Force always-inline if the user requests it so via the .config, -+ * or if gcc is too old: -+ */ -+-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ -++#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \ -+ !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4) -+-# define inline inline __attribute__((always_inline)) notrace -+-# define __inline__ __inline__ __attribute__((always_inline)) notrace -+-# define __inline __inline __attribute__((always_inline)) notrace -++#define inline inline __attribute__((always_inline)) notrace -++#define __inline__ __inline__ __attribute__((always_inline)) notrace -++#define __inline __inline __attribute__((always_inline)) notrace -+ #else -+ /* A lot of inline functions can cause havoc with function tracing */ -+-# define inline inline notrace -+-# define __inline__ __inline__ notrace -+-# define __inline __inline notrace -++#define inline inline notrace -++#define __inline__ __inline__ notrace -++#define __inline __inline notrace -+ #endif -+ -+-#define __deprecated __attribute__((deprecated)) -+-#ifndef __packed -+-#define __packed __attribute__((packed)) -+-#endif -+-#ifndef __weak -+-#define __weak __attribute__((weak)) -+-#endif -++#define __always_inline inline __attribute__((always_inline)) -++#define noinline __attribute__((noinline)) -++ -++#define __deprecated __attribute__((deprecated)) -++#define __packed __attribute__((packed)) -++#define __weak __attribute__((weak)) -++#define __alias(symbol) __attribute__((alias(#symbol))) -+ -+ /* -+- * it doesn't make sense on ARM (currently the only user of __naked) to trace -+- * naked functions because then mcount is called without stack and frame pointer -+- * being set up and there is no chance to restore the lr register to the value -+- * before mcount was called. -++ * it doesn't make sense on ARM (currently the only user of __naked) -++ * to trace naked functions because then mcount is called without -++ * stack and frame pointer being set up and there is no chance to -++ * restore the lr register to the value before mcount was called. -++ * -++ * The asm() bodies of naked functions often depend on standard calling -++ * conventions, therefore they must be noinline and noclone. -+ * -+- * The asm() bodies of naked functions often depend on standard calling conventions, -+- * therefore they must be noinline and noclone. GCC 4.[56] currently fail to enforce -+- * this, so we must do so ourselves. See GCC PR44290. -++ * GCC 4.[56] currently fail to enforce this, so we must do so ourselves. -++ * See GCC PR44290. -+ */ -+-#define __naked __attribute__((naked)) noinline __noclone notrace -++#define __naked __attribute__((naked)) noinline __noclone notrace -+ -+-#define __noreturn __attribute__((noreturn)) -++#define __noreturn __attribute__((noreturn)) -+ -+ /* -+ * From the GCC manual: -+@@ -95,34 +114,170 @@ -+ * would be. -+ * [...] -+ */ -+-#ifndef __pure -+-#define __pure __attribute__((pure)) -++#define __pure __attribute__((pure)) -++#define __aligned(x) __attribute__((aligned(x))) -++#define __printf(a, b) __attribute__((format(printf, a, b))) -++#define __scanf(a, b) __attribute__((format(scanf, a, b))) -++#define __attribute_const__ __attribute__((__const__)) -++#define __maybe_unused __attribute__((unused)) -++#define __always_unused __attribute__((unused)) -++ -++/* gcc version specific checks */ -++ -++#if GCC_VERSION < 30200 -++# error Sorry, your compiler is too old - please upgrade it. -++#endif -++ -++#if GCC_VERSION < 30300 -++# define __used __attribute__((__unused__)) -++#else -++# define __used __attribute__((__used__)) -++#endif -++ -++#ifdef CONFIG_GCOV_KERNEL -++# if GCC_VERSION < 30400 -++# error "GCOV profiling support for gcc versions below 3.4 not included" -++# endif /* __GNUC_MINOR__ */ -++#endif /* CONFIG_GCOV_KERNEL */ -++ -++#if GCC_VERSION >= 30400 -++#define __must_check __attribute__((warn_unused_result)) -++#endif -++ -++#if GCC_VERSION >= 40000 -++ -++/* GCC 4.1.[01] miscompiles __weak */ -++#ifdef __KERNEL__ -++# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101 -++# error Your version of gcc miscompiles the __weak directive -++# endif -++#endif -++ -++#define __used __attribute__((__used__)) -++#define __compiler_offsetof(a, b) \ -++ __builtin_offsetof(a, b) -++ -++#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 -++# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -++#endif -++ -++#if GCC_VERSION >= 40300 -++/* Mark functions as cold. gcc will assume any path leading to a call -++ * to them will be unlikely. This means a lot of manual unlikely()s -++ * are unnecessary now for any paths leading to the usual suspects -++ * like BUG(), printk(), panic() etc. [but let's keep them for now for -++ * older compilers] -++ * -++ * Early snapshots of gcc 4.3 don't support this and we can't detect this -++ * in the preprocessor, but we can live with this because they're unreleased. -++ * Maketime probing would be overkill here. -++ * -++ * gcc also has a __attribute__((__hot__)) to move hot functions into -++ * a special section, but I don't see any sense in this right now in -++ * the kernel context -++ */ -++#define __cold __attribute__((__cold__)) -++ -++#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) -++ -++#ifndef __CHECKER__ -++# define __compiletime_warning(message) __attribute__((warning(message))) -++# define __compiletime_error(message) __attribute__((error(message))) -++#endif /* __CHECKER__ */ -++#endif /* GCC_VERSION >= 40300 */ -++ -++#if GCC_VERSION >= 40500 -++/* -++ * Mark a position in code as unreachable. This can be used to -++ * suppress control flow warnings after asm blocks that transfer -++ * control elsewhere. -++ * -++ * Early snapshots of gcc 4.5 don't support this and we can't detect -++ * this in the preprocessor, but we can live with this because they're -++ * unreleased. Really, we need to have autoconf for the kernel. -++ */ -++#define unreachable() __builtin_unreachable() -++ -++/* Mark a function definition as prohibited from being cloned. */ -++#define __noclone __attribute__((__noclone__)) -++ -++#endif /* GCC_VERSION >= 40500 */ -++ -++#if GCC_VERSION >= 40600 -++/* -++ * When used with Link Time Optimization, gcc can optimize away C functions or -++ * variables which are referenced only from assembly code. __visible tells the -++ * optimizer that something else uses this function or variable, thus preventing -++ * this. -++ */ -++#define __visible __attribute__((externally_visible)) -+ #endif -+-#ifndef __aligned -+-#define __aligned(x) __attribute__((aligned(x))) -++ -++ -++#if GCC_VERSION >= 40900 && !defined(__CHECKER__) -++/* -++ * __assume_aligned(n, k): Tell the optimizer that the returned -++ * pointer can be assumed to be k modulo n. The second argument is -++ * optional (default 0), so we use a variadic macro to make the -++ * shorthand. -++ * -++ * Beware: Do not apply this to functions which may return -++ * ERR_PTRs. Also, it is probably unwise to apply it to functions -++ * returning extra information in the low bits (but in that case the -++ * compiler should see some alignment anyway, when the return value is -++ * massaged by 'flags = ptr & 3; ptr &= ~3;'). -++ */ -++#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__))) -+ #endif -+-#define __printf(a, b) __attribute__((format(printf, a, b))) -+-#define __scanf(a, b) __attribute__((format(scanf, a, b))) -+-#define noinline __attribute__((noinline)) -+-#define __attribute_const__ __attribute__((__const__)) -+-#define __maybe_unused __attribute__((unused)) -+-#define __always_unused __attribute__((unused)) -+ -+-#define __gcc_header(x) #x -+-#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h) -+-#define gcc_header(x) _gcc_header(x) -+-#include gcc_header(__GNUC__) -++/* -++ * GCC 'asm goto' miscompiles certain code sequences: -++ * -++ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 -++ * -++ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. -++ * -++ * (asm goto is automatically volatile - the naming reflects this.) -++ */ -++#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) -++ -++#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -++#if GCC_VERSION >= 40400 -++#define __HAVE_BUILTIN_BSWAP32__ -++#define __HAVE_BUILTIN_BSWAP64__ -++#endif -++#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) -++#define __HAVE_BUILTIN_BSWAP16__ -++#endif -++#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ -++ -++#if GCC_VERSION >= 50000 -++#define KASAN_ABI_VERSION 4 -++#elif GCC_VERSION >= 40902 -++#define KASAN_ABI_VERSION 3 -++#endif -++ -++#if GCC_VERSION >= 40902 -++/* -++ * Tell the compiler that address safety instrumentation (KASAN) -++ * should not be applied to that function. -++ * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 -++ */ -++#define __no_sanitize_address __attribute__((no_sanitize_address)) -++#endif -++ -++#endif /* gcc version >= 40000 specific checks */ -+ -+ #if !defined(__noclone) -+ #define __noclone /* not needed */ -+ #endif -+ -++#if !defined(__no_sanitize_address) -++#define __no_sanitize_address -++#endif -++ -+ /* -+ * A trick to suppress uninitialized variable warning without generating any -+ * code -+ */ -+ #define uninitialized_var(x) x = x -+- -+-#ifndef __always_inline -+-#define __always_inline inline __attribute__((always_inline)) -+-#endif -+diff --git b/include/linux/compiler-gcc3.h a/include/linux/compiler-gcc3.h -+deleted file mode 100644 -+index 7d89feb..0000000 -+--- b/include/linux/compiler-gcc3.h -++++ /dev/null -+@@ -1,23 +0,0 @@ -+-#ifndef __LINUX_COMPILER_H -+-#error "Please don't include directly, include instead." -+-#endif -+- -+-#if GCC_VERSION < 30200 -+-# error Sorry, your compiler is too old - please upgrade it. -+-#endif -+- -+-#if GCC_VERSION >= 30300 -+-# define __used __attribute__((__used__)) -+-#else -+-# define __used __attribute__((__unused__)) -+-#endif -+- -+-#if GCC_VERSION >= 30400 -+-#define __must_check __attribute__((warn_unused_result)) -+-#endif -+- -+-#ifdef CONFIG_GCOV_KERNEL -+-# if GCC_VERSION < 30400 -+-# error "GCOV profiling support for gcc versions below 3.4 not included" -+-# endif /* __GNUC_MINOR__ */ -+-#endif /* CONFIG_GCOV_KERNEL */ -+diff --git b/include/linux/compiler-gcc4.h a/include/linux/compiler-gcc4.h -+deleted file mode 100644 -+index c982a09..0000000 -+--- b/include/linux/compiler-gcc4.h -++++ /dev/null -+@@ -1,81 +0,0 @@ -+-#ifndef __LINUX_COMPILER_H -+-#error "Please don't include directly, include instead." -+-#endif -+- -+-#define __used __attribute__((__used__)) -+-#define __must_check __attribute__((warn_unused_result)) -+-#define __compiler_offsetof(a,b) __builtin_offsetof(a,b) -+- -+-#if GCC_VERSION >= 40100 && GCC_VERSION < 40600 -+-# define __compiletime_object_size(obj) __builtin_object_size(obj, 0) -+-#endif -+- -+-#if GCC_VERSION >= 40300 -+-/* Mark functions as cold. gcc will assume any path leading to a call -+- to them will be unlikely. This means a lot of manual unlikely()s -+- are unnecessary now for any paths leading to the usual suspects -+- like BUG(), printk(), panic() etc. [but let's keep them for now for -+- older compilers] -+- -+- Early snapshots of gcc 4.3 don't support this and we can't detect this -+- in the preprocessor, but we can live with this because they're unreleased. -+- Maketime probing would be overkill here. -+- -+- gcc also has a __attribute__((__hot__)) to move hot functions into -+- a special section, but I don't see any sense in this right now in -+- the kernel context */ -+-#define __cold __attribute__((__cold__)) -+- -+-#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) -+- -+-#ifndef __CHECKER__ -+-# define __compiletime_warning(message) __attribute__((warning(message))) -+-# define __compiletime_error(message) __attribute__((error(message))) -+-#endif /* __CHECKER__ */ -+-#endif /* GCC_VERSION >= 40300 */ -+- -+-#if GCC_VERSION >= 40500 -+-/* -+- * Mark a position in code as unreachable. This can be used to -+- * suppress control flow warnings after asm blocks that transfer -+- * control elsewhere. -+- * -+- * Early snapshots of gcc 4.5 don't support this and we can't detect -+- * this in the preprocessor, but we can live with this because they're -+- * unreleased. Really, we need to have autoconf for the kernel. -+- */ -+-#define unreachable() __builtin_unreachable() -+- -+-/* Mark a function definition as prohibited from being cloned. */ -+-#define __noclone __attribute__((__noclone__)) -+- -+-#endif /* GCC_VERSION >= 40500 */ -+- -+-#if GCC_VERSION >= 40600 -+-/* -+- * Tell the optimizer that something else uses this function or variable. -+- */ -+-#define __visible __attribute__((externally_visible)) -+-#endif -+- -+-/* -+- * GCC 'asm goto' miscompiles certain code sequences: -+- * -+- * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 -+- * -+- * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. -+- * Fixed in GCC 4.8.2 and later versions. -+- * -+- * (asm goto is automatically volatile - the naming reflects this.) -+- */ -+-#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) -+- -+-#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP -+-#if GCC_VERSION >= 40400 -+-#define __HAVE_BUILTIN_BSWAP32__ -+-#define __HAVE_BUILTIN_BSWAP64__ -+-#endif -+-#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600) -+-#define __HAVE_BUILTIN_BSWAP16__ -+-#endif -+-#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ -+diff --git b/include/linux/compiler-intel.h a/include/linux/compiler-intel.h -+index ba147a1..d4c7113 100644 -+--- b/include/linux/compiler-intel.h -++++ a/include/linux/compiler-intel.h -+@@ -13,9 +13,14 @@ -+ /* Intel ECC compiler doesn't support gcc specific asm stmts. -+ * It uses intrinsics to do the equivalent things. -+ */ -++#undef barrier -++#undef barrier_data -+ #undef RELOC_HIDE -+ #undef OPTIMIZER_HIDE_VAR -+ -++#define barrier() __memory_barrier() -++#define barrier_data(ptr) barrier() -++ -+ #define RELOC_HIDE(ptr, off) \ -+ ({ unsigned long __ptr; \ -+ __ptr = (unsigned long) (ptr); \ -+diff --git b/include/linux/compiler.h a/include/linux/compiler.h -+index d5ad7b1..020ad16 100644 -+--- b/include/linux/compiler.h -++++ a/include/linux/compiler.h -+@@ -17,6 +17,7 @@ -+ # define __release(x) __context__(x,-1) -+ # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) -+ # define __percpu __attribute__((noderef, address_space(3))) -++# define __pmem __attribute__((noderef, address_space(5))) -+ #ifdef CONFIG_SPARSE_RCU_POINTER -+ # define __rcu __attribute__((noderef, address_space(4))) -+ #else -+@@ -42,6 +43,7 @@ extern void __chk_io_ptr(const volatile void __iomem *); -+ # define __cond_lock(x,c) (c) -+ # define __percpu -+ # define __rcu -++# define __pmem -+ #endif -+ -+ /* Indirect macros required for expanded argument pasting, eg. __LINE__. */ -+@@ -54,7 +56,11 @@ extern void __chk_io_ptr(const volatile void __iomem *); -+ #include -+ #endif -+ -++#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__) -++#define notrace __attribute__((hotpatch(0,0))) -++#else -+ #define notrace __attribute__((no_instrument_function)) -++#endif -+ -+ /* Intel compiler defines __GNUC__. So we will overwrite implementations -+ * coming from above header files here -+@@ -138,7 +144,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ */ -+ #define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) ) -+ #define __trace_if(cond) \ -+- if (__builtin_constant_p((cond)) ? !!(cond) : \ -++ if (__builtin_constant_p(!!(cond)) ? !!(cond) : \ -+ ({ \ -+ int ______r; \ -+ static struct ftrace_branch_data \ -+@@ -165,6 +171,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ # define barrier() __memory_barrier() -+ #endif -+ -++#ifndef barrier_data -++# define barrier_data(ptr) barrier() -++#endif -++ -+ /* Unreachable code */ -+ #ifndef unreachable -+ # define unreachable() do { } while (1) -+@@ -186,6 +196,126 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ # define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__) -+ #endif -+ -++#include -++ -++#define __READ_ONCE_SIZE \ -++({ \ -++ switch (size) { \ -++ case 1: *(__u8 *)res = *(volatile __u8 *)p; break; \ -++ case 2: *(__u16 *)res = *(volatile __u16 *)p; break; \ -++ case 4: *(__u32 *)res = *(volatile __u32 *)p; break; \ -++ case 8: *(__u64 *)res = *(volatile __u64 *)p; break; \ -++ default: \ -++ barrier(); \ -++ __builtin_memcpy((void *)res, (const void *)p, size); \ -++ barrier(); \ -++ } \ -++}) -++ -++static __always_inline -++void __read_once_size(const volatile void *p, void *res, int size) -++{ -++ __READ_ONCE_SIZE; -++} -++ -++#ifdef CONFIG_KASAN -++/* -++ * This function is not 'inline' because __no_sanitize_address confilcts -++ * with inlining. Attempt to inline it may cause a build failure. -++ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368 -++ * '__maybe_unused' allows us to avoid defined-but-not-used warnings. -++ */ -++static __no_sanitize_address __maybe_unused -++void __read_once_size_nocheck(const volatile void *p, void *res, int size) -++{ -++ __READ_ONCE_SIZE; -++} -++#else -++static __always_inline -++void __read_once_size_nocheck(const volatile void *p, void *res, int size) -++{ -++ __READ_ONCE_SIZE; -++} -++#endif -++ -++static __always_inline void __write_once_size(volatile void *p, void *res, int size) -++{ -++ switch (size) { -++ case 1: *(volatile __u8 *)p = *(__u8 *)res; break; -++ case 2: *(volatile __u16 *)p = *(__u16 *)res; break; -++ case 4: *(volatile __u32 *)p = *(__u32 *)res; break; -++ case 8: *(volatile __u64 *)p = *(__u64 *)res; break; -++ default: -++ barrier(); -++ __builtin_memcpy((void *)p, (const void *)res, size); -++ barrier(); -++ } -++} -++ -++/* -++ * Prevent the compiler from merging or refetching reads or writes. The -++ * compiler is also forbidden from reordering successive instances of -++ * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the -++ * compiler is aware of some particular ordering. One way to make the -++ * compiler aware of ordering is to put the two invocations of READ_ONCE, -++ * WRITE_ONCE or ACCESS_ONCE() in different C statements. -++ * -++ * In contrast to ACCESS_ONCE these two macros will also work on aggregate -++ * data types like structs or unions. If the size of the accessed data -++ * type exceeds the word size of the machine (e.g., 32 bits or 64 bits) -++ * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a -++ * compile-time warning. -++ * -++ * Their two major use cases are: (1) Mediating communication between -++ * process-level code and irq/NMI handlers, all running on the same CPU, -++ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise -++ * mutilate accesses that either do not require ordering or that interact -++ * with an explicit memory barrier or atomic instruction that provides the -++ * required ordering. -++ */ -++ -++#define __READ_ONCE(x, check) \ -++({ \ -++ union { typeof(x) __val; char __c[1]; } __u; \ -++ if (check) \ -++ __read_once_size(&(x), __u.__c, sizeof(x)); \ -++ else \ -++ __read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \ -++ __u.__val; \ -++}) -++#define READ_ONCE(x) __READ_ONCE(x, 1) -++ -++/* -++ * Use READ_ONCE_NOCHECK() instead of READ_ONCE() if you need -++ * to hide memory access from KASAN. -++ */ -++#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0) -++ -++#define WRITE_ONCE(x, val) \ -++({ \ -++ union { typeof(x) __val; char __c[1]; } __u = \ -++ { .__val = (__force typeof(x)) (val) }; \ -++ __write_once_size(&(x), __u.__c, sizeof(x)); \ -++ __u.__val; \ -++}) -++ -++/** -++ * smp_cond_acquire() - Spin wait for cond with ACQUIRE ordering -++ * @cond: boolean expression to wait for -++ * -++ * Equivalent to using smp_load_acquire() on the condition variable but employs -++ * the control dependency of the wait to reduce the barrier on many platforms. -++ * -++ * The control dependency provides a LOAD->STORE order, the additional RMB -++ * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order, -++ * aka. ACQUIRE. -++ */ -++#define smp_cond_acquire(cond) do { \ -++ while (!(cond)) \ -++ cpu_relax(); \ -++ smp_rmb(); /* ctrl + rmb := acquire */ \ -++} while (0) -++ -+ #endif /* __KERNEL__ */ -+ -+ #endif /* __ASSEMBLY__ */ -+@@ -304,6 +434,14 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ #define __visible -+ #endif -+ -++/* -++ * Assume alignment of return value. -++ */ -++#ifndef __assume_aligned -++#define __assume_aligned(a, ...) -++#endif -++ -++ -+ /* Are two types/vars the same type (ignoring qualifiers)? */ -+ #ifndef __same_type -+ # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) -+@@ -311,7 +449,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ -+ /* Is this type a native word size -- useful for atomic operations */ -+ #ifndef __native_word -+-# define __native_word(t) (sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) -++# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long)) -+ #endif -+ -+ /* Compile time object size, -1 for unknown */ -+@@ -373,12 +511,38 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); -+ * to make the compiler aware of ordering is to put the two invocations of -+ * ACCESS_ONCE() in different C statements. -+ * -+- * This macro does absolutely -nothing- to prevent the CPU from reordering, -+- * merging, or refetching absolutely anything at any time. Its main intended -+- * use is to mediate communication between process-level code and irq/NMI -+- * handlers, all running on the same CPU. -++ * ACCESS_ONCE will only work on scalar types. For union types, ACCESS_ONCE -++ * on a union member will work as long as the size of the member matches the -++ * size of the union and the size is smaller than word size. -++ * -++ * The major use cases of ACCESS_ONCE used to be (1) Mediating communication -++ * between process-level code and irq/NMI handlers, all running on the same CPU, -++ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise -++ * mutilate accesses that either do not require ordering or that interact -++ * with an explicit memory barrier or atomic instruction that provides the -++ * required ordering. -++ * -++ * If possible use READ_ONCE()/WRITE_ONCE() instead. -++ */ -++#define __ACCESS_ONCE(x) ({ \ -++ __maybe_unused typeof(x) __var = (__force typeof(x)) 0; \ -++ (volatile typeof(x) *)&(x); }) -++#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x)) -++ -++/** -++ * lockless_dereference() - safely load a pointer for later dereference -++ * @p: The pointer to load -++ * -++ * Similar to rcu_dereference(), but for situations where the pointed-to -++ * object's lifetime is managed by something other than RCU. That -++ * "something other" might be reference counting or simple immortality. -+ */ -+-#define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) -++#define lockless_dereference(p) \ -++({ \ -++ typeof(p) _________p1 = READ_ONCE(p); \ -++ smp_read_barrier_depends(); /* Dependency order vs. p above. */ \ -++ (_________p1); \ -++}) -+ -+ /* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */ -+ #ifdef CONFIG_KPROBES -diff --git a/tools/mkimage/patches/200-gcc5_compat.patch b/tools/mkimage/patches/200-gcc5_compat.patch -deleted file mode 100644 -index 4d55f00..0000000 ---- a/tools/mkimage/patches/200-gcc5_compat.patch -+++ /dev/null -@@ -1,93 +0,0 @@ --From 478b02f1a7043b673565075ea5016376f3293b23 Mon Sep 17 00:00:00 2001 --From: Hans de Goede --Date: Sat, 7 Feb 2015 22:52:40 +0100 --Subject: [PATCH] Add linux/compiler-gcc5.h to fix builds with gcc5 -- --Add linux/compiler-gcc5/h from the kernel sources at: -- --commit 5631b8fba640a4ab2f8a954f63a603fa34eda96b --Author: Steven Noonan --Date: Sat Oct 25 15:09:42 2014 -0700 -- -- compiler/gcc4+: Remove inaccurate comment about 'asm goto' miscompiles -- --Signed-off-by: Hans de Goede ----- -- include/linux/compiler-gcc5.h | 65 +++++++++++++++++++++++++++++++++++++++++ -- 1 file changed, 65 insertions(+) -- create mode 100644 include/linux/compiler-gcc5.h -- --diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h --new file mode 100644 --index 0000000..c8c5659 ----- /dev/null --+++ b/include/linux/compiler-gcc5.h --@@ -0,0 +1,65 @@ --+#ifndef __LINUX_COMPILER_H --+#error "Please don't include directly, include instead." --+#endif --+ --+#define __used __attribute__((__used__)) --+#define __must_check __attribute__((warn_unused_result)) --+#define __compiler_offsetof(a, b) __builtin_offsetof(a, b) --+ --+/* Mark functions as cold. gcc will assume any path leading to a call --+ to them will be unlikely. This means a lot of manual unlikely()s --+ are unnecessary now for any paths leading to the usual suspects --+ like BUG(), printk(), panic() etc. [but let's keep them for now for --+ older compilers] --+ --+ Early snapshots of gcc 4.3 don't support this and we can't detect this --+ in the preprocessor, but we can live with this because they're unreleased. --+ Maketime probing would be overkill here. --+ --+ gcc also has a __attribute__((__hot__)) to move hot functions into --+ a special section, but I don't see any sense in this right now in --+ the kernel context */ --+#define __cold __attribute__((__cold__)) --+ --+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) --+ --+#ifndef __CHECKER__ --+# define __compiletime_warning(message) __attribute__((warning(message))) --+# define __compiletime_error(message) __attribute__((error(message))) --+#endif /* __CHECKER__ */ --+ --+/* --+ * Mark a position in code as unreachable. This can be used to --+ * suppress control flow warnings after asm blocks that transfer --+ * control elsewhere. --+ * --+ * Early snapshots of gcc 4.5 don't support this and we can't detect --+ * this in the preprocessor, but we can live with this because they're --+ * unreleased. Really, we need to have autoconf for the kernel. --+ */ --+#define unreachable() __builtin_unreachable() --+ --+/* Mark a function definition as prohibited from being cloned. */ --+#define __noclone __attribute__((__noclone__)) --+ --+/* --+ * Tell the optimizer that something else uses this function or variable. --+ */ --+#define __visible __attribute__((externally_visible)) --+ --+/* --+ * GCC 'asm goto' miscompiles certain code sequences: --+ * --+ * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58670 --+ * --+ * Work it around via a compiler barrier quirk suggested by Jakub Jelinek. --+ * --+ * (asm goto is automatically volatile - the naming reflects this.) --+ */ --+#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) --+ --+#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP --+#define __HAVE_BUILTIN_BSWAP32__ --+#define __HAVE_BUILTIN_BSWAP64__ --+#define __HAVE_BUILTIN_BSWAP16__ --+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */ ---- --1.7.10.4 -- diff --git a/patches/openwrt/0035-toolchain-gcc-fix-build-with-GCC-6.patch b/patches/openwrt/0035-toolchain-gcc-fix-build-with-GCC-6.patch deleted file mode 100644 index e828631b..00000000 --- a/patches/openwrt/0035-toolchain-gcc-fix-build-with-GCC-6.patch +++ /dev/null @@ -1,144 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 9 May 2016 00:16:38 +0200 -Subject: toolchain: gcc: fix build with GCC 6 - -At least for GCC 4.8, which is used by most targets. - -Signed-off-by: Matthias Schiffer - -diff --git a/toolchain/gcc/patches/4.8-linaro/030-gcc-6-compile.patch b/toolchain/gcc/patches/4.8-linaro/030-gcc-6-compile.patch -new file mode 100644 -index 0000000..c74f2aa ---- /dev/null -+++ b/toolchain/gcc/patches/4.8-linaro/030-gcc-6-compile.patch -@@ -0,0 +1,130 @@ -+Upstream commit r233721 -+ -+diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in -+index bd1c1d7..a0ea0d4 100644 -+--- a/gcc/cp/Make-lang.in -++++ b/gcc/cp/Make-lang.in -+@@ -111,7 +111,7 @@ else -+ # deleting the $(srcdir)/cp/cfns.h file. -+ $(srcdir)/cp/cfns.h: -+ endif -+- gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -L ANSI-C \ -++ gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -L C++ \ -+ $(srcdir)/cp/cfns.gperf --output-file $(srcdir)/cp/cfns.h -+ -+ # -+diff --git a/gcc/cp/cfns.gperf b/gcc/cp/cfns.gperf -+index 05ca753..d9b16b8 100644 -+--- a/gcc/cp/cfns.gperf -++++ b/gcc/cp/cfns.gperf -+@@ -1,3 +1,5 @@ -++%language=C++ -++%define class-name libc_name -+ %{ -+ /* Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ -+@@ -16,14 +18,6 @@ for more details. -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ . */ -+-#ifdef __GNUC__ -+-__inline -+-#endif -+-static unsigned int hash (const char *, unsigned int); -+-#ifdef __GNUC__ -+-__inline -+-#endif -+-const char * libc_name_p (const char *, unsigned int); -+ %} -+ %% -+ # The standard C library functions, for feeding to gperf; the result is used -+diff --git a/gcc/cp/cfns.h b/gcc/cp/cfns.h -+index c845ddf..65801d1 100644 -+--- a/gcc/cp/cfns.h -++++ b/gcc/cp/cfns.h -+@@ -1,5 +1,5 @@ -+-/* ANSI-C code produced by gperf version 3.0.3 */ -+-/* Command-line: gperf -o -C -E -k '1-6,$' -j1 -D -N libc_name_p -L ANSI-C cfns.gperf */ -++/* C++ code produced by gperf version 3.0.4 */ -++/* Command-line: gperf -o -C -E -k '1-6,$' -j1 -D -N libc_name_p -L C++ --output-file cfns.h cfns.gperf */ -+ -+ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ -+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ -+@@ -28,7 +28,7 @@ -+ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." -+ #endif -+ -+-#line 1 "cfns.gperf" -++#line 3 "cfns.gperf" -+ -+ /* Copyright (C) 2000-2014 Free Software Foundation, Inc. -+ -+@@ -47,25 +47,18 @@ for more details. -+ You should have received a copy of the GNU General Public License -+ along with GCC; see the file COPYING3. If not see -+ . */ -+-#ifdef __GNUC__ -+-__inline -+-#endif -+-static unsigned int hash (const char *, unsigned int); -+-#ifdef __GNUC__ -+-__inline -+-#endif -+-const char * libc_name_p (const char *, unsigned int); -+ /* maximum key range = 391, duplicates = 0 */ -+ -+-#ifdef __GNUC__ -+-__inline -+-#else -+-#ifdef __cplusplus -+-inline -+-#endif -+-#endif -+-static unsigned int -+-hash (register const char *str, register unsigned int len) -++class libc_name -++{ -++private: -++ static inline unsigned int hash (const char *str, unsigned int len); -++public: -++ static const char *libc_name_p (const char *str, unsigned int len); -++}; -++ -++inline unsigned int -++libc_name::hash (register const char *str, register unsigned int len) -+ { -+ static const unsigned short asso_values[] = -+ { -+@@ -122,14 +115,8 @@ hash (register const char *str, register unsigned int len) -+ return hval + asso_values[(unsigned char)str[len - 1]]; -+ } -+ -+-#ifdef __GNUC__ -+-__inline -+-#ifdef __GNUC_STDC_INLINE__ -+-__attribute__ ((__gnu_inline__)) -+-#endif -+-#endif -+ const char * -+-libc_name_p (register const char *str, register unsigned int len) -++libc_name::libc_name_p (register const char *str, register unsigned int len) -+ { -+ enum -+ { -+diff --git a/gcc/cp/except.c b/gcc/cp/except.c -+index 221971a..32340f5 100644 -+--- a/gcc/cp/except.c -++++ b/gcc/cp/except.c -+@@ -1030,7 +1030,8 @@ nothrow_libfn_p (const_tree fn) -+ unless the system headers are playing rename tricks, and if -+ they are, we don't want to be confused by them. */ -+ id = DECL_NAME (fn); -+- return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); -++ return !!libc_name::libc_name_p (IDENTIFIER_POINTER (id), -++ IDENTIFIER_LENGTH (id)); -+ } -+ -+ /* Returns nonzero if an exception of type FROM will be caught by a -+-- -+1.7.1 -+ diff --git a/patches/openwrt/0036-ath79-dev-eth-fix-QCA9561-set-phy-interface-mode-and-mask.patch b/patches/openwrt/0036-ath79-dev-eth-fix-QCA9561-set-phy-interface-mode-and-mask.patch deleted file mode 100644 index f7c393a3..00000000 --- a/patches/openwrt/0036-ath79-dev-eth-fix-QCA9561-set-phy-interface-mode-and-mask.patch +++ /dev/null @@ -1,46 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 20:59:44 +0200 -Subject: ath79: dev-eth: fix QCA9561 set phy interface mode and mask - -QCA9563 and QCA9561 are two series of Qualcomm SoC Dragonfly. The only different -is QCA9563 w/o internal switch. It has one GMAC with SGMII interface. But they -have the same device ID(0x1150). So they share the same codes. - -Signed-off-by: Miaoqing Pan - -Backport of OpenWrt r46971 - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -index ff94e2e..31d2438 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -@@ -633,7 +633,6 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, - case ATH79_SOC_AR9330: - case ATH79_SOC_AR9331: - case ATH79_SOC_QCA9533: -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - pdata->phy_if_mode = PHY_INTERFACE_MODE_MII; - break; -@@ -667,6 +666,11 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, - } - break; - -+ case ATH79_SOC_QCA9561: -+ if (!pdata->phy_if_mode) -+ pdata->phy_if_mode = PHY_INTERFACE_MODE_MII; -+ break; -+ - default: - BUG(); - } -@@ -1035,7 +1039,8 @@ void __init ath79_register_eth(unsigned int id) - AR933X_RESET_GE0_MDIO; - pdata->set_speed = ath79_set_speed_dummy; - -- pdata->phy_mask = BIT(4); -+ if (!pdata->phy_mask) -+ pdata->phy_mask = BIT(4); - } else { - pdata->reset_bit = AR933X_RESET_GE1_MAC | - AR933X_RESET_GE1_MDIO; diff --git a/patches/openwrt/0037-ar71xx-use-correct-PLL-configuration-register-bitmask-for-QCA956x-SoC.patch b/patches/openwrt/0037-ar71xx-use-correct-PLL-configuration-register-bitmask-for-QCA956x-SoC.patch deleted file mode 100644 index 3a9968e3..00000000 --- a/patches/openwrt/0037-ar71xx-use-correct-PLL-configuration-register-bitmask-for-QCA956x-SoC.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 22:58:50 +0200 -Subject: ar71xx: use correct PLL configuration register bitmask for QCA956x SoC. - -Incorrect value causes clock inaccuracy as huge as 1/60. - -Signed-off-by: Dmitry Ivanov -Signed-off-by: Felix Fietkau - -Backport of OpenWrt r47363 - -diff --git a/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -index b5c88e9..d3a14b2 100644 ---- a/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -+++ b/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -@@ -529,7 +529,7 @@ - +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT 0 - +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK 0x1f - +#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT 5 --+#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x3fff -++#define QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK 0x1fff - +#define QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT 18 - +#define QCA956X_PLL_CPU_CONFIG1_NINT_MASK 0x1ff - + -@@ -541,7 +541,7 @@ - +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT 0 - +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK 0x1f - +#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT 5 --+#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x3fff -++#define QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK 0x1fff - +#define QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT 18 - +#define QCA956X_PLL_DDR_CONFIG1_NINT_MASK 0x1ff - + diff --git a/patches/openwrt/0038-ar71xx-update-QCA956x-support.patch b/patches/openwrt/0038-ar71xx-update-QCA956x-support.patch deleted file mode 100644 index 3ae6c249..00000000 --- a/patches/openwrt/0038-ar71xx-update-QCA956x-support.patch +++ /dev/null @@ -1,381 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 22:18:40 +0200 -Subject: ar71xx: update QCA956x support - -- separate qca956x and tp9343 (they use different IDs) -- rename qca9561->qca956x for consistency -- add missing bits (device reset, gpio output select) -- fix wmac setup - -Signed-off-by: Roman Yeryomin - -Backport of OpenWrt r47981 - -diff --git a/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch b/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -index d3a14b2..61b8976 100644 ---- a/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -+++ b/target/linux/ar71xx/patches-3.18/735-MIPS-ath79-add-support-for-QCA956x-SoC.patch -@@ -105,7 +105,7 @@ - qca953x_clocks_init(); - else if (soc_is_qca955x()) - qca955x_clocks_init(); --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + qca956x_clocks_init(); - else - BUG(); -@@ -116,7 +116,7 @@ - reg = QCA953X_RESET_REG_RESET_MODULE; - else if (soc_is_qca955x()) - reg = QCA955X_RESET_REG_RESET_MODULE; --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + reg = QCA956X_RESET_REG_RESET_MODULE; - else - panic("Reset register not defined for this SOC"); -@@ -125,20 +125,30 @@ - reg = QCA953X_RESET_REG_RESET_MODULE; - else if (soc_is_qca955x()) - reg = QCA955X_RESET_REG_RESET_MODULE; --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + reg = QCA956X_RESET_REG_RESET_MODULE; - else - panic("Reset register not defined for this SOC"); - -+@@ -133,6 +137,8 @@ u32 ath79_device_reset_get(u32 mask) -+ reg = AR933X_RESET_REG_RESET_MODULE; -+ else if (soc_is_ar934x()) -+ reg = AR934X_RESET_REG_RESET_MODULE; -++ else if (soc_is_qca956x() || soc_is_tp9343()) -++ reg = QCA956X_RESET_REG_RESET_MODULE; -+ else -+ BUG(); -+ - --- a/arch/mips/ath79/dev-common.c - +++ b/arch/mips/ath79/dev-common.c --@@ -94,7 +94,8 @@ void __init ath79_register_uart(void) -+@@ -94,7 +94,9 @@ void __init ath79_register_uart(void) - soc_is_ar913x() || - soc_is_ar934x() || - soc_is_qca953x() || - - soc_is_qca955x()) { - + soc_is_qca955x() || --+ soc_is_qca956x()) { -++ soc_is_qca956x() || -++ soc_is_tp9343()) { - ath79_uart_data[0].uartclk = uart_clk_rate; - platform_device_register(&ath79_uart_device); - } else if (soc_is_ar933x()) { -@@ -168,14 +178,14 @@ - qca953x_usb_setup(); - else if (soc_is_qca955x()) - qca955x_usb_setup(); --+ else if (soc_is_qca9561()) -++ else if (soc_is_qca956x()) - + qca956x_usb_setup(); - else - BUG(); - } - --- a/arch/mips/ath79/dev-wmac.c - +++ b/arch/mips/ath79/dev-wmac.c --@@ -189,6 +189,24 @@ static void qca955x_wmac_setup(void) -+@@ -189,6 +189,26 @@ static void qca955x_wmac_setup(void) - ath79_wmac_data.is_clk_25mhz = true; - } - -@@ -195,16 +205,18 @@ - + ath79_wmac_data.is_clk_25mhz = false; - + else - + ath79_wmac_data.is_clk_25mhz = true; -++ -++ ath79_wmac_data.get_mac_revision = ar93xx_get_soc_revision; - +} - + - static bool __init - ar93xx_wmac_otp_read_word(void __iomem *base, int addr, u32 *data) - { --@@ -392,6 +410,8 @@ void __init ath79_register_wmac(u8 *cal_ -+@@ -392,6 +412,8 @@ void __init ath79_register_wmac(u8 *cal_ - qca953x_wmac_setup(); - else if (soc_is_qca955x()) - qca955x_wmac_setup(); --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + qca956x_wmac_setup(); - else - BUG(); -@@ -216,27 +228,38 @@ - case REV_ID_MAJOR_QCA9556: - case REV_ID_MAJOR_QCA9558: - + case REV_ID_MAJOR_TP9343: --+ case REV_ID_MAJOR_QCA9561: -++ case REV_ID_MAJOR_QCA956X: - _prom_putchar = prom_putchar_ar71xx; - break; - - --- a/arch/mips/ath79/gpio.c - +++ b/arch/mips/ath79/gpio.c --@@ -148,7 +148,8 @@ static void __iomem *ath79_gpio_get_func -+@@ -148,7 +148,10 @@ static void __iomem *ath79_gpio_get_func - soc_is_ar913x() || - soc_is_ar933x()) - reg = AR71XX_GPIO_REG_FUNC; - - else if (soc_is_ar934x() || soc_is_qca953x()) - + else if (soc_is_ar934x() || --+ soc_is_qca953x() || soc_is_qca956x()) -++ soc_is_qca953x() || -++ soc_is_qca956x() || -++ soc_is_tp9343()) - reg = AR934X_GPIO_REG_FUNC; - else - BUG(); --@@ -228,12 +229,15 @@ void __init ath79_gpio_init(void) -+@@ -187,7 +190,7 @@ void __init ath79_gpio_output_select(uns -+ unsigned int reg; -+ u32 t, s; -+ -+- BUG_ON(!soc_is_ar934x() && !soc_is_qca953x()); -++ BUG_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x()); -+ -+ if (gpio >= AR934X_GPIO_COUNT) -+ return; -+@@ -228,12 +231,15 @@ void __init ath79_gpio_init(void) - ath79_gpio_count = QCA953X_GPIO_COUNT; - else if (soc_is_qca955x()) - ath79_gpio_count = QCA955X_GPIO_COUNT; --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + ath79_gpio_count = QCA956X_GPIO_COUNT; - else - BUG(); -@@ -245,23 +268,24 @@ - ath79_gpio_chip.ngpio = ath79_gpio_count; - - if (soc_is_ar934x() || soc_is_qca953x() || soc_is_qca955x()) { - + if (soc_is_ar934x() || soc_is_qca953x() || soc_is_qca955x() || --+ soc_is_qca956x()) { -++ soc_is_qca956x() || soc_is_tp9343()) { - ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; - ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; - } - --- a/arch/mips/ath79/irq.c - +++ b/arch/mips/ath79/irq.c --@@ -107,7 +107,8 @@ static void __init ath79_misc_irq_init(v -+@@ -107,7 +107,9 @@ static void __init ath79_misc_irq_init(v - soc_is_ar933x() || - soc_is_ar934x() || - soc_is_qca953x() || - - soc_is_qca955x()) - + soc_is_qca955x() || --+ soc_is_qca956x()) -++ soc_is_qca956x() || -++ soc_is_tp9343()) - ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; - else - BUG(); --@@ -268,6 +269,97 @@ static void qca955x_irq_init(void) -+@@ -268,6 +270,97 @@ static void qca955x_irq_init(void) - irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); - } - -@@ -359,21 +383,21 @@ - asmlinkage void plat_irq_dispatch(void) - { - unsigned long pending; --@@ -397,6 +489,9 @@ void __init arch_init_irq(void) -+@@ -397,6 +490,9 @@ void __init arch_init_irq(void) - } else if (soc_is_qca955x()) { - ath79_ip2_handler = ath79_default_ip2_handler; - ath79_ip3_handler = ath79_default_ip3_handler; --+ } else if (soc_is_qca956x()) { -++ } else if (soc_is_qca956x() || soc_is_tp9343()) { - + ath79_ip2_handler = ath79_default_ip2_handler; - + ath79_ip3_handler = ath79_default_ip3_handler; - } else { - BUG(); - } --@@ -411,4 +506,6 @@ void __init arch_init_irq(void) -+@@ -411,4 +507,6 @@ void __init arch_init_irq(void) - qca953x_irq_init(); - else if (soc_is_qca955x()) - qca955x_irq_init(); --+ else if (soc_is_qca956x()) -++ else if (soc_is_qca956x() || soc_is_tp9343()) - + qca956x_irq_init(); - } - --- a/arch/mips/ath79/Kconfig -@@ -428,7 +452,7 @@ - } else if (soc_is_qca955x()) { - ath79_pci_irq_map = qca955x_pci_irq_map; - ath79_pci_nr_irqs = ARRAY_SIZE(qca955x_pci_irq_map); --+ } else if (soc_is_qca9561()) { -++ } else if (soc_is_qca956x()) { - + ath79_pci_irq_map = qca956x_pci_irq_map; - + ath79_pci_nr_irqs = ARRAY_SIZE(qca956x_pci_irq_map); - } else { -@@ -438,7 +462,7 @@ - QCA955X_PCI_MEM_SIZE, - 1, - ATH79_IP3_IRQ(2)); --+ } else if (soc_is_qca9561()) { -++ } else if (soc_is_qca956x()) { - + pdev = ath79_register_pci_ar724x(0, - + QCA956X_PCI_CFG_BASE1, - + QCA956X_PCI_CTRL_BASE1, -@@ -456,15 +480,15 @@ - rev = id & QCA955X_REV_ID_REVISION_MASK; - break; - --+ case REV_ID_MAJOR_TP9343: --+ ath79_soc = ATH79_SOC_TP9343; --+ chip = "9343"; -++ case REV_ID_MAJOR_QCA956X: -++ ath79_soc = ATH79_SOC_QCA956X; -++ chip = "956X"; - + rev = id & QCA956X_REV_ID_REVISION_MASK; - + break; - + --+ case REV_ID_MAJOR_QCA9561: --+ ath79_soc = ATH79_SOC_QCA9561; --+ chip = "9561"; -++ case REV_ID_MAJOR_TP9343: -++ ath79_soc = ATH79_SOC_TP9343; -++ chip = "9343"; - + rev = id & QCA956X_REV_ID_REVISION_MASK; - + break; - + -@@ -476,7 +500,7 @@ - ath79_soc_rev = rev; - - - if (soc_is_qca953x() || soc_is_qca955x()) --+ if (soc_is_qca953x() || soc_is_qca955x() || soc_is_qca9561()) -++ if (soc_is_qca953x() || soc_is_qca955x() || soc_is_qca956x()) - sprintf(ath79_sys_type, "Qualcomm Atheros QCA%s ver %u rev %u", - chip, ver, rev); - + else if (soc_is_tp9343()) -@@ -511,7 +535,21 @@ - #define AR9300_OTP_BASE 0x14000 - #define AR9300_OTP_STATUS 0x15f18 - #define AR9300_OTP_STATUS_TYPE 0x7 --@@ -375,6 +392,49 @@ -+@@ -152,6 +169,13 @@ -+ #define AR9300_OTP_READ_DATA 0x15f1c -+ -+ /* -++ * Hidden Registers -++ */ -++#define QCA956X_DAM_RESET_OFFSET 0xb90001bc -++#define QCA956X_DAM_RESET_SIZE 0x4 -++#define QCA956X_INLINE_CHKSUM_ENG BIT(27) -++ -++/* -+ * DDR_CTRL block -+ */ -+ #define AR71XX_DDR_REG_PCI_WIN0 0x7c -+@@ -375,6 +399,49 @@ - #define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL BIT(21) - #define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL BIT(24) - -@@ -561,7 +599,7 @@ - /* - * USB_CONFIG block - */ --@@ -422,6 +482,11 @@ -+@@ -422,6 +489,11 @@ - #define QCA955X_RESET_REG_BOOTSTRAP 0xb0 - #define QCA955X_RESET_REG_EXT_INT_STATUS 0xac - -@@ -573,7 +611,7 @@ - #define MISC_INT_ETHSW BIT(12) - #define MISC_INT_TIMER4 BIT(10) - #define MISC_INT_TIMER3 BIT(9) --@@ -596,6 +661,8 @@ -+@@ -596,6 +668,8 @@ - - #define QCA955X_BOOTSTRAP_REF_CLK_40 BIT(4) - -@@ -582,7 +620,7 @@ - #define AR934X_PCIE_WMAC_INT_WMAC_MISC BIT(0) - #define AR934X_PCIE_WMAC_INT_WMAC_TX BIT(1) - #define AR934X_PCIE_WMAC_INT_WMAC_RXLP BIT(2) --@@ -663,6 +730,37 @@ -+@@ -663,6 +737,37 @@ - QCA955X_EXT_INT_PCIE_RC2_INT1 | QCA955X_EXT_INT_PCIE_RC2_INT2 | \ - QCA955X_EXT_INT_PCIE_RC2_INT3) - -@@ -620,16 +658,16 @@ - #define REV_ID_MAJOR_MASK 0xfff0 - #define REV_ID_MAJOR_AR71XX 0x00a0 - #define REV_ID_MAJOR_AR913X 0x00b0 --@@ -678,6 +776,8 @@ -+@@ -678,6 +783,8 @@ - #define REV_ID_MAJOR_QCA9533_V2 0x0160 - #define REV_ID_MAJOR_QCA9556 0x0130 - #define REV_ID_MAJOR_QCA9558 0x1130 - +#define REV_ID_MAJOR_TP9343 0x0150 --+#define REV_ID_MAJOR_QCA9561 0x1150 -++#define REV_ID_MAJOR_QCA956X 0x1150 - - #define AR71XX_REV_ID_MINOR_MASK 0x3 - #define AR71XX_REV_ID_MINOR_AR7130 0x0 --@@ -702,6 +802,8 @@ -+@@ -702,6 +809,8 @@ - - #define QCA955X_REV_ID_REVISION_MASK 0xf - -@@ -638,7 +676,7 @@ - /* - * SPI block - */ --@@ -766,6 +868,19 @@ -+@@ -766,6 +875,19 @@ - #define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 - #define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 - -@@ -658,7 +696,7 @@ - #define AR71XX_GPIO_COUNT 16 - #define AR7240_GPIO_COUNT 18 - #define AR7241_GPIO_COUNT 20 --@@ -774,6 +889,7 @@ -+@@ -774,6 +896,7 @@ - #define AR934X_GPIO_COUNT 23 - #define QCA953X_GPIO_COUNT 18 - #define QCA955X_GPIO_COUNT 24 -@@ -673,11 +711,11 @@ - ATH79_SOC_QCA9556, - ATH79_SOC_QCA9558, - + ATH79_SOC_TP9343, --+ ATH79_SOC_QCA9561, -++ ATH79_SOC_QCA956X, - }; - - extern enum ath79_soc_type ath79_soc; --@@ -126,6 +128,21 @@ static inline int soc_is_qca955x(void) -+@@ -126,6 +128,26 @@ static inline int soc_is_qca955x(void) - return soc_is_qca9556() || soc_is_qca9558(); - } - -@@ -685,15 +723,20 @@ - +{ - + return ath79_soc == ATH79_SOC_TP9343; - +} --+ -++ - +static inline int soc_is_qca9561(void) - +{ --+ return ath79_soc == ATH79_SOC_QCA9561; -++ return ath79_soc == ATH79_SOC_QCA956X; -++} -++ -++static inline int soc_is_qca9563(void) -++{ -++ return ath79_soc == ATH79_SOC_QCA956X; - +} - + - +static inline int soc_is_qca956x(void) - +{ --+ return soc_is_tp9343() || soc_is_qca9561(); -++ return soc_is_qca9561() || soc_is_qca9563(); - +} - + - extern void __iomem *ath79_ddr_base; diff --git a/patches/openwrt/0039-ar71xx-fold-patch-622-MIPS-ath79-add-support-for-QCA956x-ethernet.patch-into-files.patch b/patches/openwrt/0039-ar71xx-fold-patch-622-MIPS-ath79-add-support-for-QCA956x-ethernet.patch-into-files.patch deleted file mode 100644 index 13161242..00000000 --- a/patches/openwrt/0039-ar71xx-fold-patch-622-MIPS-ath79-add-support-for-QCA956x-ethernet.patch-into-files.patch +++ /dev/null @@ -1,176 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:00:16 +0200 -Subject: ar71xx: fold patch 622-MIPS-ath79-add-support-for-QCA956x-ethernet.patch into files/ - -Signed-off-by: Felix Fietkau - -Backport of OpenWrt r48650 - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -index 31d2438..2efb9c7 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -@@ -198,7 +198,6 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - case ATH79_SOC_AR9330: - case ATH79_SOC_AR9331: - case ATH79_SOC_QCA9533: -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - mdio_dev = &ath79_mdio1_device; - mdio_data = &ath79_mdio1_data; -@@ -209,6 +208,7 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - case ATH79_SOC_AR9344: - case ATH79_SOC_QCA9556: - case ATH79_SOC_QCA9558: -+ case ATH79_SOC_QCA956X: - if (id == 0) { - mdio_dev = &ath79_mdio0_device; - mdio_data = &ath79_mdio0_data; -@@ -258,7 +258,6 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - break; - - case ATH79_SOC_QCA9533: -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - mdio_data->builtin_switch = 1; - break; -@@ -268,6 +267,11 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - mdio_data->is_ar934x = 1; - break; - -+ case ATH79_SOC_QCA956X: -+ if (id == 1) -+ mdio_data->builtin_switch = 1; -+ break; -+ - default: - break; - } -@@ -387,6 +391,16 @@ static void qca955x_set_speed_sgmii(int speed) - iounmap(base); - } - -+static void qca956x_set_speed_sgmii(int speed) -+{ -+ void __iomem *base; -+ u32 val = ath79_get_eth_pll(0, speed); -+ -+ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); -+ __raw_writel(val, base + QCA955X_PLL_ETH_SGMII_CONTROL_REG); -+ iounmap(base); -+} -+ - static void ath79_set_speed_dummy(int speed) - { - } -@@ -517,6 +531,10 @@ struct ag71xx_switch_platform_data ath79_switch_data; - #define AR934X_PLL_VAL_100 0x00000101 - #define AR934X_PLL_VAL_10 0x00001616 - -+#define QCA956X_PLL_VAL_1000 0x03000000 -+#define QCA956X_PLL_VAL_100 0x00000101 -+#define QCA956X_PLL_VAL_10 0x00001919 -+ - static void __init ath79_init_eth_pll_data(unsigned int id) - { - struct ath79_eth_pll_data *pll_data; -@@ -575,13 +593,18 @@ static void __init ath79_init_eth_pll_data(unsigned int id) - case ATH79_SOC_QCA9533: - case ATH79_SOC_QCA9556: - case ATH79_SOC_QCA9558: -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - pll_10 = AR934X_PLL_VAL_10; - pll_100 = AR934X_PLL_VAL_100; - pll_1000 = AR934X_PLL_VAL_1000; - break; - -+ case ATH79_SOC_QCA956X: -+ pll_10 = QCA956X_PLL_VAL_10; -+ pll_100 = QCA956X_PLL_VAL_100; -+ pll_1000 = QCA956X_PLL_VAL_1000; -+ break; -+ - default: - BUG(); - } -@@ -656,6 +679,7 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, - - case ATH79_SOC_QCA9556: - case ATH79_SOC_QCA9558: -+ case ATH79_SOC_QCA956X: - switch (pdata->phy_if_mode) { - case PHY_INTERFACE_MODE_MII: - case PHY_INTERFACE_MODE_RGMII: -@@ -666,11 +690,6 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, - } - break; - -- case ATH79_SOC_QCA9561: -- if (!pdata->phy_if_mode) -- pdata->phy_if_mode = PHY_INTERFACE_MODE_MII; -- break; -- - default: - BUG(); - } -@@ -699,7 +718,7 @@ static int __init ath79_setup_phy_if_mode(unsigned int id, - case ATH79_SOC_AR7241: - case ATH79_SOC_AR9330: - case ATH79_SOC_AR9331: -- case ATH79_SOC_QCA9561: -+ case ATH79_SOC_QCA956X: - case ATH79_SOC_TP9343: - pdata->phy_if_mode = PHY_INTERFACE_MODE_GMII; - break; -@@ -1032,7 +1051,6 @@ void __init ath79_register_eth(unsigned int id) - pdata->fifo_cfg3 = 0x01f00140; - break; - -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - if (id == 0) { - pdata->reset_bit = AR933X_RESET_GE0_MAC | -@@ -1100,6 +1118,34 @@ void __init ath79_register_eth(unsigned int id) - pdata->fifo_cfg3 = 0x01f00140; - break; - -+ case ATH79_SOC_QCA956X: -+ if (id == 0) { -+ pdata->reset_bit = QCA955X_RESET_GE0_MAC | -+ QCA955X_RESET_GE0_MDIO; -+ if (pdata->phy_if_mode == PHY_INTERFACE_MODE_SGMII) -+ pdata->set_speed = qca956x_set_speed_sgmii; -+ else -+ /* FIXME */ -+ pdata->set_speed = ath79_set_speed_dummy; -+ } else { -+ pdata->reset_bit = QCA955X_RESET_GE1_MAC | -+ QCA955X_RESET_GE1_MDIO; -+ /* FIXME */ -+ pdata->set_speed = ath79_set_speed_dummy; -+ } -+ -+ pdata->ddr_flush = ath79_ddr_no_flush; -+ pdata->has_gbit = 1; -+ pdata->is_ar724x = 1; -+ -+ if (!pdata->fifo_cfg1) -+ pdata->fifo_cfg1 = 0x0010ffff; -+ if (!pdata->fifo_cfg2) -+ pdata->fifo_cfg2 = 0x015500aa; -+ if (!pdata->fifo_cfg3) -+ pdata->fifo_cfg3 = 0x01f00140; -+ break; -+ - default: - BUG(); - } -@@ -1140,7 +1186,6 @@ void __init ath79_register_eth(unsigned int id) - case ATH79_SOC_AR9330: - case ATH79_SOC_AR9331: - case ATH79_SOC_QCA9533: -- case ATH79_SOC_QCA9561: - case ATH79_SOC_TP9343: - pdata->mii_bus_dev = &ath79_mdio1_device.dev; - break; diff --git a/patches/openwrt/0040-ar71xx-fix-MDIO-bus-probe-on-QCA956x.patch b/patches/openwrt/0040-ar71xx-fix-MDIO-bus-probe-on-QCA956x.patch deleted file mode 100644 index 7594cf2f..00000000 --- a/patches/openwrt/0040-ar71xx-fix-MDIO-bus-probe-on-QCA956x.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:00:41 +0200 -Subject: ar71xx: fix MDIO bus probe on QCA956x - -Signed-off-by: Felix Fietkau - -Backport of OpenWrt r48651 - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -index 2efb9c7..12a376e 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -@@ -183,7 +183,8 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - ath79_soc == ATH79_SOC_AR9342 || - ath79_soc == ATH79_SOC_AR9344 || - ath79_soc == ATH79_SOC_QCA9556 || -- ath79_soc == ATH79_SOC_QCA9558) -+ ath79_soc == ATH79_SOC_QCA9558 || -+ ath79_soc == ATH79_SOC_QCA956X) - max_id = 1; - else - max_id = 0; diff --git a/patches/openwrt/0041-ar71xx-fix-qca956x-ethernet-initialization.patch b/patches/openwrt/0041-ar71xx-fix-qca956x-ethernet-initialization.patch deleted file mode 100644 index 6cc5e950..00000000 --- a/patches/openwrt/0041-ar71xx-fix-qca956x-ethernet-initialization.patch +++ /dev/null @@ -1,64 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:01:19 +0200 -Subject: ar71xx: fix qca956x ethernet initialization - -Complete internal switch initialization for QCA956X. -Set default mdio device if the interface mode of GE0 is not SGMII (fix ticket #21520). - -Signed-off-by: Weijie Gao - -Backport of OpenWrt r48937 - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -index 12a376e..b43c80a 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/dev-eth.c -@@ -271,6 +271,7 @@ void __init ath79_register_mdio(unsigned int id, u32 phy_mask) - case ATH79_SOC_QCA956X: - if (id == 1) - mdio_data->builtin_switch = 1; -+ mdio_data->is_ar934x = 1; - break; - - default: -@@ -1123,16 +1124,25 @@ void __init ath79_register_eth(unsigned int id) - if (id == 0) { - pdata->reset_bit = QCA955X_RESET_GE0_MAC | - QCA955X_RESET_GE0_MDIO; -+ - if (pdata->phy_if_mode == PHY_INTERFACE_MODE_SGMII) - pdata->set_speed = qca956x_set_speed_sgmii; - else -- /* FIXME */ -- pdata->set_speed = ath79_set_speed_dummy; -+ pdata->set_speed = ath79_set_speed_ge0; - } else { - pdata->reset_bit = QCA955X_RESET_GE1_MAC | - QCA955X_RESET_GE1_MDIO; -- /* FIXME */ -+ - pdata->set_speed = ath79_set_speed_dummy; -+ -+ pdata->switch_data = &ath79_switch_data; -+ -+ pdata->speed = SPEED_1000; -+ pdata->duplex = DUPLEX_FULL; -+ -+ /* reset the built-in switch */ -+ ath79_device_reset_set(AR934X_RESET_ETH_SWITCH); -+ ath79_device_reset_clear(AR934X_RESET_ETH_SWITCH); - } - - pdata->ddr_flush = ath79_ddr_no_flush; -@@ -1196,6 +1206,11 @@ void __init ath79_register_eth(unsigned int id) - /* don't assign any MDIO device by default */ - break; - -+ case ATH79_SOC_QCA956X: -+ if (pdata->phy_if_mode != PHY_INTERFACE_MODE_SGMII) -+ pdata->mii_bus_dev = &ath79_mdio1_device.dev; -+ break; -+ - default: - pdata->mii_bus_dev = &ath79_mdio0_device.dev; - break; diff --git a/patches/openwrt/0042-ar71xx-Support-for-Ubiquiti-UniFi-AP-AC-LITE.patch b/patches/openwrt/0042-ar71xx-Support-for-Ubiquiti-UniFi-AP-AC-LITE.patch deleted file mode 100644 index 21390fc7..00000000 --- a/patches/openwrt/0042-ar71xx-Support-for-Ubiquiti-UniFi-AP-AC-LITE.patch +++ /dev/null @@ -1,562 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 20:47:26 +0200 -Subject: ar71xx: Support for Ubiquiti UniFi AP AC LITE - -Add support for the Ubiquiti UniFi AP AC LITE -Signed-off-by: P.Wassi - -Backport of OpenWrt r48711 - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index 5a184cd..8c6ac9a 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -296,7 +296,8 @@ get_status_led() { - unifi) - status_led="ubnt:green:dome" - ;; -- uap-pro) -+ uap-pro | \ -+ unifiac) - status_led="ubnt:white:dome" - ;; - unifi-outdoor-plus) -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -index b2e15bb..e4a1473 100755 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -@@ -366,6 +366,7 @@ tl-wa901nd-v3 |\ - tl-wa901nd-v4 |\ - tl-wr703n |\ - tube2h |\ -+unifiac |\ - wndap360 |\ - mynet-rext |\ - wp543) -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index ddd6611..8670583 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -881,6 +881,9 @@ ar71xx_board_detect() { - *UniFi) - name="unifi" - ;; -+ *"UniFi-AC") -+ name="unifiac" -+ ;; - *"UniFi AP Pro") - name="uap-pro" - ;; -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index c5c1871..4c43166 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -251,6 +251,7 @@ platform_check_image() { - wlae-ag300n | \ - nbg460n_550n_550nh | \ - unifi | \ -+ unifiac | \ - unifi-outdoor | \ - carambola2 | \ - weio ) -diff --git a/target/linux/ar71xx/config-3.18 b/target/linux/ar71xx/config-3.18 -index e2ff826..9a81911 100644 ---- a/target/linux/ar71xx/config-3.18 -+++ b/target/linux/ar71xx/config-3.18 -@@ -137,6 +137,7 @@ CONFIG_ATH79_MACH_TL_WR941ND=y - CONFIG_ATH79_MACH_TL_WR941ND_V6=y - CONFIG_ATH79_MACH_TUBE2H=y - CONFIG_ATH79_MACH_UBNT=y -+CONFIG_ATH79_MACH_UBNT_UNIFIAC=y - CONFIG_ATH79_MACH_UBNT_XM=y - CONFIG_ATH79_MACH_WEIO=y - CONFIG_ATH79_MACH_WHR_HP_G300N=y -@@ -320,7 +321,7 @@ CONFIG_SOC_AR933X=y - CONFIG_SOC_AR934X=y - CONFIG_SOC_QCA953X=y - CONFIG_SOC_QCA955X=y --# CONFIG_SOC_QCA956X is not set -+CONFIG_SOC_QCA956X=y - CONFIG_SPI=y - CONFIG_SPI_AP83=y - CONFIG_SPI_ATH79=y -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -new file mode 100644 -index 0000000..3617ca7 ---- /dev/null -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -@@ -0,0 +1,109 @@ -+/* -+ * Ubiquiti UniFi AC (LITE) board support -+ * -+ * Copyright (C) 2015-2016 P. Wassi -+ * -+ * Derived from: mach-ubnt-xm.c -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#include "common.h" -+#include "dev-ap9x-pci.h" -+#include "dev-eth.h" -+#include "dev-gpio-buttons.h" -+#include "dev-leds-gpio.h" -+#include "dev-m25p80.h" -+#include "dev-wmac.h" -+#include "machtypes.h" -+ -+ -+#define UNIFIAC_KEYS_POLL_INTERVAL 20 -+#define UNIFIAC_KEYS_DEBOUNCE_INTERVAL (3 * UNIFIAC_KEYS_POLL_INTERVAL) -+ -+#define UNIFIAC_GPIO_LED_WHITE 7 -+#define UNIFIAC_GPIO_LED_BLUE 8 -+ -+#define UNIFIAC_GPIO_BTN_RESET 2 -+ -+#define UNIFIAC_MAC0_OFFSET 0x0000 -+#define UNIFIAC_WMAC_CALDATA_OFFSET 0x1000 -+#define UNIFIAC_PCI_CALDATA_OFFSET 0x5000 -+ -+ -+static struct flash_platform_data ubnt_unifiac_flash_data = { -+ /* mx25l12805d and mx25l12835f have the same JEDEC ID */ -+ .type = "mx25l12805d", -+}; -+ -+static struct gpio_led ubnt_unifiac_leds_gpio[] __initdata = { -+ { -+ .name = "ubnt:white:dome", -+ .gpio = UNIFIAC_GPIO_LED_WHITE, -+ .active_low = 0, -+ }, { -+ .name = "ubnt:blue:dome", -+ .gpio = UNIFIAC_GPIO_LED_BLUE, -+ .active_low = 0, -+ } -+}; -+ -+static struct gpio_keys_button ubnt_unifiac_gpio_keys[] __initdata = { -+ { -+ .desc = "reset", -+ .type = EV_KEY, -+ .code = KEY_RESTART, -+ .debounce_interval = UNIFIAC_KEYS_DEBOUNCE_INTERVAL, -+ .gpio = UNIFIAC_GPIO_BTN_RESET, -+ .active_low = 1, -+ } -+}; -+ -+static void __init ubnt_unifiac_setup(void) -+{ -+ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); -+ -+ ath79_register_m25p80(&ubnt_unifiac_flash_data); -+ -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, -+ eeprom + UNIFIAC_MAC0_OFFSET, 0); -+ -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; -+ ath79_eth0_data.phy_mask = BIT(4); -+ ath79_eth0_pll_data.pll_10 = 0x00001313; -+ -+ ath79_register_mdio(0, ~BIT(4)); -+ ath79_register_eth(0); -+ -+ -+ ath79_register_wmac(eeprom + UNIFIAC_WMAC_CALDATA_OFFSET, NULL); -+ -+ -+ ap91_pci_init(eeprom + UNIFIAC_PCI_CALDATA_OFFSET, NULL); -+ -+ -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifiac_leds_gpio), -+ ubnt_unifiac_leds_gpio); -+ -+ ath79_register_gpio_keys_polled(-1, UNIFIAC_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(ubnt_unifiac_gpio_keys), -+ ubnt_unifiac_gpio_keys); -+} -+ -+MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC, "UBNT-UF-AC", "Ubiquiti UniFi-AC", -+ ubnt_unifiac_setup); -diff --git a/target/linux/ar71xx/generic/profiles/ubnt.mk b/target/linux/ar71xx/generic/profiles/ubnt.mk -index d8e24d0..94eff18 100644 ---- a/target/linux/ar71xx/generic/profiles/ubnt.mk -+++ b/target/linux/ar71xx/generic/profiles/ubnt.mk -@@ -38,6 +38,17 @@ endef - - $(eval $(call Profile,UBNTUNIFI)) - -+define Profile/UBNTUNIFIAC -+ NAME:=Ubiquiti UniFi AP AC -+ PACKAGES:=kmod-ath10k ath10k-firmware-qca988x -+endef -+ -+define Profile/UBNTUNIFIAC/Description -+ Package set optimized for the Ubiquiti UniFi AP AC. -+endef -+ -+$(eval $(call Profile,UBNTUNIFIAC)) -+ - define Profile/UBNTUNIFIOUTDOOR - NAME:=Ubiquiti UniFiAP Outdoor - PACKAGES:= -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index d42ceef..dd59f2d 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -740,6 +740,16 @@ define Device/oolite - endef - TARGET_DEVICES += oolite - -+define Device/ubnt-unifiac -+ DEVICE_PROFILE := UBNT UBNTUNIFIAC -+ IMAGE_SIZE := 7744k -+ MTDPARTS = spi0.0:384k(u-boot)ro,64k(u-boot-env)ro,7744k(firmware),7744k(ubnt-airos)ro,128k(bs)ro,256k(cfg)ro,64k(EEPROM)ro -+ IMAGES := sysupgrade.bin -+ IMAGE/sysupgrade.bin = append-kernel $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) -+ BOARDNAME := UBNT-UF-AC -+endef -+TARGET_DEVICES += ubnt-unifiac -+ - rootfs_type=$(patsubst jffs2-%,jffs2,$(patsubst squashfs-%,squashfs,$(1))) - - # $(1): rootfs type. -diff --git a/target/linux/ar71xx/mikrotik/config-default b/target/linux/ar71xx/mikrotik/config-default -index b8a7bf1..2b1fe24 100644 ---- a/target/linux/ar71xx/mikrotik/config-default -+++ b/target/linux/ar71xx/mikrotik/config-default -@@ -97,6 +97,7 @@ CONFIG_ATH79_MACH_RBSXTLITE=y - # CONFIG_ATH79_MACH_TUBE2H is not set - # CONFIG_ATH79_MACH_UBNT is not set - # CONFIG_ATH79_MACH_UBNT_XM is not set -+# CONFIG_ATH79_MACH_UBNT_UNIFIAC is not set - # CONFIG_ATH79_MACH_WHR_HP_G300N is not set - # CONFIG_ATH79_MACH_WLAE_AG300N is not set - # CONFIG_ATH79_MACH_WLR8100 is not set -diff --git a/target/linux/ar71xx/nand/config-default b/target/linux/ar71xx/nand/config-default -index 626d676..f62cf1a 100644 ---- a/target/linux/ar71xx/nand/config-default -+++ b/target/linux/ar71xx/nand/config-default -@@ -59,6 +59,7 @@ - # CONFIG_ATH79_MACH_TL_WR941ND is not set - # CONFIG_ATH79_MACH_UBNT is not set - # CONFIG_ATH79_MACH_UBNT_XM is not set -+# CONFIG_ATH79_MACH_UBNT_UNIFIAC is not set - # CONFIG_ATH79_MACH_WHR_HP_G300N is not set - # CONFIG_ATH79_MACH_WLAE_AG300N is not set - # CONFIG_ATH79_MACH_WNDAP360 is not set -diff --git a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -index d6e786d..5a7a72c 100644 ---- a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -+++ b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -@@ -1,6 +1,6 @@ - --- a/arch/mips/ath79/machtypes.h - +++ b/arch/mips/ath79/machtypes.h --@@ -16,22 +16,199 @@ -+@@ -16,22 +16,200 @@ - - enum ath79_mach_type { - ATH79_MACH_GENERIC = 0, -@@ -164,6 +164,7 @@ - + ATH79_MACH_UBNT_RS, /* Ubiquiti RouterStation */ - ATH79_MACH_UBNT_UAP_PRO, /* Ubiquiti UniFi AP Pro */ - ATH79_MACH_UBNT_UNIFI, /* Ubiquiti Unifi */ -++ ATH79_MACH_UBNT_UNIFIAC, /* Ubiquiti Unifi AC */ - ATH79_MACH_UBNT_UNIFI_OUTDOOR, /* Ubiquiti UnifiAP Outdoor */ - + ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, /* Ubiquiti UnifiAP Outdoor+ */ - ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */ -@@ -1097,10 +1098,7 @@ - + select ATH79_DEV_M25P80 - + select ATH79_DEV_USB - + select ATH79_DEV_WMAC -- ---config ATH79_MACH_AP136 --- bool "Atheros AP136/AP135 reference board" --- select SOC_QCA955X -++ - +config ATH79_MACH_TL_WA7210N_V2 - + bool "TP-LINK TL-WA7210N v2 support" - + select SOC_AR724X -@@ -1115,19 +1113,12 @@ - + bool "TP-LINK TL-WA830RE v2 support" - + select SOC_AR934X - + select ATH79_DEV_ETH -- select ATH79_DEV_GPIO_BUTTONS -- select ATH79_DEV_LEDS_GPIO --- select ATH79_DEV_NFC --- select ATH79_DEV_SPI -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO - + select ATH79_DEV_M25P80 -- select ATH79_DEV_USB -- select ATH79_DEV_WMAC --- help --- Say 'Y' here if you want your kernel to support the --- Atheros AP136 or AP135 reference boards. -- ---config ATH79_MACH_AP81 --- bool "Atheros AP81 reference board" -++ select ATH79_DEV_USB -++ select ATH79_DEV_WMAC -++ - +config ATH79_MACH_TL_WA901ND - + bool "TP-LINK TL-WA901ND/TL-WA7510N support" - + select SOC_AR724X -@@ -1139,11 +1130,11 @@ - + - +config ATH79_MACH_TL_WA901ND_V2 - + bool "TP-LINK TL-WA901ND v2 support" -- select SOC_AR913X -- select ATH79_DEV_ETH -- select ATH79_DEV_GPIO_BUTTONS -- select ATH79_DEV_LEDS_GPIO -- select ATH79_DEV_M25P80 -++ select SOC_AR913X -++ select ATH79_DEV_ETH -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO -++ select ATH79_DEV_M25P80 - + select ATH79_DEV_WMAC - + - +config ATH79_MACH_TL_WDR3500 -@@ -1154,34 +1145,13 @@ - + select ATH79_DEV_GPIO_BUTTONS - + select ATH79_DEV_LEDS_GPIO - + select ATH79_DEV_M25P80 -- select ATH79_DEV_USB -- select ATH79_DEV_WMAC --- help --- Say 'Y' here if you want your kernel to support the --- Atheros AP81 reference board. -- ---config ATH79_MACH_DB120 --- bool "Atheros DB120 reference board" -++ select ATH79_DEV_USB -++ select ATH79_DEV_WMAC -++ - +config ATH79_MACH_TL_WDR4300 - + bool "TP-LINK TL-WDR3600/4300/4310 board support" -- select SOC_AR934X -- select ATH79_DEV_AP9X_PCI if PCI -- select ATH79_DEV_ETH -- select ATH79_DEV_GPIO_BUTTONS -- select ATH79_DEV_LEDS_GPIO -- select ATH79_DEV_M25P80 --- select ATH79_DEV_NFC -- select ATH79_DEV_USB -- select ATH79_DEV_WMAC --- help --- Say 'Y' here if you want your kernel to support the --- Atheros DB120 reference board. -- ---config ATH79_MACH_PB44 --- bool "Atheros PB44 reference board" --+config ATH79_MACH_TL_WR703N --+ bool "TP-LINK TL-WR703N/TL-WR710N/TL-MR10U support" --+ select SOC_AR933X -++ select SOC_AR934X -++ select ATH79_DEV_AP9X_PCI if PCI - + select ATH79_DEV_ETH - + select ATH79_DEV_GPIO_BUTTONS - + select ATH79_DEV_LEDS_GPIO -@@ -1189,8 +1159,8 @@ - + select ATH79_DEV_USB - + select ATH79_DEV_WMAC - + --+config ATH79_MACH_TL_WR720N_V3 --+ bool "TP-LINK TL-WR720N v3/v4 support" -++config ATH79_MACH_TL_WR703N -++ bool "TP-LINK TL-WR703N/TL-WR710N/TL-MR10U support" - + select SOC_AR933X - + select ATH79_DEV_ETH - + select ATH79_DEV_GPIO_BUTTONS -@@ -1198,7 +1168,28 @@ - + select ATH79_DEV_M25P80 - + select ATH79_DEV_USB - + select ATH79_DEV_WMAC --+ -+ -+-config ATH79_MACH_AP136 -+- bool "Atheros AP136/AP135 reference board" -+- select SOC_QCA955X -++config ATH79_MACH_TL_WR720N_V3 -++ bool "TP-LINK TL-WR720N v3/v4 support" -++ select SOC_AR933X -++ select ATH79_DEV_ETH -+ select ATH79_DEV_GPIO_BUTTONS -+ select ATH79_DEV_LEDS_GPIO -+- select ATH79_DEV_NFC -+- select ATH79_DEV_SPI -++ select ATH79_DEV_M25P80 -+ select ATH79_DEV_USB -+ select ATH79_DEV_WMAC -+- help -+- Say 'Y' here if you want your kernel to support the -+- Atheros AP136 or AP135 reference boards. -+ -+-config ATH79_MACH_AP81 -+- bool "Atheros AP81 reference board" -+- select SOC_AR913X - +config ATH79_MACH_TL_WR741ND - + bool "TP-LINK TL-WR741ND support" - + select SOC_AR724X -@@ -1211,21 +1202,25 @@ - +config ATH79_MACH_TL_WR741ND_V4 - + bool "TP-LINK TL-WR741ND v4/TL-MR3220 v2 support" - + select SOC_AR933X --+ select ATH79_DEV_ETH --+ select ATH79_DEV_GPIO_BUTTONS --+ select ATH79_DEV_LEDS_GPIO --+ select ATH79_DEV_M25P80 --+ select ATH79_DEV_USB --+ select ATH79_DEV_WMAC --+ --+config ATH79_MACH_TL_WR841N_V1 --+ bool "TP-LINK TL-WR841N v1 support" -- select SOC_AR71XX --+ select ATH79_DEV_DSA - select ATH79_DEV_ETH - select ATH79_DEV_GPIO_BUTTONS - select ATH79_DEV_LEDS_GPIO --- select ATH79_DEV_SPI -+ select ATH79_DEV_M25P80 -+ select ATH79_DEV_USB -+ select ATH79_DEV_WMAC -+- help -+- Say 'Y' here if you want your kernel to support the -+- Atheros AP81 reference board. -+ -+-config ATH79_MACH_DB120 -+- bool "Atheros DB120 reference board" -++config ATH79_MACH_TL_WR841N_V1 -++ bool "TP-LINK TL-WR841N v1 support" -++ select SOC_AR71XX -++ select ATH79_DEV_DSA -++ select ATH79_DEV_ETH -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO - + select ATH79_DEV_M25P80 - + - +config ATH79_MACH_TL_WR841N_V8 -@@ -1268,15 +1263,21 @@ - + - +config ATH79_MACH_TL_WR1041N_V2 - + bool "TP-LINK TL-WR1041N v2 support" --+ select SOC_AR934X --+ select ATH79_DEV_AP9X_PCI if PCI --+ select ATH79_DEV_ETH --+ select ATH79_DEV_GPIO_BUTTONS --+ select ATH79_DEV_LEDS_GPIO --+ select ATH79_DEV_M25P80 --+ select ATH79_DEV_USB --+ select ATH79_DEV_WMAC --+ -+ select SOC_AR934X -+ select ATH79_DEV_AP9X_PCI if PCI -+ select ATH79_DEV_ETH -+ select ATH79_DEV_GPIO_BUTTONS -+ select ATH79_DEV_LEDS_GPIO -+ select ATH79_DEV_M25P80 -+- select ATH79_DEV_NFC -+ select ATH79_DEV_USB -+ select ATH79_DEV_WMAC -+- help -+- Say 'Y' here if you want your kernel to support the -+- Atheros DB120 reference board. -+ -+-config ATH79_MACH_PB44 -+- bool "Atheros PB44 reference board" - +config ATH79_MACH_TL_WR1043ND - + bool "TP-LINK TL-WR1043ND support" - + select SOC_AR913X -@@ -1319,11 +1320,12 @@ - + - +config ATH79_MACH_TEW_673GRU - + bool "TRENDnet TEW-673GRU support" --+ select SOC_AR71XX -+ select SOC_AR71XX - + select ATH79_DEV_AP9X_PCI if PCI --+ select ATH79_DEV_ETH --+ select ATH79_DEV_GPIO_BUTTONS --+ select ATH79_DEV_LEDS_GPIO -+ select ATH79_DEV_ETH -+ select ATH79_DEV_GPIO_BUTTONS -+ select ATH79_DEV_LEDS_GPIO -+- select ATH79_DEV_SPI - + select ATH79_DEV_M25P80 - + select ATH79_DEV_USB - + select ATH79_NVRAM -@@ -1361,10 +1363,20 @@ - - config ATH79_MACH_UBNT_XM - bool "Ubiquiti Networks XM/UniFi boards" --@@ -83,6 +1144,106 @@ config ATH79_MACH_UBNT_XM -+@@ -83,6 +1144,116 @@ config ATH79_MACH_UBNT_XM - Say 'Y' here if you want your kernel to support the - Ubiquiti Networks XM (rev 1.0) board. - -++config ATH79_MACH_UBNT_UNIFIAC -++ bool "Ubiquiti UniFi AC (LITE) support" -++ select SOC_QCA956X -++ select ATH79_DEV_AP9X_PCI if PCI -++ select ATH79_DEV_ETH -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO -++ select ATH79_DEV_M25P80 -++ select ATH79_DEV_WMAC -++ - +config ATH79_MACH_WEIO - + bool "WeIO board" - + select SOC_AR933X -@@ -1468,7 +1480,7 @@ - endmenu - - config SOC_AR71XX --@@ -124,7 +1285,10 @@ config ATH79_DEV_DSA -+@@ -124,7 +1295,10 @@ config ATH79_DEV_DSA - config ATH79_DEV_ETH - def_bool n - -@@ -1480,7 +1492,7 @@ - def_bool n - - config ATH79_DEV_GPIO_BUTTONS --@@ -154,6 +1318,11 @@ config ATH79_PCI_ATH9K_FIXUP -+@@ -154,6 +1328,11 @@ config ATH79_PCI_ATH9K_FIXUP - def_bool n - - config ATH79_ROUTERBOOT -@@ -1494,7 +1506,7 @@ - endif - --- a/arch/mips/ath79/Makefile - +++ b/arch/mips/ath79/Makefile --@@ -38,9 +38,128 @@ obj-$(CONFIG_ATH79_ROUTERBOOT) += route -+@@ -38,9 +38,129 @@ obj-$(CONFIG_ATH79_ROUTERBOOT) += route - # - # Machines - # -@@ -1596,6 +1608,7 @@ - +obj-$(CONFIG_ATH79_MACH_TL_WR720N_V3) += mach-tl-wr720n-v3.o - +obj-$(CONFIG_ATH79_MACH_TUBE2H) += mach-tube2h.o - +obj-$(CONFIG_ATH79_MACH_UBNT) += mach-ubnt.o -++obj-$(CONFIG_ATH79_MACH_UBNT_UNIFIAC) += mach-ubnt-unifiac.o - obj-$(CONFIG_ATH79_MACH_UBNT_XM) += mach-ubnt-xm.o - +obj-$(CONFIG_ATH79_MACH_WEIO) += mach-weio.o - +obj-$(CONFIG_ATH79_MACH_WHR_HP_G300N) += mach-whr-hp-g300n.o diff --git a/patches/openwrt/0043-ar71xx-Fix-eth0-support-for-Ubiquiti-UniFi-AP-AC.patch b/patches/openwrt/0043-ar71xx-Fix-eth0-support-for-Ubiquiti-UniFi-AP-AC.patch deleted file mode 100644 index bae7f32e..00000000 --- a/patches/openwrt/0043-ar71xx-Fix-eth0-support-for-Ubiquiti-UniFi-AP-AC.patch +++ /dev/null @@ -1,21 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:02:55 +0200 -Subject: ar71xx: Fix eth0 support for Ubiquiti UniFi AP AC - -Fix eth0 support for the Ubiquiti UniFi AP AC -Signed-off-by: Paul Wassi - -Backport of OpenWrt r49277 - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -index 3617ca7..072cf12 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -@@ -84,6 +84,7 @@ static void __init ubnt_unifiac_setup(void) - eeprom + UNIFIAC_MAC0_OFFSET, 0); - - ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; - ath79_eth0_data.phy_mask = BIT(4); - ath79_eth0_pll_data.pll_10 = 0x00001313; - diff --git a/patches/openwrt/0044-ar71xx-Rename-unifiac-to-unifiac-lite.patch b/patches/openwrt/0044-ar71xx-Rename-unifiac-to-unifiac-lite.patch deleted file mode 100644 index cbd40637..00000000 --- a/patches/openwrt/0044-ar71xx-Rename-unifiac-to-unifiac-lite.patch +++ /dev/null @@ -1,192 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:24:44 +0200 -Subject: ar71xx: Rename unifiac to unifiac-lite - -To avoid confusion with different unifiac devices, rename existing target -"unifiac" to "unifiac-lite", before "unifiac-pro" is introduced. - -Signed-off-by: P.Wassi - -Backport of LEDE c855e70491fbd5d432915c4cbeb3b80f3a117e30 - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index 8c6ac9a..3d711ca 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -297,7 +297,7 @@ get_status_led() { - status_led="ubnt:green:dome" - ;; - uap-pro | \ -- unifiac) -+ unifiac-lite) - status_led="ubnt:white:dome" - ;; - unifi-outdoor-plus) -diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -index e6fcec8..fa8a2c8 100644 ---- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -+++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -@@ -75,7 +75,7 @@ case "$FIRMWARE" in - ath10kcal_extract "ART" 20480 2116 - ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) - ;; -- unifiac) -+ unifiac-lite) - ath10kcal_extract "EEPROM" 20480 2116 - ;; - esac -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -index e4a1473..0269e6d 100755 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -@@ -366,7 +366,7 @@ tl-wa901nd-v3 |\ - tl-wa901nd-v4 |\ - tl-wr703n |\ - tube2h |\ --unifiac |\ -+unifiac-lite |\ - wndap360 |\ - mynet-rext |\ - wp543) -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index 8670583..d3e6db9 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -881,8 +881,8 @@ ar71xx_board_detect() { - *UniFi) - name="unifi" - ;; -- *"UniFi-AC") -- name="unifiac" -+ *"UniFi-AC-LITE") -+ name="unifiac-lite" - ;; - *"UniFi AP Pro") - name="uap-pro" -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index 4c43166..a1b65b7 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -251,7 +251,7 @@ platform_check_image() { - wlae-ag300n | \ - nbg460n_550n_550nh | \ - unifi | \ -- unifiac | \ -+ unifiac-lite | \ - unifi-outdoor | \ - carambola2 | \ - weio ) -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -index 072cf12..31cbe30 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -@@ -73,7 +73,7 @@ static struct gpio_keys_button ubnt_unifiac_gpio_keys[] __initdata = { - } - }; - --static void __init ubnt_unifiac_setup(void) -+static void __init ubnt_unifiac_lite_setup(void) - { - u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); - -@@ -81,7 +81,7 @@ static void __init ubnt_unifiac_setup(void) - - - ath79_init_mac(ath79_eth0_data.mac_addr, -- eeprom + UNIFIAC_MAC0_OFFSET, 0); -+ eeprom + UNIFIAC_MAC0_OFFSET, 0); - - ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; - ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; -@@ -99,12 +99,12 @@ static void __init ubnt_unifiac_setup(void) - - - ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifiac_leds_gpio), -- ubnt_unifiac_leds_gpio); -+ ubnt_unifiac_leds_gpio); - - ath79_register_gpio_keys_polled(-1, UNIFIAC_KEYS_POLL_INTERVAL, -- ARRAY_SIZE(ubnt_unifiac_gpio_keys), -- ubnt_unifiac_gpio_keys); -+ ARRAY_SIZE(ubnt_unifiac_gpio_keys), -+ ubnt_unifiac_gpio_keys); - } - --MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC, "UBNT-UF-AC", "Ubiquiti UniFi-AC", -- ubnt_unifiac_setup); -+MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC_LITE, "UBNT-UF-AC-LITE", "Ubiquiti UniFi-AC-LITE", -+ ubnt_unifiac_lite_setup); -diff --git a/target/linux/ar71xx/generic/profiles/ubnt.mk b/target/linux/ar71xx/generic/profiles/ubnt.mk -index 94eff18..eac0240 100644 ---- a/target/linux/ar71xx/generic/profiles/ubnt.mk -+++ b/target/linux/ar71xx/generic/profiles/ubnt.mk -@@ -38,16 +38,16 @@ endef - - $(eval $(call Profile,UBNTUNIFI)) - --define Profile/UBNTUNIFIAC -- NAME:=Ubiquiti UniFi AP AC -+define Profile/UBNTUNIFIACLITE -+ NAME:=Ubiquiti UniFi AP AC LITE/LR - PACKAGES:=kmod-ath10k ath10k-firmware-qca988x - endef - --define Profile/UBNTUNIFIAC/Description -- Package set optimized for the Ubiquiti UniFi AP AC. -+define Profile/UBNTUNIFIACLITE/Description -+ Package set optimized for the Ubiquiti UniFi AP AC LITE/LR. - endef - --$(eval $(call Profile,UBNTUNIFIAC)) -+$(eval $(call Profile,UBNTUNIFIACLITE)) - - define Profile/UBNTUNIFIOUTDOOR - NAME:=Ubiquiti UniFiAP Outdoor -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index dd59f2d..31aff78 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -741,14 +741,19 @@ endef - TARGET_DEVICES += oolite - - define Device/ubnt-unifiac -- DEVICE_PROFILE := UBNT UBNTUNIFIAC -+ DEVICE_PROFILE := UBNT - IMAGE_SIZE := 7744k - MTDPARTS = spi0.0:384k(u-boot)ro,64k(u-boot-env)ro,7744k(firmware),7744k(ubnt-airos)ro,128k(bs)ro,256k(cfg)ro,64k(EEPROM)ro - IMAGES := sysupgrade.bin - IMAGE/sysupgrade.bin = append-kernel $$$$(BLOCKSIZE) | append-rootfs | pad-rootfs | check-size $$$$(IMAGE_SIZE) -+endef -+ -+define Device/ubnt-unifiac-lite -+ $(Device/ubnt-unifiac) -+ DEVICE_PROFILE := UBNT UBNTUNIFIACLITE - BOARDNAME := UBNT-UF-AC - endef --TARGET_DEVICES += ubnt-unifiac -+TARGET_DEVICES += ubnt-unifiac-lite - - rootfs_type=$(patsubst jffs2-%,jffs2,$(patsubst squashfs-%,squashfs,$(1))) - -diff --git a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -index 5a7a72c..0ade403 100644 ---- a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -+++ b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -@@ -164,7 +164,7 @@ - + ATH79_MACH_UBNT_RS, /* Ubiquiti RouterStation */ - ATH79_MACH_UBNT_UAP_PRO, /* Ubiquiti UniFi AP Pro */ - ATH79_MACH_UBNT_UNIFI, /* Ubiquiti Unifi */ --+ ATH79_MACH_UBNT_UNIFIAC, /* Ubiquiti Unifi AC */ -++ ATH79_MACH_UBNT_UNIFIAC_LITE, /* Ubiquiti Unifi AC LITE/LR */ - ATH79_MACH_UBNT_UNIFI_OUTDOOR, /* Ubiquiti UnifiAP Outdoor */ - + ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, /* Ubiquiti UnifiAP Outdoor+ */ - ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */ -@@ -1368,7 +1368,7 @@ - Ubiquiti Networks XM (rev 1.0) board. - - +config ATH79_MACH_UBNT_UNIFIAC --+ bool "Ubiquiti UniFi AC (LITE) support" -++ bool "Ubiquiti UniFi AC (LITE/LR) support" - + select SOC_QCA956X - + select ATH79_DEV_AP9X_PCI if PCI - + select ATH79_DEV_ETH diff --git a/patches/openwrt/0045-ar71xx-Add-support-for-Ubiquiti-UniFi-AP-AC-PRO.patch b/patches/openwrt/0045-ar71xx-Add-support-for-Ubiquiti-UniFi-AP-AC-PRO.patch deleted file mode 100644 index 30cf6d46..00000000 --- a/patches/openwrt/0045-ar71xx-Add-support-for-Ubiquiti-UniFi-AP-AC-PRO.patch +++ /dev/null @@ -1,274 +0,0 @@ -From: Matthias Schiffer -Date: Fri, 13 May 2016 21:34:05 +0200 -Subject: ar71xx: Add support for Ubiquiti UniFi AP AC PRO - -Add support for the Ubiquiti UniFi AP AC PRO -Signed-off-by: P.Wassi - -Backport of LEDE 8307c2fe686ded345c80318359d5b6679e581fa2 - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index 3d711ca..775aac6 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -297,7 +297,8 @@ get_status_led() { - status_led="ubnt:green:dome" - ;; - uap-pro | \ -- unifiac-lite) -+ unifiac-lite | \ -+ unifiac-pro) - status_led="ubnt:white:dome" - ;; - unifi-outdoor-plus) -diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -index fa8a2c8..cde7aaf 100644 ---- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -+++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -@@ -75,7 +75,8 @@ case "$FIRMWARE" in - ath10kcal_extract "ART" 20480 2116 - ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) - ;; -- unifiac-lite) -+ unifiac-lite | \ -+ unifiac-pro) - ath10kcal_extract "EEPROM" 20480 2116 - ;; - esac -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -index 0269e6d..0a23756 100755 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -@@ -398,6 +398,13 @@ wpj344) - ucidef_add_switch_vlan "switch0" "2" "0t 2" - ;; - -+unifiac-pro) -+ ucidef_set_interfaces_lan_wan "eth0.1" "eth0.2" -+ ucidef_add_switch "switch0" "1" "1" -+ ucidef_add_switch_vlan "switch0" "1" "0t 2" -+ ucidef_add_switch_vlan "switch0" "2" "0t 3" -+ ;; -+ - wpj531) - ucidef_set_interfaces_lan_wan "eth0" "eth1" - ;; -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index d3e6db9..7fc951a 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -884,6 +884,9 @@ ar71xx_board_detect() { - *"UniFi-AC-LITE") - name="unifiac-lite" - ;; -+ *"UniFi-AC-PRO") -+ name="unifiac-pro" -+ ;; - *"UniFi AP Pro") - name="uap-pro" - ;; -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index a1b65b7..0e9833d 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -252,6 +252,7 @@ platform_check_image() { - nbg460n_550n_550nh | \ - unifi | \ - unifiac-lite | \ -+ unifiac-pro | \ - unifi-outdoor | \ - carambola2 | \ - weio ) -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -index 31cbe30..9194bc1 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-ubnt-unifiac.c -@@ -21,6 +21,7 @@ - #include - - #include -+#include - - #include "common.h" - #include "dev-ap9x-pci.h" -@@ -29,6 +30,7 @@ - #include "dev-leds-gpio.h" - #include "dev-m25p80.h" - #include "dev-wmac.h" -+#include "dev-usb.h" - #include "machtypes.h" - - -@@ -108,3 +110,70 @@ static void __init ubnt_unifiac_lite_setup(void) - - MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC_LITE, "UBNT-UF-AC-LITE", "Ubiquiti UniFi-AC-LITE", - ubnt_unifiac_lite_setup); -+ -+static struct ar8327_pad_cfg ubnt_unifiac_pro_ar8327_pad0_cfg = { -+ .mode = AR8327_PAD_MAC_SGMII, -+ .sgmii_delay_en = true, -+}; -+ -+static struct ar8327_platform_data ubnt_unifiac_pro_ar8327_data = { -+ .pad0_cfg = &ubnt_unifiac_pro_ar8327_pad0_cfg, -+ .port0_cfg = { -+ .force_link = 1, -+ .speed = AR8327_PORT_SPEED_1000, -+ .duplex = 1, -+ .txpause = 1, -+ .rxpause = 1, -+ }, -+}; -+ -+ -+static struct mdio_board_info ubnt_unifiac_pro_mdio0_info[] = { -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 0, -+ .platform_data = &ubnt_unifiac_pro_ar8327_data, -+ }, -+}; -+ -+static void __init ubnt_unifiac_pro_setup(void) -+{ -+ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff0000); -+ -+ ath79_register_m25p80(&ubnt_unifiac_flash_data); -+ -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, -+ eeprom + UNIFIAC_MAC0_OFFSET, 0); -+ -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; -+ ath79_eth0_data.phy_mask = BIT(0); -+ -+ mdiobus_register_board_info(ubnt_unifiac_pro_mdio0_info, -+ ARRAY_SIZE(ubnt_unifiac_pro_mdio0_info)); -+ -+ ath79_register_mdio(0, 0x00); -+ ath79_register_eth(0); -+ -+ -+ ath79_register_usb(); -+ -+ -+ ath79_register_wmac(eeprom + UNIFIAC_WMAC_CALDATA_OFFSET, NULL); -+ -+ -+ ap91_pci_init(eeprom + UNIFIAC_PCI_CALDATA_OFFSET, NULL); -+ -+ -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(ubnt_unifiac_leds_gpio), -+ ubnt_unifiac_leds_gpio); -+ -+ ath79_register_gpio_keys_polled(-1, UNIFIAC_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(ubnt_unifiac_gpio_keys), -+ ubnt_unifiac_gpio_keys); -+} -+ -+ -+MIPS_MACHINE(ATH79_MACH_UBNT_UNIFIAC_PRO, "UBNT-UF-AC-PRO", "Ubiquiti UniFi-AC-PRO", -+ ubnt_unifiac_pro_setup); -diff --git a/target/linux/ar71xx/generic/profiles/ubnt.mk b/target/linux/ar71xx/generic/profiles/ubnt.mk -index eac0240..69b8398 100644 ---- a/target/linux/ar71xx/generic/profiles/ubnt.mk -+++ b/target/linux/ar71xx/generic/profiles/ubnt.mk -@@ -49,6 +49,17 @@ endef - - $(eval $(call Profile,UBNTUNIFIACLITE)) - -+define Profile/UBNTUNIFIACPRO -+ NAME:=Ubiquiti UniFi AP AC PRO -+ PACKAGES:=kmod-ath10k ath10k-firmware-qca988x kmod-usb-core kmod-usb-ohci kmod-usb2 -+endef -+ -+define Profile/UBNTUNIFIACPRO/Description -+ Package set optimized for the Ubiquiti UniFi AP AC PRO. -+endef -+ -+$(eval $(call Profile,UBNTUNIFIACPRO)) -+ - define Profile/UBNTUNIFIOUTDOOR - NAME:=Ubiquiti UniFiAP Outdoor - PACKAGES:= -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index 31aff78..916d4e2 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -753,7 +753,13 @@ define Device/ubnt-unifiac-lite - DEVICE_PROFILE := UBNT UBNTUNIFIACLITE - BOARDNAME := UBNT-UF-AC - endef --TARGET_DEVICES += ubnt-unifiac-lite -+ -+define Device/ubnt-unifiac-pro -+ $(Device/ubnt-unifiac) -+ DEVICE_PROFILE := UBNT UBNTUNIFIACPRO -+ BOARDNAME := UBNT-UF-AC-PRO -+endef -+TARGET_DEVICES += ubnt-unifiac-lite ubnt-unifiac-pro - - rootfs_type=$(patsubst jffs2-%,jffs2,$(patsubst squashfs-%,squashfs,$(1))) - -diff --git a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -index 0ade403..dbd3fca 100644 ---- a/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -+++ b/target/linux/ar71xx/patches-3.18/610-MIPS-ath79-openwrt-machines.patch -@@ -1,6 +1,6 @@ - --- a/arch/mips/ath79/machtypes.h - +++ b/arch/mips/ath79/machtypes.h --@@ -16,22 +16,200 @@ -+@@ -16,22 +16,201 @@ - - enum ath79_mach_type { - ATH79_MACH_GENERIC = 0, -@@ -165,6 +165,7 @@ - ATH79_MACH_UBNT_UAP_PRO, /* Ubiquiti UniFi AP Pro */ - ATH79_MACH_UBNT_UNIFI, /* Ubiquiti Unifi */ - + ATH79_MACH_UBNT_UNIFIAC_LITE, /* Ubiquiti Unifi AC LITE/LR */ -++ ATH79_MACH_UBNT_UNIFIAC_PRO, /* Ubiquiti Unifi AC PRO */ - ATH79_MACH_UBNT_UNIFI_OUTDOOR, /* Ubiquiti UnifiAP Outdoor */ - + ATH79_MACH_UBNT_UNIFI_OUTDOOR_PLUS, /* Ubiquiti UnifiAP Outdoor+ */ - ATH79_MACH_UBNT_XM, /* Ubiquiti Networks XM board rev 1.0 */ -@@ -1363,12 +1364,12 @@ - - config ATH79_MACH_UBNT_XM - bool "Ubiquiti Networks XM/UniFi boards" --@@ -83,6 +1144,116 @@ config ATH79_MACH_UBNT_XM -+@@ -83,6 +1144,117 @@ config ATH79_MACH_UBNT_XM - Say 'Y' here if you want your kernel to support the - Ubiquiti Networks XM (rev 1.0) board. - - +config ATH79_MACH_UBNT_UNIFIAC --+ bool "Ubiquiti UniFi AC (LITE/LR) support" -++ bool "Ubiquiti UniFi AC (LITE/LR/PRO) support" - + select SOC_QCA956X - + select ATH79_DEV_AP9X_PCI if PCI - + select ATH79_DEV_ETH -@@ -1376,6 +1377,7 @@ - + select ATH79_DEV_LEDS_GPIO - + select ATH79_DEV_M25P80 - + select ATH79_DEV_WMAC -++ select ATH79_DEV_USB - + - +config ATH79_MACH_WEIO - + bool "WeIO board" -@@ -1480,7 +1482,7 @@ - endmenu - - config SOC_AR71XX --@@ -124,7 +1295,10 @@ config ATH79_DEV_DSA -+@@ -124,7 +1296,10 @@ config ATH79_DEV_DSA - config ATH79_DEV_ETH - def_bool n - -@@ -1492,7 +1494,7 @@ - def_bool n - - config ATH79_DEV_GPIO_BUTTONS --@@ -154,6 +1328,11 @@ config ATH79_PCI_ATH9K_FIXUP -+@@ -154,6 +1329,11 @@ config ATH79_PCI_ATH9K_FIXUP - def_bool n - - config ATH79_ROUTERBOOT diff --git a/patches/openwrt/0046-ar71xx-Generate-sysupgrade-images-for-OpenMesh-devic.patch b/patches/openwrt/0046-ar71xx-Generate-sysupgrade-images-for-OpenMesh-devic.patch deleted file mode 100644 index 6470646d..00000000 --- a/patches/openwrt/0046-ar71xx-Generate-sysupgrade-images-for-OpenMesh-devic.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Sven Eckelmann -Date: Tue, 17 May 2016 16:38:29 +0200 -Subject: ar71xx: Generate sysupgrade images for OpenMesh devices - -Some OpenWrt based firmwares like Gluon expect that a sysupgrade image -exists when a device firmware can be updated via sysupgrade. This image -wasn't created until now because OpenMesh devices use the same image for -factory and sysupgrade flash. Copying the image from *factory.bin to -*sysupgrade.bin is therefore enough to make the sysupgrade functionality -visible. - -Reported-by: Matthias Schiffer -Signed-off-by: Sven Eckelmann - -Forwarded: https://patchwork.ozlabs.org/patch/624172/ - -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index 916d4e2..f91e20e 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -1877,6 +1877,9 @@ define Image/Build/OpenMesh - "$(BUILD_DIR)/fwupgrade.cfg-$(4)" "fwupgrade.cfg" \ - "$(KDIR_TMP)/vmlinux-$(2).uImage" "kernel" \ - "$(KDIR)/root.$(1)" "rootfs" -+ if [ -e "$(call factoryname,$(1),$(2))" ]; then \ -+ cp "$(call factoryname,$(1),$(2))" "$(call sysupname,$(1),$(2))"; \ -+ fi - endef - - diff --git a/patches/openwrt/0047-ar71xx-add-kernel-support-for-the-OpenMesh-MR1750-bo.patch b/patches/openwrt/0047-ar71xx-add-kernel-support-for-the-OpenMesh-MR1750-bo.patch deleted file mode 100644 index 35dcac61..00000000 --- a/patches/openwrt/0047-ar71xx-add-kernel-support-for-the-OpenMesh-MR1750-bo.patch +++ /dev/null @@ -1,202 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:10:43 +0000 -Subject: ar71xx: add kernel support for the OpenMesh MR1750 board - -Signed-off-by: Sven Eckelmann - -Backport of r46926 - -Forwarded: https://patchwork.ozlabs.org/patch/624173/ - -diff --git a/target/linux/ar71xx/config-3.18 b/target/linux/ar71xx/config-3.18 -index 9a81911..c5a3c9a 100644 ---- a/target/linux/ar71xx/config-3.18 -+++ b/target/linux/ar71xx/config-3.18 -@@ -79,6 +79,7 @@ CONFIG_ATH79_MACH_JWAP003=y - CONFIG_ATH79_MACH_MC_MAC1200R=y - CONFIG_ATH79_MACH_MR16=y - CONFIG_ATH79_MACH_MR12=y -+CONFIG_ATH79_MACH_MR1750=y - CONFIG_ATH79_MACH_MR600=y - CONFIG_ATH79_MACH_MR900=y - CONFIG_ATH79_MACH_MYNET_N600=y -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -new file mode 100644 -index 0000000..8ace02f ---- /dev/null -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -@@ -0,0 +1,129 @@ -+/* -+ * MR1750 board support -+ * -+ * Copyright (c) 2012 Qualcomm Atheros -+ * Copyright (c) 2012-2013 Marek Lindner -+ * -+ * Permission to use, copy, modify, and/or distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ * -+ */ -+ -+#include -+#include -+ -+#include -+ -+#include "common.h" -+#include "dev-ap9x-pci.h" -+#include "dev-gpio-buttons.h" -+#include "dev-eth.h" -+#include "dev-leds-gpio.h" -+#include "dev-m25p80.h" -+#include "dev-wmac.h" -+#include "machtypes.h" -+#include "pci.h" -+ -+#define MR1750_GPIO_LED_LAN 12 -+#define MR1750_GPIO_LED_WLAN_2G 13 -+#define MR1750_GPIO_LED_STATUS_GREEN 19 -+#define MR1750_GPIO_LED_STATUS_RED 21 -+#define MR1750_GPIO_LED_POWER 22 -+#define MR1750_GPIO_LED_WLAN_5G 23 -+ -+#define MR1750_GPIO_BTN_RESET 17 -+ -+#define MR1750_KEYS_POLL_INTERVAL 20 /* msecs */ -+#define MR1750_KEYS_DEBOUNCE_INTERVAL (3 * MR1750_KEYS_POLL_INTERVAL) -+ -+#define MR1750_MAC0_OFFSET 0 -+#define MR1750_WMAC_CALDATA_OFFSET 0x1000 -+ -+static struct gpio_led mr1750_leds_gpio[] __initdata = { -+ { -+ .name = "mr1750:blue:power", -+ .gpio = MR1750_GPIO_LED_POWER, -+ .active_low = 1, -+ }, -+ { -+ .name = "mr1750:blue:wan", -+ .gpio = MR1750_GPIO_LED_LAN, -+ .active_low = 1, -+ }, -+ { -+ .name = "mr1750:blue:wlan24", -+ .gpio = MR1750_GPIO_LED_WLAN_2G, -+ .active_low = 1, -+ }, -+ { -+ .name = "mr1750:blue:wlan58", -+ .gpio = MR1750_GPIO_LED_WLAN_5G, -+ .active_low = 1, -+ }, -+ { -+ .name = "mr1750:green:status", -+ .gpio = MR1750_GPIO_LED_STATUS_GREEN, -+ .active_low = 1, -+ }, -+ { -+ .name = "mr1750:red:status", -+ .gpio = MR1750_GPIO_LED_STATUS_RED, -+ .active_low = 1, -+ }, -+}; -+ -+static struct gpio_keys_button mr1750_gpio_keys[] __initdata = { -+ { -+ .desc = "Reset button", -+ .type = EV_KEY, -+ .code = KEY_RESTART, -+ .debounce_interval = MR1750_KEYS_DEBOUNCE_INTERVAL, -+ .gpio = MR1750_GPIO_BTN_RESET, -+ .active_low = 1, -+ }, -+}; -+ -+static void __init mr1750_setup(void) -+{ -+ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -+ u8 mac[6]; -+ -+ ath79_eth0_pll_data.pll_1000 = 0xbe000101; -+ ath79_eth0_pll_data.pll_100 = 0x80000101; -+ ath79_eth0_pll_data.pll_10 = 0x80001313; -+ -+ ath79_register_m25p80(NULL); -+ -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(mr1750_leds_gpio), -+ mr1750_leds_gpio); -+ ath79_register_gpio_keys_polled(-1, MR1750_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(mr1750_gpio_keys), -+ mr1750_gpio_keys); -+ -+ ath79_init_mac(mac, art + MR1750_MAC0_OFFSET, 1); -+ ath79_register_wmac(art + MR1750_WMAC_CALDATA_OFFSET, mac); -+ ath79_register_pci(); -+ -+ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); -+ ath79_register_mdio(0, 0x0); -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, art + MR1750_MAC0_OFFSET, 0); -+ -+ /* GMAC0 is connected to the RMGII interface */ -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; -+ ath79_eth0_data.phy_mask = BIT(5); -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; -+ -+ ath79_register_eth(0); -+} -+ -+MIPS_MACHINE(ATH79_MACH_MR1750, "MR1750", "OpenMesh MR1750", mr1750_setup); -diff --git a/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-mr1750-support.patch b/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-mr1750-support.patch -new file mode 100644 -index 0000000..d802a12 ---- /dev/null -+++ b/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-mr1750-support.patch -@@ -0,0 +1,39 @@ -+--- a/arch/mips/ath79/Kconfig -++++ b/arch/mips/ath79/Kconfig -+@@ -763,6 +763,16 @@ config ATH79_MACH_CAP4200AG -+ select ATH79_DEV_M25P80 -+ select ATH79_DEV_WMAC -+ -++config ATH79_MACH_MR1750 -++ bool "OpenMesh MR1750 board support" -++ select SOC_QCA955X -++ select ATH79_DEV_AP9X_PCI if PCI -++ select ATH79_DEV_ETH -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO -++ select ATH79_DEV_M25P80 -++ select ATH79_DEV_WMAC -++ -+ config ATH79_MACH_MR900 -+ bool "OpenMesh MR900 board support" -+ select SOC_QCA955X -+--- a/arch/mips/ath79/Makefile -++++ b/arch/mips/ath79/Makefile -+@@ -80,6 +80,7 @@ obj-$(CONFIG_ATH79_MACH_HORNET_UB) += ma -+ obj-$(CONFIG_ATH79_MACH_MC_MAC1200R) += mach-mc-mac1200r.o -+ obj-$(CONFIG_ATH79_MACH_MR12) += mach-mr12.o -+ obj-$(CONFIG_ATH79_MACH_MR16) += mach-mr16.o -++obj-$(CONFIG_ATH79_MACH_MR1750) += mach-mr1750.o -+ obj-$(CONFIG_ATH79_MACH_MR600) += mach-mr600.o -+ obj-$(CONFIG_ATH79_MACH_MR900) += mach-mr900.o -+ obj-$(CONFIG_ATH79_MACH_MYNET_N600) += mach-mynet-n600.o -+--- a/arch/mips/ath79/machtypes.h -++++ b/arch/mips/ath79/machtypes.h -+@@ -69,6 +69,7 @@ enum ath79_mach_type { -+ ATH79_MACH_HORNET_UB, /* ALFA Networks Hornet-UB */ -+ ATH79_MACH_MR12, /* Cisco Meraki MR12 */ -+ ATH79_MACH_MR16, /* Cisco Meraki MR16 */ -++ ATH79_MACH_MR1750, /* OpenMesh MR1750 */ -+ ATH79_MACH_MR600V2, /* OpenMesh MR600v2 */ -+ ATH79_MACH_MR600, /* OpenMesh MR600 */ -+ ATH79_MACH_MR900, /* OpenMesh MR900 */ diff --git a/patches/openwrt/0048-ar71xx-add-user-space-support-for-the-OpenMesh-MR175.patch b/patches/openwrt/0048-ar71xx-add-user-space-support-for-the-OpenMesh-MR175.patch deleted file mode 100644 index 3e6363c7..00000000 --- a/patches/openwrt/0048-ar71xx-add-user-space-support-for-the-OpenMesh-MR175.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:01 +0000 -Subject: ar71xx: add user-space support for the OpenMesh MR1750 board - -Signed-off-by: Sven Eckelmann - -Backport of r46927 - -Forwarded: https://patchwork.ozlabs.org/patch/624174/ - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index 775aac6..44d2ddf 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -143,6 +143,9 @@ get_status_led() { - mr600v2) - status_led="mr600:blue:power" - ;; -+ mr1750) -+ status_led="mr1750:blue:power" -+ ;; - mr900 | \ - mr900v2) - status_led="mr900:blue:power" -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -index a4b355a..c451124 100644 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -@@ -239,6 +239,12 @@ mr600) - ucidef_set_led_wlan "wlan58" "WLAN58" "mr600:green:wlan58" "phy0tpt" - ;; - -+mr1750) -+ ucidef_set_led_netdev "lan" "LAN" "mr1750:blue:wan" "eth0" -+ ucidef_set_led_wlan "wlan58" "WLAN58" "mr1750:blue:wlan58" "phy0tpt" -+ ucidef_set_led_wlan "wlan24" "WLAN24" "mr1750:blue:wlan24" "phy1tpt" -+ ;; -+ - mr900 | \ - mr900v2) - ucidef_set_led_netdev "lan" "LAN" "mr900:blue:wan" "eth0" -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -index 0a23756..4066506 100755 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/02_network -@@ -334,6 +334,7 @@ eap300v2 |\ - eap7660d |\ - el-mini |\ - loco-m-xw |\ -+mr1750 |\ - mr600 |\ - mr600v2 |\ - mr900 |\ -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index 7fc951a..587d029 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -562,6 +562,9 @@ ar71xx_board_detect() { - *MR600v2) - name="mr600v2" - ;; -+ *MR1750) -+ name="mr1750" -+ ;; - *MR600) - name="mr600" - ;; diff --git a/patches/openwrt/0049-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-M.patch b/patches/openwrt/0049-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-M.patch deleted file mode 100644 index 66b0bc4f..00000000 --- a/patches/openwrt/0049-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-M.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:18 +0000 -Subject: scripts/om-fwupgradecfg-gen.sh: add support for the MR1750 - -Signed-off-by: Sven Eckelmann - -Backport of r46928 - -Forwarded: https://patchwork.ozlabs.org/patch/624175/ - -diff --git a/scripts/om-fwupgradecfg-gen.sh b/scripts/om-fwupgradecfg-gen.sh -index e132954..c790214 100644 ---- a/scripts/om-fwupgradecfg-gen.sh -+++ b/scripts/om-fwupgradecfg-gen.sh -@@ -7,7 +7,7 @@ - # - - usage() { -- echo "Usage: $0 " -+ echo "Usage: $0 " - rm -f $CFG_OUT - exit 1 - } -@@ -26,7 +26,7 @@ case $CE_TYPE in - FLASH_BS=262144 - MD5_SKIP_BLOCKS=1 - ;; -- OM5P|MR600|MR900) -+ OM5P|MR600|MR900|MR1750) - MAX_PART_SIZE=7808 - KERNEL_FLASH_ADDR=0xb0000 - FLASH_BS=65536 diff --git a/patches/openwrt/0050-ar71xx-enable-sysupgrade-for-the-OpenMesh-MR1750.patch b/patches/openwrt/0050-ar71xx-enable-sysupgrade-for-the-OpenMesh-MR1750.patch deleted file mode 100644 index dc595593..00000000 --- a/patches/openwrt/0050-ar71xx-enable-sysupgrade-for-the-OpenMesh-MR1750.patch +++ /dev/null @@ -1,55 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:24 +0000 -Subject: ar71xx: enable sysupgrade for the OpenMesh MR1750 - -Signed-off-by: Sven Eckelmann - -Backport of r46929 - -Forwarded: https://patchwork.ozlabs.org/patch/624176/ - -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -index 547116e..9ca0f5b 100644 ---- a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -@@ -72,6 +72,11 @@ platform_check_image_openmesh() - echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" - return 1 - ;; -+ MR1750) -+ [ "$board" = "mr1750" ] && break -+ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" -+ return 1 -+ ;; - MR600) - [ "$board" = "mr600" ] && break - [ "$board" = "mr600v2" ] && break -@@ -157,7 +162,7 @@ platform_do_upgrade_openmesh() - kernel_start_addr1=0x9f1c0000 - kernel_start_addr2=0x9f8c0000 - ;; -- OM5P|MR600|MR900) -+ OM5P|MR600|MR900|MR1750) - block_size=$((64 * 1024)) - total_size=7995392 - kernel_start_addr1=0x9f0b0000 -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index 0e9833d..ac060ea 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -296,6 +296,7 @@ platform_check_image() { - - return 0; - ;; -+ mr1750 | \ - mr600 | \ - mr600v2 | \ - mr900 | \ -@@ -528,6 +529,7 @@ platform_do_upgrade() { - tew-673gru) - platform_do_upgrade_dir825b "$ARGV" - ;; -+ mr1750 | \ - mr600 | \ - mr600v2 | \ - mr900 | \ diff --git a/patches/openwrt/0051-package-om-watchdog-add-OpenMesh-MR1750-support.patch b/patches/openwrt/0051-package-om-watchdog-add-OpenMesh-MR1750-support.patch deleted file mode 100644 index e16fb3ef..00000000 --- a/patches/openwrt/0051-package-om-watchdog-add-OpenMesh-MR1750-support.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:35 +0000 -Subject: package/om-watchdog: add OpenMesh MR1750 support - -Signed-off-by: Sven Eckelmann - -Backport of r46930 - -Forwarded: https://patchwork.ozlabs.org/patch/624177/ - -diff --git a/package/kernel/om-watchdog/files/om-watchdog.init b/package/kernel/om-watchdog/files/om-watchdog.init -index 135fef7..c792968 100644 ---- a/package/kernel/om-watchdog/files/om-watchdog.init -+++ b/package/kernel/om-watchdog/files/om-watchdog.init -@@ -25,7 +25,7 @@ boot() { - "mr600v2") - service_start /sbin/om-watchdog 15 - ;; -- "mr900"|"mr900v2") -+ "mr900"|"mr900v2"|"mr1750") - service_start /sbin/om-watchdog 16 - ;; - esac diff --git a/patches/openwrt/0052-package-uboot-envtools-add-OpenMesh-MR1750-support.patch b/patches/openwrt/0052-package-uboot-envtools-add-OpenMesh-MR1750-support.patch deleted file mode 100644 index 8e975a1c..00000000 --- a/patches/openwrt/0052-package-uboot-envtools-add-OpenMesh-MR1750-support.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:43 +0000 -Subject: package/uboot-envtools: add OpenMesh MR1750 support - -Signed-off-by: Sven Eckelmann - -Backport of r46931 - -Forwarded: https://patchwork.ozlabs.org/patch/624178/ - -diff --git a/package/boot/uboot-envtools/files/ar71xx b/package/boot/uboot-envtools/files/ar71xx -index ec8541c..ef00f17 100644 ---- a/package/boot/uboot-envtools/files/ar71xx -+++ b/package/boot/uboot-envtools/files/ar71xx -@@ -21,6 +21,7 @@ carambola2 | \ - eap300v2 | \ - hornet-ub | \ - hornet-ub-x2 | \ -+mr1750 | \ - mr600 | \ - mr600v2 | \ - mr900 | \ diff --git a/patches/openwrt/0053-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch b/patches/openwrt/0053-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch deleted file mode 100644 index 2a166e16..00000000 --- a/patches/openwrt/0053-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch +++ /dev/null @@ -1,57 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:11:51 +0000 -Subject: ar71xx: create profile and build image for the OpenMesh MR1750 board - -Signed-off-by: Sven Eckelmann - -Backport of r46932 - -Forwarded: https://patchwork.ozlabs.org/patch/624179/ - -diff --git a/target/linux/ar71xx/generic/profiles/openmesh.mk b/target/linux/ar71xx/generic/profiles/openmesh.mk -index 41b462e..06cf135 100644 ---- a/target/linux/ar71xx/generic/profiles/openmesh.mk -+++ b/target/linux/ar71xx/generic/profiles/openmesh.mk -@@ -49,9 +49,20 @@ endef - - $(eval $(call Profile,MR900)) - -+define Profile/MR1750 -+ NAME:=OpenMesh MR1750 -+ PACKAGES:=kmod-ath9k kmod-ath10k ath10k-firmware-qca988x -+endef -+ -+define Profile/MR1750/Description -+ Package set optimized for the OpenMesh MR1750. -+endef -+ -+$(eval $(call Profile,MR1750)) -+ - define Profile/OPENMESH - NAME:=OpenMesh products -- PACKAGES:=kmod-ath9k om-watchdog -+ PACKAGES:=kmod-ath9k kmod-ath10k om-watchdog - endef - - define Profile/OPENMESH/Description -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index f91e20e..b74aa45 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -2045,6 +2045,7 @@ $(eval $(call SingleProfile,OpenMesh,squashfs-only,OM2P,om2p,,,,OM2P)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,OM5P,om5p,,,,OM5P)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,MR600,mr600,,,,MR600)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,MR900,mr900,,,,MR900)) -+$(eval $(call SingleProfile,OpenMesh,squashfs-only,MR1750,mr1750,,,,MR1750)) - - $(eval $(call SingleProfile,PB4X,128k,ALL0305,all0305,ALL0305,ttyS0,115200)) - $(eval $(call SingleProfile,PB4X,128k,EAP7660D,eap7660d,EAP7660D,ttyS0,115200)) -@@ -2138,7 +2139,7 @@ $(eval $(call MultiProfile,AP121,AP121_2M AP121_4M)) - $(eval $(call MultiProfile,DIR615IX,DIR615I1 DIR615I3)) - $(eval $(call MultiProfile,AP136,AP136_010 AP136_020)) - $(eval $(call MultiProfile,EWDORIN, EWDORINAP EWDORINRT EWDORIN16M)) --$(eval $(call MultiProfile,OPENMESH,OM2P OM5P MR600 MR900)) -+$(eval $(call MultiProfile,OPENMESH,OM2P OM5P MR600 MR900 MR1750)) - $(eval $(call MultiProfile,TEW652BRP,TEW652BRP_FW TEW652BRP_RECOVERY)) - $(eval $(call MultiProfile,TLMR3220,TLMR3220V1)) - $(eval $(call MultiProfile,TLMR3420,TLMR3420V1)) diff --git a/patches/openwrt/0054-ar71xx-Extend-the-list-of-bits-in-QCA955X_GMAC_REG_E.patch b/patches/openwrt/0054-ar71xx-Extend-the-list-of-bits-in-QCA955X_GMAC_REG_E.patch deleted file mode 100644 index efe4b609..00000000 --- a/patches/openwrt/0054-ar71xx-Extend-the-list-of-bits-in-QCA955X_GMAC_REG_E.patch +++ /dev/null @@ -1,47 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 16 Mar 2016 09:27:01 +0000 -Subject: ar71xx: Extend the list of bits in QCA955X_GMAC_REG_ETH_CFG - -Signed-off-by: Sven Eckelmann - -Backport of r49027 - -Forwarded: https://patchwork.ozlabs.org/patch/624180/ - -diff --git a/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch b/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -index 8bf7658..797977f 100644 ---- a/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -+++ b/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -@@ -207,7 +207,7 @@ - #define AR934X_GPIO_REG_FUNC 0x6c - - #define AR71XX_GPIO_COUNT 16 --@@ -560,4 +663,153 @@ -+@@ -560,4 +663,170 @@ - #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 - #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 - -@@ -358,6 +358,23 @@ - +#define QCA955X_GMAC_REG_ETH_CFG 0x00 - + - +#define QCA955X_ETH_CFG_RGMII_EN BIT(0) -++#define QCA955X_ETH_CFG_MII_GE0 BIT(1) -++#define QCA955X_ETH_CFG_GMII_GE0 BIT(2) -++#define QCA955X_ETH_CFG_MII_GE0_MASTER BIT(3) -++#define QCA955X_ETH_CFG_MII_GE0_SLAVE BIT(4) -++#define QCA955X_ETH_CFG_GE0_ERR_EN BIT(5) - +#define QCA955X_ETH_CFG_GE0_SGMII BIT(6) -++#define QCA955X_ETH_CFG_RMII_GE0 BIT(10) -++#define QCA955X_ETH_CFG_MII_CNTL_SPEED BIT(11) -++#define QCA955X_ETH_CFG_RMII_GE0_MASTER BIT(12) -++#define QCA955X_ETH_CFG_RXD_DELAY_MASK 0x3 -++#define QCA955X_ETH_CFG_RXD_DELAY_SHIFT 14 -++#define QCA955X_ETH_CFG_RDV_DELAY BIT(16) -++#define QCA955X_ETH_CFG_RDV_DELAY_MASK 0x3 -++#define QCA955X_ETH_CFG_RDV_DELAY_SHIFT 16 -++#define QCA955X_ETH_CFG_TXD_DELAY_MASK 0x3 -++#define QCA955X_ETH_CFG_TXD_DELAY_SHIFT 18 -++#define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3 -++#define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20 - + - #endif /* __ASM_MACH_AR71XX_REGS_H */ diff --git a/patches/openwrt/0055-ar71xx-Use-_eth_cfg-helper-for-Open-Mesh-MR900-board.patch b/patches/openwrt/0055-ar71xx-Use-_eth_cfg-helper-for-Open-Mesh-MR900-board.patch deleted file mode 100644 index 43a876d2..00000000 --- a/patches/openwrt/0055-ar71xx-Use-_eth_cfg-helper-for-Open-Mesh-MR900-board.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Sven Eckelmann -Date: Tue, 7 Jul 2015 13:47:39 +0000 -Subject: ar71xx: Use *_eth_cfg helper for Open Mesh MR900 boards - -Signed-off-by: Sven Eckelmann - -Backport of r46241 - -Forwarded: https://patchwork.ozlabs.org/patch/624181/ - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -index fe3e1fa..9c3164d 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -@@ -94,24 +94,6 @@ static struct gpio_keys_button mr900_gpio_keys[] __initdata = { - }, - }; - -- --static void __init mr900_gmac_setup(void) --{ -- void __iomem *base; -- u32 t; -- -- base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); -- -- t = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG); -- -- t &= ~(QCA955X_ETH_CFG_RGMII_EN | QCA955X_ETH_CFG_GE0_SGMII); -- t |= QCA955X_ETH_CFG_RGMII_EN; -- -- __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); -- -- iounmap(base); --} -- - static void __init mr900_setup(void) - { - u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -@@ -141,8 +123,7 @@ static void __init mr900_setup(void) - } - pdata->use_eeprom = true; - -- mr900_gmac_setup(); -- -+ ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); - ath79_register_mdio(0, 0x0); - - ath79_init_mac(ath79_eth0_data.mac_addr, art + MR900_MAC0_OFFSET, 0); diff --git a/patches/openwrt/0056-ar71xx-Allow-to-use-ath79_gpio_output_select-on-QCA9.patch b/patches/openwrt/0056-ar71xx-Allow-to-use-ath79_gpio_output_select-on-QCA9.patch deleted file mode 100644 index 137aa9d4..00000000 --- a/patches/openwrt/0056-ar71xx-Allow-to-use-ath79_gpio_output_select-on-QCA9.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: Sven Eckelmann -Date: Fri, 24 Jul 2015 09:10:00 +0000 -Subject: ar71xx: Allow to use ath79_gpio_output_select on QCA955x - -Signed-off-by: Sven Eckelmann - -Backport of r46459 - -Forwarded: https://patchwork.ozlabs.org/patch/624182/ - -diff --git a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -new file mode 100644 -index 0000000..e71b6e2 ---- /dev/null -+++ b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -@@ -0,0 +1,63 @@ -+--- a/arch/mips/ath79/gpio.c -++++ b/arch/mips/ath79/gpio.c -+@@ -187,15 +187,30 @@ void __init ath79_gpio_output_select(uns -+ { -+ void __iomem *base = ath79_gpio_base; -+ unsigned long flags; -+- unsigned int reg; -++ unsigned int reg, reg_base; -++ unsigned long gpio_count; -+ u32 t, s; -+ -+- BUG_ON(!soc_is_ar934x() && !soc_is_qca953x() && !soc_is_qca956x()); -++ if (soc_is_ar934x()) { -++ gpio_count = AR934X_GPIO_COUNT; -++ reg_base = AR934X_GPIO_REG_OUT_FUNC0; -++ } else if (soc_is_qca953x()) { -++ gpio_count = QCA953X_GPIO_COUNT; -++ reg_base = QCA953X_GPIO_REG_OUT_FUNC0; -++ } else if (soc_is_qca955x()) { -++ gpio_count = QCA955X_GPIO_COUNT; -++ reg_base = QCA955X_GPIO_REG_OUT_FUNC0; -++ } else if (soc_is_qca956x()) { -++ gpio_count = QCA956X_GPIO_COUNT; -++ reg_base = QCA956X_GPIO_REG_OUT_FUNC0; -++ } else { -++ BUG(); -++ } -+ -+- if (gpio >= AR934X_GPIO_COUNT) -++ if (gpio >= gpio_count) -+ return; -+ -+- reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); -++ reg = reg_base + 4 * (gpio / 4); -+ s = 8 * (gpio % 4); -+ -+ spin_lock_irqsave(&ath79_gpio_lock, flags); -+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h -+@@ -875,6 +875,14 @@ -+ #define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 -+ #define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 -+ -++#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c -++#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 -++#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 -++#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 -++#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c -++#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 -++#define QCA955X_GPIO_REG_FUNC 0x6c -++ -+ #define QCA956X_GPIO_REG_OUT_FUNC0 0x2c -+ #define QCA956X_GPIO_REG_OUT_FUNC1 0x30 -+ #define QCA956X_GPIO_REG_OUT_FUNC2 0x34 -+@@ -1014,6 +1022,8 @@ -+ #define AR934X_GPIO_OUT_EXT_LNA0 46 -+ #define AR934X_GPIO_OUT_EXT_LNA1 47 -+ -++#define QCA955X_GPIO_OUT_GPIO 0 -++ -+ /* -+ * MII_CTRL block -+ */ diff --git a/patches/openwrt/0057-ar71xx-Add-support-for-ath79_gpio_function_-on-QCA95.patch b/patches/openwrt/0057-ar71xx-Add-support-for-ath79_gpio_function_-on-QCA95.patch deleted file mode 100644 index 23b42cb6..00000000 --- a/patches/openwrt/0057-ar71xx-Add-support-for-ath79_gpio_function_-on-QCA95.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 23 Mar 2016 12:52:27 +0000 -Subject: ar71xx: Add support for ath79_gpio_function_* on QCA955X - -Signed-off-by: Sven Eckelmann - -Backport of r49074 - -Forwarded: https://patchwork.ozlabs.org/patch/624183/ - -diff --git a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -index e71b6e2..0e87357 100644 ---- a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -+++ b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -@@ -1,6 +1,16 @@ - --- a/arch/mips/ath79/gpio.c - +++ b/arch/mips/ath79/gpio.c --@@ -187,15 +187,30 @@ void __init ath79_gpio_output_select(uns -+@@ -146,7 +146,8 @@ static void __iomem *ath79_gpio_get_func -+ if (soc_is_ar71xx() || -+ soc_is_ar724x() || -+ soc_is_ar913x() || -+- soc_is_ar933x()) -++ soc_is_ar933x() || -++ soc_is_qca955x()) -+ reg = AR71XX_GPIO_REG_FUNC; -+ else if (soc_is_ar934x() || -+ soc_is_qca953x() || -+@@ -187,15 +188,30 @@ void __init ath79_gpio_output_select(uns - { - void __iomem *base = ath79_gpio_base; - unsigned long flags; diff --git a/patches/openwrt/0058-ar71xx-Add-QCA955X-GPIO-mux-and-function-definitions.patch b/patches/openwrt/0058-ar71xx-Add-QCA955X-GPIO-mux-and-function-definitions.patch deleted file mode 100644 index ee3c3674..00000000 --- a/patches/openwrt/0058-ar71xx-Add-QCA955X-GPIO-mux-and-function-definitions.patch +++ /dev/null @@ -1,159 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 23 Mar 2016 12:52:31 +0000 -Subject: ar71xx: Add QCA955X GPIO mux and function definitions - -Signed-off-by: Sven Eckelmann - -Backport of r49075 - -Forwarded: https://patchwork.ozlabs.org/patch/624184/ - -diff --git a/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch b/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -index 797977f..0126f6a 100644 ---- a/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -+++ b/target/linux/ar71xx/patches-3.18/601-MIPS-ath79-add-more-register-defines.patch -@@ -194,7 +194,7 @@ - #define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0) - - #define AR934X_BOOTSTRAP_SW_OPTION8 BIT(23) --@@ -529,6 +626,12 @@ -+@@ -529,8 +626,22 @@ - #define AR71XX_GPIO_REG_INT_ENABLE 0x24 - #define AR71XX_GPIO_REG_FUNC 0x28 - -@@ -206,8 +206,18 @@ - +#define AR934X_GPIO_REG_OUT_FUNC5 0x40 - #define AR934X_GPIO_REG_FUNC 0x6c - -++#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c -++#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 -++#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 -++#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 -++#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c -++#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 -++#define QCA955X_GPIO_REG_FUNC 0x6c -++ - #define AR71XX_GPIO_COUNT 16 --@@ -560,4 +663,170 @@ -+ #define AR7240_GPIO_COUNT 18 -+ #define AR7241_GPIO_COUNT 20 -+@@ -560,4 +671,235 @@ - #define AR934X_SRIF_DPLL2_OUTDIV_SHIFT 13 - #define AR934X_SRIF_DPLL2_OUTDIV_MASK 0x7 - -@@ -288,6 +298,71 @@ - +#define AR934X_GPIO_OUT_EXT_LNA0 46 - +#define AR934X_GPIO_OUT_EXT_LNA1 47 - + -++#define QCA955X_GPIO_FUNC_CLK_OBS7_EN BIT(9) -++#define QCA955X_GPIO_FUNC_CLK_OBS6_EN BIT(8) -++#define QCA955X_GPIO_FUNC_CLK_OBS5_EN BIT(7) -++#define QCA955X_GPIO_FUNC_CLK_OBS4_EN BIT(6) -++#define QCA955X_GPIO_FUNC_CLK_OBS3_EN BIT(5) -++#define QCA955X_GPIO_FUNC_CLK_OBS2_EN BIT(4) -++#define QCA955X_GPIO_FUNC_CLK_OBS1_EN BIT(3) -++#define QCA955X_GPIO_FUNC_JTAG_DISABLE BIT(1) -++ -++#define QCA955X_GPIO_OUT_GPIO 0 -++#define QCA955X_MII_EXT_MDI 1 -++#define QCA955X_SLIC_DATA_OUT 3 -++#define QCA955X_SLIC_PCM_FS 4 -++#define QCA955X_SLIC_PCM_CLK 5 -++#define QCA955X_SPI_CLK 8 -++#define QCA955X_SPI_CS_0 9 -++#define QCA955X_SPI_CS_1 10 -++#define QCA955X_SPI_CS_2 11 -++#define QCA955X_SPI_MISO 12 -++#define QCA955X_I2S_CLK 13 -++#define QCA955X_I2S_WS 14 -++#define QCA955X_I2S_SD 15 -++#define QCA955X_I2S_MCK 16 -++#define QCA955X_SPDIF_OUT 17 -++#define QCA955X_UART1_TD 18 -++#define QCA955X_UART1_RTS 19 -++#define QCA955X_UART1_RD 20 -++#define QCA955X_UART1_CTS 21 -++#define QCA955X_UART0_SOUT 22 -++#define QCA955X_SPDIF2_OUT 23 -++#define QCA955X_LED_SGMII_SPEED0 24 -++#define QCA955X_LED_SGMII_SPEED1 25 -++#define QCA955X_LED_SGMII_DUPLEX 26 -++#define QCA955X_LED_SGMII_LINK_UP 27 -++#define QCA955X_SGMII_SPEED0_INVERT 28 -++#define QCA955X_SGMII_SPEED1_INVERT 29 -++#define QCA955X_SGMII_DUPLEX_INVERT 30 -++#define QCA955X_SGMII_LINK_UP_INVERT 31 -++#define QCA955X_GE1_MII_MDO 32 -++#define QCA955X_GE1_MII_MDC 33 -++#define QCA955X_SWCOM2 38 -++#define QCA955X_SWCOM3 39 -++#define QCA955X_MAC2_GPIO 40 -++#define QCA955X_MAC3_GPIO 41 -++#define QCA955X_ATT_LED 42 -++#define QCA955X_PWR_LED 43 -++#define QCA955X_TX_FRAME 44 -++#define QCA955X_RX_CLEAR_EXTERNAL 45 -++#define QCA955X_LED_NETWORK_EN 46 -++#define QCA955X_LED_POWER_EN 47 -++#define QCA955X_WMAC_GLUE_WOW 68 -++#define QCA955X_RX_CLEAR_EXTENSION 70 -++#define QCA955X_CP_NAND_CS1 73 -++#define QCA955X_USB_SUSPEND 74 -++#define QCA955X_ETH_TX_ERR 75 -++#define QCA955X_DDR_DQ_OE 76 -++#define QCA955X_CLKREQ_N_EP 77 -++#define QCA955X_CLKREQ_N_RC 78 -++#define QCA955X_CLK_OBS0 79 -++#define QCA955X_CLK_OBS1 80 -++#define QCA955X_CLK_OBS2 81 -++#define QCA955X_CLK_OBS3 82 -++#define QCA955X_CLK_OBS4 83 -++#define QCA955X_CLK_OBS5 84 -++ - +/* - + * MII_CTRL block - + */ -diff --git a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -index 0e87357..8a54859 100644 ---- a/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -+++ b/target/linux/ar71xx/patches-3.18/739-MIPS-ath79-add-gpio-func-register-for-QCA955x-SoC.patch -@@ -37,37 +37,12 @@ - + } - - - if (gpio >= AR934X_GPIO_COUNT) -+- return; - + if (gpio >= gpio_count) -- return; -++ return; - - - reg = AR934X_GPIO_REG_OUT_FUNC0 + 4 * (gpio / 4); - + reg = reg_base + 4 * (gpio / 4); - s = 8 * (gpio % 4); - - spin_lock_irqsave(&ath79_gpio_lock, flags); ----- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h --+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h --@@ -875,6 +875,14 @@ -- #define QCA953X_GPIO_OUT_MUX_LED_LINK4 44 -- #define QCA953X_GPIO_OUT_MUX_LED_LINK5 45 -- --+#define QCA955X_GPIO_REG_OUT_FUNC0 0x2c --+#define QCA955X_GPIO_REG_OUT_FUNC1 0x30 --+#define QCA955X_GPIO_REG_OUT_FUNC2 0x34 --+#define QCA955X_GPIO_REG_OUT_FUNC3 0x38 --+#define QCA955X_GPIO_REG_OUT_FUNC4 0x3c --+#define QCA955X_GPIO_REG_OUT_FUNC5 0x40 --+#define QCA955X_GPIO_REG_FUNC 0x6c --+ -- #define QCA956X_GPIO_REG_OUT_FUNC0 0x2c -- #define QCA956X_GPIO_REG_OUT_FUNC1 0x30 -- #define QCA956X_GPIO_REG_OUT_FUNC2 0x34 --@@ -1014,6 +1022,8 @@ -- #define AR934X_GPIO_OUT_EXT_LNA0 46 -- #define AR934X_GPIO_OUT_EXT_LNA1 47 -- --+#define QCA955X_GPIO_OUT_GPIO 0 --+ -- /* -- * MII_CTRL block -- */ diff --git a/patches/openwrt/0059-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR900.patch b/patches/openwrt/0059-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR900.patch deleted file mode 100644 index 6a32c80b..00000000 --- a/patches/openwrt/0059-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR900.patch +++ /dev/null @@ -1,78 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 16 Mar 2016 09:27:11 +0000 -Subject: ar71xx: Use PHY fixups for Open Mesh MR900 - -The delays of PHY/MAC on the MR900 are done by u-boot and OpenWrt in -different ways. u-boot only modifies the ETH_CFG of the QCA955x based on -the link speed. But OpenWrt can only modify the PHY delays based on the -link speed. - -This can lead to communication problems when u-boot initializes the ETH_CFG -for a specific link speed (e.g. 10BASE-T) but then OpenWrt the sets the PHY -delays to an incompatible value. - -Instead reset the ETH_CFG delay bits of the QCA955x to a specific value and -only rely on the AT803x PHY settings. - -Signed-off-by: Sven Eckelmann - -Backport of r49030 - -Forwarded: https://patchwork.ozlabs.org/patch/624185/ - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -index 9c3164d..3634bf0 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -@@ -23,6 +23,7 @@ - #include - - #include -+#include - - #include "common.h" - #include "dev-ap9x-pci.h" -@@ -94,15 +95,30 @@ static struct gpio_keys_button mr900_gpio_keys[] __initdata = { - }, - }; - -+static struct at803x_platform_data mr900_at803x_data = { -+ .disable_smarteee = 1, -+ .enable_rgmii_rx_delay = 1, -+ .enable_rgmii_tx_delay = 0, -+ .fixup_rgmii_tx_delay = 1, -+}; -+ -+static struct mdio_board_info mr900_mdio0_info[] = { -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 5, -+ .platform_data = &mr900_at803x_data, -+ }, -+}; -+ - static void __init mr900_setup(void) - { - u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); - u8 mac[6], pcie_mac[6]; - struct ath9k_platform_data *pdata; - -- ath79_eth0_pll_data.pll_1000 = 0xbe000101; -- ath79_eth0_pll_data.pll_100 = 0x80000101; -- ath79_eth0_pll_data.pll_10 = 0x80001313; -+ ath79_eth0_pll_data.pll_1000 = 0xae000000; -+ ath79_eth0_pll_data.pll_100 = 0xa0000101; -+ ath79_eth0_pll_data.pll_10 = 0xa0001313; - - ath79_register_m25p80(NULL); - -@@ -126,6 +142,9 @@ static void __init mr900_setup(void) - ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); - ath79_register_mdio(0, 0x0); - -+ mdiobus_register_board_info(mr900_mdio0_info, -+ ARRAY_SIZE(mr900_mdio0_info)); -+ - ath79_init_mac(ath79_eth0_data.mac_addr, art + MR900_MAC0_OFFSET, 0); - - /* GMAC0 is connected to the RMGII interface */ diff --git a/patches/openwrt/0060-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR1750.patch b/patches/openwrt/0060-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR1750.patch deleted file mode 100644 index 50ff879c..00000000 --- a/patches/openwrt/0060-ar71xx-Use-PHY-fixups-for-Open-Mesh-MR1750.patch +++ /dev/null @@ -1,77 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 16 Mar 2016 09:27:14 +0000 -Subject: ar71xx: Use PHY fixups for Open Mesh MR1750 - -The delays of PHY/MAC on the MR1750 are done by u-boot and OpenWrt in -different ways. u-boot only modifies the ETH_CFG of the QCA955x based on -the link speed. But OpenWrt can only modify the PHY delays based on the -link speed. - -This can lead to communication problems when u-boot initializes the ETH_CFG -for a specific link speed (e.g. 10BASE-T) but then OpenWrt the sets the PHY -delays to an incompatible value. - -Instead reset the ETH_CFG delay bits of the QCA955x to a specific value and -only rely on the AT803x PHY settings. - -Signed-off-by: Sven Eckelmann - -Backport of r49031 - -Forwarded: https://patchwork.ozlabs.org/patch/624186/ - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -index 8ace02f..f9e45bd 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -@@ -22,6 +22,7 @@ - #include - - #include -+#include - - #include "common.h" - #include "dev-ap9x-pci.h" -@@ -92,14 +93,29 @@ static struct gpio_keys_button mr1750_gpio_keys[] __initdata = { - }, - }; - -+static struct at803x_platform_data mr1750_at803x_data = { -+ .disable_smarteee = 1, -+ .enable_rgmii_rx_delay = 1, -+ .enable_rgmii_tx_delay = 0, -+ .fixup_rgmii_tx_delay = 1, -+}; -+ -+static struct mdio_board_info mr1750_mdio0_info[] = { -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 5, -+ .platform_data = &mr1750_at803x_data, -+ }, -+}; -+ - static void __init mr1750_setup(void) - { - u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); - u8 mac[6]; - -- ath79_eth0_pll_data.pll_1000 = 0xbe000101; -- ath79_eth0_pll_data.pll_100 = 0x80000101; -- ath79_eth0_pll_data.pll_10 = 0x80001313; -+ ath79_eth0_pll_data.pll_1000 = 0xae000000; -+ ath79_eth0_pll_data.pll_100 = 0xa0000101; -+ ath79_eth0_pll_data.pll_10 = 0xa0001313; - - ath79_register_m25p80(NULL); - -@@ -116,6 +132,9 @@ static void __init mr1750_setup(void) - ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); - ath79_register_mdio(0, 0x0); - -+ mdiobus_register_board_info(mr1750_mdio0_info, -+ ARRAY_SIZE(mr1750_mdio0_info)); -+ - ath79_init_mac(ath79_eth0_data.mac_addr, art + MR1750_MAC0_OFFSET, 0); - - /* GMAC0 is connected to the RMGII interface */ diff --git a/patches/openwrt/0061-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch b/patches/openwrt/0061-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch deleted file mode 100644 index 3567a32f..00000000 --- a/patches/openwrt/0061-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 23 Mar 2016 12:52:09 +0000 -Subject: ar71xx: Use private version of ath79_setup_qca955x_eth_cfg for MR900 - -The MR900 must unset some bits in ETH_CFG which were set by u-boot to work -correctly under OpenWrt. But the global function -ath79_setup_qca955x_eth_cfg will not unset all of them to increase the -backward compatiblity with older mach-* files. A private (simplified) -version for MR900 can be used instead. - -Signed-off-by: Sven Eckelmann - -Backport of r49069 - -Forwarded: https://patchwork.ozlabs.org/patch/624187/ - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -index 3634bf0..b439f58 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr900.c -@@ -110,6 +110,28 @@ static struct mdio_board_info mr900_mdio0_info[] = { - }, - }; - -+static void __init mr900_setup_qca955x_eth_cfg(u32 mask, -+ unsigned int rxd, -+ unsigned int rxdv, -+ unsigned int txd, -+ unsigned int txe) -+{ -+ void __iomem *base; -+ u32 t; -+ -+ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); -+ -+ t = mask; -+ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; -+ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; -+ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; -+ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; -+ -+ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); -+ -+ iounmap(base); -+} -+ - static void __init mr900_setup(void) - { - u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -@@ -139,7 +161,7 @@ static void __init mr900_setup(void) - } - pdata->use_eeprom = true; - -- ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); -+ mr900_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); - ath79_register_mdio(0, 0x0); - - mdiobus_register_board_info(mr900_mdio0_info, diff --git a/patches/openwrt/0062-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch b/patches/openwrt/0062-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch deleted file mode 100644 index 8ea16499..00000000 --- a/patches/openwrt/0062-ar71xx-Use-private-version-of-ath79_setup_qca955x_et.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Sven Eckelmann -Date: Wed, 23 Mar 2016 12:52:12 +0000 -Subject: ar71xx: Use private version of ath79_setup_qca955x_eth_cfg for MR1750 - -The MR1750 must unset some bits in ETH_CFG which were set by u-boot to work -correctly under OpenWrt. But the global function -ath79_setup_qca955x_eth_cfg will not unset all of them to increase the -backward compatiblity with older mach-* files. A private (simplified) -version for MR1750 can be used instead. - -Signed-off-by: Sven Eckelmann - -Backport of r49070 - -Forwarded: https://patchwork.ozlabs.org/patch/624188/ - -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -index f9e45bd..e3c04e7 100644 ---- a/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-mr1750.c -@@ -108,6 +108,28 @@ static struct mdio_board_info mr1750_mdio0_info[] = { - }, - }; - -+static void __init mr1750_setup_qca955x_eth_cfg(u32 mask, -+ unsigned int rxd, -+ unsigned int rxdv, -+ unsigned int txd, -+ unsigned int txe) -+{ -+ void __iomem *base; -+ u32 t; -+ -+ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); -+ -+ t = mask; -+ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; -+ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; -+ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; -+ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; -+ -+ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); -+ -+ iounmap(base); -+} -+ - static void __init mr1750_setup(void) - { - u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -@@ -129,7 +151,7 @@ static void __init mr1750_setup(void) - ath79_register_wmac(art + MR1750_WMAC_CALDATA_OFFSET, mac); - ath79_register_pci(); - -- ath79_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN); -+ mr1750_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); - ath79_register_mdio(0, 0x0); - - mdiobus_register_board_info(mr1750_mdio0_info, diff --git a/patches/openwrt/0063-scripts-om-fwupgradecfg-gen.sh-Fix-u-boot-image-md5s.patch b/patches/openwrt/0063-scripts-om-fwupgradecfg-gen.sh-Fix-u-boot-image-md5s.patch deleted file mode 100644 index 30658cdb..00000000 --- a/patches/openwrt/0063-scripts-om-fwupgradecfg-gen.sh-Fix-u-boot-image-md5s.patch +++ /dev/null @@ -1,43 +0,0 @@ -From: Sven Eckelmann -Date: Mon, 14 Sep 2015 20:10:10 +0000 -Subject: scripts/om-fwupgradecfg-gen.sh: Fix u-boot image md5sum check - -The u-boot on Open Mesh devices checks the whole transfered image against a -md5sum. This is stored inside the option filemd5sum inside the -fwupgrade.cfg. The bootloader will not check it when this setting is -missing and could therefore write invalid images to the flash. - -Signed-off-by: Sven Eckelmann - -Backport of r46925 - -Forwarded: https://patchwork.ozlabs.org/patch/624189/ - -diff --git a/scripts/om-fwupgradecfg-gen.sh b/scripts/om-fwupgradecfg-gen.sh -index c790214..fab1582 100644 ---- a/scripts/om-fwupgradecfg-gen.sh -+++ b/scripts/om-fwupgradecfg-gen.sh -@@ -48,6 +48,7 @@ ROOTFS_FLASH_ADDR=$(addr=$(($KERNEL_FLASH_ADDR + ($KERNEL_PART_SIZE * 1024))); p - ROOTFS_SIZE=$(stat -c%s "$ROOTFS_PATH") - ROOTFS_CHECK_BLOCKS=$((($ROOTFS_SIZE / $CHECK_BS) - $MD5_SKIP_BLOCKS)) - ROOTFS_MD5=$(md5=$(dd if=$ROOTFS_PATH bs=$CHECK_BS count=$ROOTFS_CHECK_BLOCKS 2>&- | md5sum); echo ${md5%% *}) -+ROOTFS_MD5_FULL=$(md5=$(md5sum $ROOTFS_PATH); echo ${md5%% *}) - ROOTFS_CHECK_SIZE=$(printf '0x%x' $(($ROOTFS_CHECK_BLOCKS * $CHECK_BS))) - ROOTFS_PART_SIZE=$(($MAX_PART_SIZE - $KERNEL_PART_SIZE)) - -@@ -55,6 +56,7 @@ cat << EOF > $CFG_OUT - [vmlinux] - filename=kernel - md5sum=$KERNEL_MD5 -+filemd5sum=$KERNEL_MD5 - flashaddr=$KERNEL_FLASH_ADDR - checksize=0x0 - cmd_success=setenv bootseq 1,2; setenv kernel_size_1 $KERNEL_PART_SIZE; saveenv -@@ -63,6 +65,7 @@ cmd_fail=reset - [rootfs] - filename=rootfs - md5sum=$ROOTFS_MD5 -+filemd5sum=$ROOTFS_MD5_FULL - flashaddr=$ROOTFS_FLASH_ADDR - checksize=$ROOTFS_CHECK_SIZE - cmd_success=setenv bootseq 1,2; setenv kernel_size_1 $KERNEL_PART_SIZE; setenv rootfs_size_1 $ROOTFS_PART_SIZE; saveenv diff --git a/patches/openwrt/0064-scripts-om-fwupgradecfg-gen.sh-Generate-sha256sum-fo.patch b/patches/openwrt/0064-scripts-om-fwupgradecfg-gen.sh-Generate-sha256sum-fo.patch deleted file mode 100644 index 01bb37b5..00000000 --- a/patches/openwrt/0064-scripts-om-fwupgradecfg-gen.sh-Generate-sha256sum-fo.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:25:42 +0000 -Subject: scripts/om-fwupgradecfg-gen.sh: Generate sha256sum for uboot verification - -Future Open Mesh u-boot versions are changing the check of the image files -(vmlinux, rootfs) from md5 to sha256. Having both in them should be enough -to ensure backward and forward compatibility. - -Signed-off-by: Sven Eckelmann - -Backport of r49140 - -Forwarded: https://patchwork.ozlabs.org/patch/624190/ - -diff --git a/scripts/om-fwupgradecfg-gen.sh b/scripts/om-fwupgradecfg-gen.sh -index fab1582..e208e6d 100644 ---- a/scripts/om-fwupgradecfg-gen.sh -+++ b/scripts/om-fwupgradecfg-gen.sh -@@ -42,6 +42,7 @@ CHECK_BS=65536 - - KERNEL_SIZE=$(stat -c%s "$KERNEL_PATH") - KERNEL_MD5=$(md5=$(md5sum $KERNEL_PATH); echo ${md5%% *}) -+KERNEL_SHA256=$(openssl dgst -sha256 $KERNEL_PATH | awk '{print $2}') - KERNEL_PART_SIZE=$(size=$(($KERNEL_SIZE / $FLASH_BS)); [ $(($size * $FLASH_BS)) -lt $KERNEL_SIZE ] && size=$(($size + 1)); echo $(($size * $FLASH_BS / 1024))) - - ROOTFS_FLASH_ADDR=$(addr=$(($KERNEL_FLASH_ADDR + ($KERNEL_PART_SIZE * 1024))); printf "0x%x" $addr) -@@ -49,6 +50,7 @@ ROOTFS_SIZE=$(stat -c%s "$ROOTFS_PATH") - ROOTFS_CHECK_BLOCKS=$((($ROOTFS_SIZE / $CHECK_BS) - $MD5_SKIP_BLOCKS)) - ROOTFS_MD5=$(md5=$(dd if=$ROOTFS_PATH bs=$CHECK_BS count=$ROOTFS_CHECK_BLOCKS 2>&- | md5sum); echo ${md5%% *}) - ROOTFS_MD5_FULL=$(md5=$(md5sum $ROOTFS_PATH); echo ${md5%% *}) -+ROOTFS_SHA256_FULL=$(openssl dgst -sha256 $ROOTFS_PATH | awk '{print $2}') - ROOTFS_CHECK_SIZE=$(printf '0x%x' $(($ROOTFS_CHECK_BLOCKS * $CHECK_BS))) - ROOTFS_PART_SIZE=$(($MAX_PART_SIZE - $KERNEL_PART_SIZE)) - -@@ -57,6 +59,7 @@ cat << EOF > $CFG_OUT - filename=kernel - md5sum=$KERNEL_MD5 - filemd5sum=$KERNEL_MD5 -+filesha256sum=$KERNEL_SHA256 - flashaddr=$KERNEL_FLASH_ADDR - checksize=0x0 - cmd_success=setenv bootseq 1,2; setenv kernel_size_1 $KERNEL_PART_SIZE; saveenv -@@ -66,6 +69,7 @@ cmd_fail=reset - filename=rootfs - md5sum=$ROOTFS_MD5 - filemd5sum=$ROOTFS_MD5_FULL -+filesha256sum=$ROOTFS_SHA256_FULL - flashaddr=$ROOTFS_FLASH_ADDR - checksize=$ROOTFS_CHECK_SIZE - cmd_success=setenv bootseq 1,2; setenv kernel_size_1 $KERNEL_PART_SIZE; setenv rootfs_size_1 $ROOTFS_PART_SIZE; saveenv diff --git a/patches/openwrt/0065-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-AC-b.patch b/patches/openwrt/0065-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-AC-b.patch deleted file mode 100644 index f3f8b253..00000000 --- a/patches/openwrt/0065-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-AC-b.patch +++ /dev/null @@ -1,265 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:25:47 +0000 -Subject: ar71xx: add kernel support for the OpenMesh OM5P-AC board - -Signed-off-by: Sven Eckelmann - -Backport of r49141 - -Forwarded: https://patchwork.ozlabs.org/patch/624191/ - -diff --git a/target/linux/ar71xx/config-3.18 b/target/linux/ar71xx/config-3.18 -index c5a3c9a..dd89357 100644 ---- a/target/linux/ar71xx/config-3.18 -+++ b/target/linux/ar71xx/config-3.18 -@@ -91,6 +91,7 @@ CONFIG_ATH79_MACH_NBG460N=y - CONFIG_ATH79_MACH_NBG6716=y - CONFIG_ATH79_MACH_OM2P=y - CONFIG_ATH79_MACH_OM5P=y -+CONFIG_ATH79_MACH_OM5P_AC=y - CONFIG_ATH79_MACH_ONION_OMEGA=y - CONFIG_ATH79_MACH_PB42=y - CONFIG_ATH79_MACH_PB44=y -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c -new file mode 100644 -index 0000000..f6974af ---- /dev/null -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pac.c -@@ -0,0 +1,193 @@ -+/* -+ * OpenMesh OM5P-AC support -+ * -+ * Copyright (C) 2013 Marek Lindner -+ * Copyright (C) 2014 Sven Eckelmann -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "common.h" -+#include "dev-ap9x-pci.h" -+#include "dev-eth.h" -+#include "dev-leds-gpio.h" -+#include "dev-m25p80.h" -+#include "dev-wmac.h" -+#include "machtypes.h" -+#include "pci.h" -+ -+#define OM5PAC_GPIO_LED_POWER 18 -+#define OM5PAC_GPIO_LED_GREEN 21 -+#define OM5PAC_GPIO_LED_RED 23 -+#define OM5PAC_GPIO_LED_YELLOW 22 -+#define OM5PAC_GPIO_LED_LAN 20 -+#define OM5PAC_GPIO_LED_WAN 19 -+#define OM5PAC_GPIO_I2C_SCL 12 -+#define OM5PAC_GPIO_I2C_SDA 11 -+ -+#define OM5PAC_KEYS_POLL_INTERVAL 20 /* msecs */ -+#define OM5PAC_KEYS_DEBOUNCE_INTERVAL (3 * OM5PAC_KEYS_POLL_INTERVAL) -+ -+#define OM5PAC_WMAC_CALDATA_OFFSET 0x1000 -+ -+static struct gpio_led om5pac_leds_gpio[] __initdata = { -+ { -+ .name = "om5pac:blue:power", -+ .gpio = OM5PAC_GPIO_LED_POWER, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:red:wifi", -+ .gpio = OM5PAC_GPIO_LED_RED, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:yellow:wifi", -+ .gpio = OM5PAC_GPIO_LED_YELLOW, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:green:wifi", -+ .gpio = OM5PAC_GPIO_LED_GREEN, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:blue:lan", -+ .gpio = OM5PAC_GPIO_LED_LAN, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:blue:wan", -+ .gpio = OM5PAC_GPIO_LED_WAN, -+ .active_low = 1, -+ } -+}; -+ -+static struct flash_platform_data om5pac_flash_data = { -+ .type = "mx25l12805d", -+}; -+ -+static struct i2c_gpio_platform_data om5pac_i2c_device_platdata = { -+ .sda_pin = OM5PAC_GPIO_I2C_SDA, -+ .scl_pin = OM5PAC_GPIO_I2C_SCL, -+ .udelay = 10, -+ .sda_is_open_drain = 1, -+ .scl_is_open_drain = 1, -+}; -+ -+static struct platform_device om5pac_i2c_device = { -+ .name = "i2c-gpio", -+ .id = 0, -+ .dev = { -+ .platform_data = &om5pac_i2c_device_platdata, -+ }, -+}; -+ -+static struct i2c_board_info om5pac_i2c_devs[] __initdata = { -+ { -+ I2C_BOARD_INFO("tmp423", 0x4c), -+ }, -+}; -+ -+static struct at803x_platform_data om5pac_at803x_data = { -+ .disable_smarteee = 1, -+ .enable_rgmii_rx_delay = 1, -+ .enable_rgmii_tx_delay = 1, -+}; -+ -+static struct mdio_board_info om5pac_mdio0_info[] = { -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 1, -+ .platform_data = &om5pac_at803x_data, -+ }, -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 2, -+ .platform_data = &om5pac_at803x_data, -+ }, -+}; -+ -+static void __init om5p_ac_setup_qca955x_eth_cfg(u32 mask, -+ unsigned int rxd, -+ unsigned int rxdv, -+ unsigned int txd, -+ unsigned int txe) -+{ -+ void __iomem *base; -+ u32 t; -+ -+ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); -+ -+ t = mask; -+ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; -+ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; -+ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; -+ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; -+ -+ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); -+ -+ iounmap(base); -+} -+ -+static void __init om5p_ac_setup(void) -+{ -+ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -+ u8 mac[6]; -+ -+ /* temperature sensor */ -+ platform_device_register(&om5pac_i2c_device); -+ i2c_register_board_info(0, om5pac_i2c_devs, -+ ARRAY_SIZE(om5pac_i2c_devs)); -+ -+ ath79_gpio_output_select(OM5PAC_GPIO_LED_WAN, QCA955X_GPIO_OUT_GPIO); -+ -+ ath79_register_m25p80(&om5pac_flash_data); -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5pac_leds_gpio), -+ om5pac_leds_gpio); -+ -+ ath79_init_mac(mac, art, 0x02); -+ ath79_register_wmac(art + OM5PAC_WMAC_CALDATA_OFFSET, mac); -+ -+ om5p_ac_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 3, 3, 0, 0); -+ ath79_register_mdio(0, 0x0); -+ -+ mdiobus_register_board_info(om5pac_mdio0_info, -+ ARRAY_SIZE(om5pac_mdio0_info)); -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); -+ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); -+ -+ /* GMAC0 is connected to the PHY1 */ -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; -+ ath79_eth0_data.phy_mask = BIT(1); -+ ath79_eth0_pll_data.pll_1000 = 0x82000101; -+ ath79_eth0_pll_data.pll_100 = 0x80000101; -+ ath79_eth0_pll_data.pll_10 = 0x80001313; -+ ath79_register_eth(0); -+ -+ /* GMAC1 is connected to MDIO1 in SGMII mode */ -+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; -+ ath79_eth1_data.mii_bus_dev = &ath79_mdio0_device.dev; -+ ath79_eth1_data.phy_mask = BIT(2); -+ ath79_eth1_pll_data.pll_1000 = 0x03000101; -+ ath79_eth1_pll_data.pll_100 = 0x80000101; -+ ath79_eth1_pll_data.pll_10 = 0x80001313; -+ ath79_eth1_data.speed = SPEED_1000; -+ ath79_eth1_data.duplex = DUPLEX_FULL; -+ ath79_register_eth(1); -+ -+ ath79_register_pci(); -+} -+ -+MIPS_MACHINE(ATH79_MACH_OM5P_AC, "OM5P-AC", "OpenMesh OM5P AC", om5p_ac_setup); -diff --git a/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-om5pac-support.patch b/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-om5pac-support.patch -new file mode 100644 -index 0000000..4accd03 ---- /dev/null -+++ b/target/linux/ar71xx/patches-3.18/815-MIPS-ath79-add-om5pac-support.patch -@@ -0,0 +1,38 @@ -+--- a/arch/mips/ath79/Kconfig -++++ b/arch/mips/ath79/Kconfig -+@@ -799,6 +799,15 @@ config ATH79_MACH_OM5P -+ select ATH79_DEV_M25P80 -+ select ATH79_DEV_WMAC -+ -++config ATH79_MACH_OM5P_AC -++ bool "OpenMesh OM5P-AC board support" -++ select SOC_QCA955X -++ select ATH79_DEV_AP9X_PCI if PCI -++ select ATH79_DEV_ETH -++ select ATH79_DEV_LEDS_GPIO -++ select ATH79_DEV_M25P80 -++ select ATH79_DEV_WMAC -++ -+ config ATH79_MACH_ONION_OMEGA -+ bool "ONION OMEGA support" -+ select SOC_AR933X -+--- a/arch/mips/ath79/Makefile -++++ b/arch/mips/ath79/Makefile -+@@ -100,6 +100,7 @@ obj-$(CONFIG_ATH79_MACH_MZK_W300NH) += m -+ obj-$(CONFIG_ATH79_MACH_NBG460N) += mach-nbg460n.o -+ obj-$(CONFIG_ATH79_MACH_OM2P) += mach-om2p.o -+ obj-$(CONFIG_ATH79_MACH_OM5P) += mach-om5p.o -++obj-$(CONFIG_ATH79_MACH_OM5P_AC) += mach-om5pac.o -+ obj-$(CONFIG_ATH79_MACH_ONION_OMEGA) += mach-onion-omega.o -+ obj-$(CONFIG_ATH79_MACH_PB42) += mach-pb42.o -+ obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o -+--- a/arch/mips/ath79/machtypes.h -++++ b/arch/mips/ath79/machtypes.h -+@@ -95,6 +95,7 @@ enum ath79_mach_type { -+ ATH79_MACH_OM2P_LC, /* OpenMesh OM2P-LC */ -+ ATH79_MACH_OM2Pv2, /* OpenMesh OM2Pv2 */ -+ ATH79_MACH_OM2P, /* OpenMesh OM2P */ -++ ATH79_MACH_OM5P_AC, /* OpenMesh OM5P-AC */ -+ ATH79_MACH_OM5P_AN, /* OpenMesh OM5P-AN */ -+ ATH79_MACH_OM5P, /* OpenMesh OM5P */ -+ ATH79_MACH_ONION_OMEGA, /* ONION OMEGA */ diff --git a/patches/openwrt/0066-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch b/patches/openwrt/0066-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch deleted file mode 100644 index 7161fdca..00000000 --- a/patches/openwrt/0066-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:25:51 +0000 -Subject: ar71xx: add user-space support for the OpenMesh OM5P-AC - -Signed-off-by: Sven Eckelmann - -Backport of r49142 - -Forwarded: https://patchwork.ozlabs.org/patch/624192/ - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index 44d2ddf..a4051f2 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -178,6 +178,9 @@ get_status_led() { - om5p-an) - status_led="om5p:blue:power" - ;; -+ om5p-ac) -+ status_led="om5pac:blue:power" -+ ;; - onion-omega) - status_led="onion:amber:system" - ;; -diff --git a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -index c451124..9a768cd 100644 ---- a/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -+++ b/target/linux/ar71xx/base-files/etc/uci-defaults/01_leds -@@ -304,6 +304,11 @@ om5p-an) - ucidef_set_led_netdev "port2" "port2" "om5p:blue:lan" "eth1" - ;; - -+om5p-ac) -+ ucidef_set_led_netdev "port1" "port1" "om5pac:blue:lan" "eth0" -+ ucidef_set_led_netdev "port2" "port2" "om5pac:blue:wan" "eth1" -+ ;; -+ - qihoo-c301) - ucidef_set_led_wlan "wlan2g" "WLAN2G" "qihoo:red:status" "phy1tpt" - ;; -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index 587d029..10b8048 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -616,6 +616,9 @@ ar71xx_board_detect() { - *"OM5P AN") - name="om5p-an" - ;; -+ *"OM5P AC") -+ name="om5p-ac" -+ ;; - *"Onion Omega") - name="onion-omega" - ;; diff --git a/patches/openwrt/0067-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-O.patch b/patches/openwrt/0067-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-O.patch deleted file mode 100644 index 4b6311e2..00000000 --- a/patches/openwrt/0067-scripts-om-fwupgradecfg-gen.sh-add-support-for-the-O.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:25:54 +0000 -Subject: scripts/om-fwupgradecfg-gen.sh: add support for the OM5P-AC - -Signed-off-by: Sven Eckelmann - -Backport of r49143 - -Forwarded: https://patchwork.ozlabs.org/patch/624193/ - -diff --git a/scripts/om-fwupgradecfg-gen.sh b/scripts/om-fwupgradecfg-gen.sh -index e208e6d..6c3b74c 100644 ---- a/scripts/om-fwupgradecfg-gen.sh -+++ b/scripts/om-fwupgradecfg-gen.sh -@@ -7,7 +7,7 @@ - # - - usage() { -- echo "Usage: $0 " -+ echo "Usage: $0 " - rm -f $CFG_OUT - exit 1 - } -@@ -26,7 +26,7 @@ case $CE_TYPE in - FLASH_BS=262144 - MD5_SKIP_BLOCKS=1 - ;; -- OM5P|MR600|MR900|MR1750) -+ OM5P|OM5PAC|MR600|MR900|MR1750) - MAX_PART_SIZE=7808 - KERNEL_FLASH_ADDR=0xb0000 - FLASH_BS=65536 diff --git a/patches/openwrt/0068-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-AC.patch b/patches/openwrt/0068-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-AC.patch deleted file mode 100644 index ae08198a..00000000 --- a/patches/openwrt/0068-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-AC.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:25:57 +0000 -Subject: ar71xx: enable sysupgrade for the OpenMesh OM5P-AC - -Signed-off-by: Sven Eckelmann - -Backport of r49144 - -Forwarded: https://patchwork.ozlabs.org/patch/624194/ - -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -index 9ca0f5b..1cfead9 100644 ---- a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -@@ -72,6 +72,11 @@ platform_check_image_openmesh() - echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" - return 1 - ;; -+ OM5PAC) -+ [ "$board" = "om5p-ac" ] && break -+ echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" -+ return 1 -+ ;; - MR1750) - [ "$board" = "mr1750" ] && break - echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" -@@ -162,7 +167,7 @@ platform_do_upgrade_openmesh() - kernel_start_addr1=0x9f1c0000 - kernel_start_addr2=0x9f8c0000 - ;; -- OM5P|MR600|MR900|MR1750) -+ OM5P|OM5PAC|MR600|MR900|MR1750) - block_size=$((64 * 1024)) - total_size=7995392 - kernel_start_addr1=0x9f0b0000 -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index ac060ea..67c0661 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -307,7 +307,8 @@ platform_check_image() { - om2p-hsv2 | \ - om2p-lc | \ - om5p | \ -- om5p-an) -+ om5p-an | \ -+ om5p-ac) - platform_check_image_openmesh "$magic_long" "$1" && return 0 - return 1 - ;; -@@ -540,7 +541,8 @@ platform_do_upgrade() { - om2p-hsv2 | \ - om2p-lc | \ - om5p | \ -- om5p-an) -+ om5p-an | \ -+ om5p-ac) - platform_do_upgrade_openmesh "$ARGV" - ;; - unifi-outdoor-plus | \ diff --git a/patches/openwrt/0069-om-watchdog-add-OpenMesh-OM5P-AC-support.patch b/patches/openwrt/0069-om-watchdog-add-OpenMesh-OM5P-AC-support.patch deleted file mode 100644 index c2d2e225..00000000 --- a/patches/openwrt/0069-om-watchdog-add-OpenMesh-OM5P-AC-support.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:01 +0000 -Subject: om-watchdog: add OpenMesh OM5P-AC support - -Signed-off-by: Sven Eckelmann - -Backport of r49145 - -Forwarded: https://patchwork.ozlabs.org/patch/624195/ - -diff --git a/package/kernel/om-watchdog/files/om-watchdog.init b/package/kernel/om-watchdog/files/om-watchdog.init -index c792968..8cec13b 100644 ---- a/package/kernel/om-watchdog/files/om-watchdog.init -+++ b/package/kernel/om-watchdog/files/om-watchdog.init -@@ -22,6 +22,9 @@ boot() { - "om5p"|"om5p-an") - service_start /sbin/om-watchdog 11 - ;; -+ "om5p-ac") -+ service_start /sbin/om-watchdog 17 -+ ;; - "mr600v2") - service_start /sbin/om-watchdog 15 - ;; diff --git a/patches/openwrt/0070-uboot-envtools-add-OpenMesh-OM5P-AC-support.patch b/patches/openwrt/0070-uboot-envtools-add-OpenMesh-OM5P-AC-support.patch deleted file mode 100644 index 0d7b312e..00000000 --- a/patches/openwrt/0070-uboot-envtools-add-OpenMesh-OM5P-AC-support.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:04 +0000 -Subject: uboot-envtools: add OpenMesh OM5P-AC support - -Signed-off-by: Sven Eckelmann - -Backport of r49146 - -Forwarded: https://patchwork.ozlabs.org/patch/624196/ - -diff --git a/package/boot/uboot-envtools/files/ar71xx b/package/boot/uboot-envtools/files/ar71xx -index ef00f17..657b25f 100644 ---- a/package/boot/uboot-envtools/files/ar71xx -+++ b/package/boot/uboot-envtools/files/ar71xx -@@ -28,6 +28,7 @@ mr900 | \ - mr900v2 | \ - nbg6716 | \ - om5p-an | \ -+om5p-ac | \ - om5p | \ - tube2h | \ - wndr3700) diff --git a/patches/openwrt/0071-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch b/patches/openwrt/0071-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch deleted file mode 100644 index 0cd9fec5..00000000 --- a/patches/openwrt/0071-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch +++ /dev/null @@ -1,25 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:08 +0000 -Subject: ar71xx: extract ath10k wifi board.bin for the OpenMesh OM5P-AC board - -Signed-off-by: Sven Eckelmann - -Backport of r49147 - -Forwarded: https://patchwork.ozlabs.org/patch/624197/ - -diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -index cde7aaf..c1f4b85 100644 ---- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -+++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -@@ -96,6 +96,10 @@ case "$FIRMWARE" in - rb-911g-5hpacd) - ath10kcal_from_file "/sys/firmware/routerboot/ext_wlan_data" 20480 2116 - ;; -+ om5p-ac) -+ ath10kcal_extract "ART" 20480 2116 -+ ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) -+ ;; - esac - ;; - *) diff --git a/patches/openwrt/0072-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch b/patches/openwrt/0072-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch deleted file mode 100644 index ce03a85f..00000000 --- a/patches/openwrt/0072-ar71xx-create-profile-and-build-image-for-the-OpenMe.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:11 +0000 -Subject: ar71xx: create profile and build image for the OpenMesh OM5P-AC board - -Signed-off-by: Sven Eckelmann - -Backport of r49148 - -Forwarded: https://patchwork.ozlabs.org/patch/624198/ - -diff --git a/target/linux/ar71xx/generic/profiles/openmesh.mk b/target/linux/ar71xx/generic/profiles/openmesh.mk -index 06cf135..64aaa24 100644 ---- a/target/linux/ar71xx/generic/profiles/openmesh.mk -+++ b/target/linux/ar71xx/generic/profiles/openmesh.mk -@@ -27,6 +27,17 @@ endef - - $(eval $(call Profile,OM5P)) - -+define Profile/OM5PAC -+ NAME:=OpenMesh OM5P-AC -+ PACKAGES:=kmod-ath9k kmod-ath10k om-watchdog ath10k-firmware-qca988x -+endef -+ -+define Profile/OM5PAC/Description -+ Package set optimized for the OpenMesh OM5P-AC. -+endef -+ -+$(eval $(call Profile,OM5PAC)) -+ - define Profile/MR600 - NAME:=OpenMesh MR600 - PACKAGES:=kmod-ath9k om-watchdog -diff --git a/target/linux/ar71xx/image/Makefile b/target/linux/ar71xx/image/Makefile -index b74aa45..06dbb77 100644 ---- a/target/linux/ar71xx/image/Makefile -+++ b/target/linux/ar71xx/image/Makefile -@@ -2043,6 +2043,7 @@ $(eval $(call SingleProfile,Netgear,64kraw,WPN824N,wpn824n,WPN824N,ttyS0,115200, - - $(eval $(call SingleProfile,OpenMesh,squashfs-only,OM2P,om2p,,,,OM2P)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,OM5P,om5p,,,,OM5P)) -+$(eval $(call SingleProfile,OpenMesh,squashfs-only,OM5PAC,om5pac,,,,OM5PAC)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,MR600,mr600,,,,MR600)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,MR900,mr900,,,,MR900)) - $(eval $(call SingleProfile,OpenMesh,squashfs-only,MR1750,mr1750,,,,MR1750)) -@@ -2139,7 +2140,7 @@ $(eval $(call MultiProfile,AP121,AP121_2M AP121_4M)) - $(eval $(call MultiProfile,DIR615IX,DIR615I1 DIR615I3)) - $(eval $(call MultiProfile,AP136,AP136_010 AP136_020)) - $(eval $(call MultiProfile,EWDORIN, EWDORINAP EWDORINRT EWDORIN16M)) --$(eval $(call MultiProfile,OPENMESH,OM2P OM5P MR600 MR900 MR1750)) -+$(eval $(call MultiProfile,OPENMESH,OM2P OM5P OM5PAC MR600 MR900 MR1750)) - $(eval $(call MultiProfile,TEW652BRP,TEW652BRP_FW TEW652BRP_RECOVERY)) - $(eval $(call MultiProfile,TLMR3220,TLMR3220V1)) - $(eval $(call MultiProfile,TLMR3420,TLMR3420V1)) diff --git a/patches/openwrt/0073-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-ACv2.patch b/patches/openwrt/0073-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-ACv2.patch deleted file mode 100644 index d2e2cd60..00000000 --- a/patches/openwrt/0073-ar71xx-add-kernel-support-for-the-OpenMesh-OM5P-ACv2.patch +++ /dev/null @@ -1,289 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:15 +0000 -Subject: ar71xx: add kernel support for the OpenMesh OM5P-ACv2 board - -Signed-off-by: Sven Eckelmann - -Backport of r49149 - -Forwarded: https://patchwork.ozlabs.org/patch/624199/ - -diff --git a/target/linux/ar71xx/config-3.18 b/target/linux/ar71xx/config-3.18 -index dd89357..514f7d5 100644 ---- a/target/linux/ar71xx/config-3.18 -+++ b/target/linux/ar71xx/config-3.18 -@@ -92,6 +92,7 @@ CONFIG_ATH79_MACH_NBG6716=y - CONFIG_ATH79_MACH_OM2P=y - CONFIG_ATH79_MACH_OM5P=y - CONFIG_ATH79_MACH_OM5P_AC=y -+CONFIG_ATH79_MACH_OM5P_ACv2=y - CONFIG_ATH79_MACH_ONION_OMEGA=y - CONFIG_ATH79_MACH_PB42=y - CONFIG_ATH79_MACH_PB44=y -diff --git a/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c -new file mode 100644 -index 0000000..587ca32 ---- /dev/null -+++ b/target/linux/ar71xx/files/arch/mips/ath79/mach-om5pacv2.c -@@ -0,0 +1,216 @@ -+/* -+ * OpenMesh OM5P-ACv2 support -+ * -+ * Copyright (C) 2013 Marek Lindner -+ * Copyright (C) 2014-2016 Sven Eckelmann -+ * Copyright (C) 2015 Open-Mesh - Jim Collar -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+ -+#include "common.h" -+#include "dev-ap9x-pci.h" -+#include "dev-eth.h" -+#include "dev-gpio-buttons.h" -+#include "dev-leds-gpio.h" -+#include "dev-m25p80.h" -+#include "dev-wmac.h" -+#include "machtypes.h" -+#include "pci.h" -+ -+#define OM5PACV2_GPIO_LED_POWER 14 -+#define OM5PACV2_GPIO_LED_GREEN 13 -+#define OM5PACV2_GPIO_LED_RED 23 -+#define OM5PACV2_GPIO_LED_YELLOW 15 -+#define OM5PACV2_GPIO_BTN_RESET 1 -+#define OM5PACV2_GPIO_I2C_SCL 18 -+#define OM5PACV2_GPIO_I2C_SDA 19 -+#define OM5PACV2_GPIO_PA_DCDC 2 -+#define OM5PACV2_GPIO_PA_HIGH 16 -+ -+#define OM5PACV2_KEYS_POLL_INTERVAL 20 /* msecs */ -+#define OM5PACV2_KEYS_DEBOUNCE_INTERVAL (3 * OM5PACV2_KEYS_POLL_INTERVAL) -+ -+#define OM5PACV2_WMAC_CALDATA_OFFSET 0x1000 -+ -+static struct gpio_led om5pacv2_leds_gpio[] __initdata = { -+ { -+ .name = "om5pac:blue:power", -+ .gpio = OM5PACV2_GPIO_LED_POWER, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:red:wifi", -+ .gpio = OM5PACV2_GPIO_LED_RED, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:yellow:wifi", -+ .gpio = OM5PACV2_GPIO_LED_YELLOW, -+ .active_low = 1, -+ }, { -+ .name = "om5pac:green:wifi", -+ .gpio = OM5PACV2_GPIO_LED_GREEN, -+ .active_low = 1, -+ } -+}; -+ -+static struct gpio_keys_button om5pacv2_gpio_keys[] __initdata = { -+ { -+ .desc = "reset", -+ .type = EV_KEY, -+ .code = KEY_RESTART, -+ .debounce_interval = OM5PACV2_KEYS_DEBOUNCE_INTERVAL, -+ .gpio = OM5PACV2_GPIO_BTN_RESET, -+ .active_low = 1, -+ } -+}; -+ -+static struct i2c_gpio_platform_data om5pacv2_i2c_device_platdata = { -+ .sda_pin = OM5PACV2_GPIO_I2C_SDA, -+ .scl_pin = OM5PACV2_GPIO_I2C_SCL, -+ .udelay = 10, -+ .sda_is_open_drain = 1, -+ .scl_is_open_drain = 1, -+}; -+ -+static struct platform_device om5pacv2_i2c_device = { -+ .name = "i2c-gpio", -+ .id = 0, -+ .dev = { -+ .platform_data = &om5pacv2_i2c_device_platdata, -+ }, -+}; -+ -+static struct i2c_board_info om5pacv2_i2c_devs[] __initdata = { -+ { -+ I2C_BOARD_INFO("tmp423", 0x4e), -+ }, -+}; -+ -+static struct flash_platform_data om5pacv2_flash_data = { -+ .type = "mx25l12805d", -+}; -+ -+static struct at803x_platform_data om5pacv2_an_at803x_data = { -+ .disable_smarteee = 1, -+ .enable_rgmii_rx_delay = 1, -+ .enable_rgmii_tx_delay = 1, -+}; -+ -+static struct at803x_platform_data om5pacv2_an_at8031_data = { -+ .disable_smarteee = 1, -+ .enable_rgmii_rx_delay = 1, -+ .enable_rgmii_tx_delay = 1, -+}; -+ -+static struct mdio_board_info om5pacv2_an_mdio0_info[] = { -+ { -+ .bus_id = "ag71xx-mdio.0", -+ .phy_addr = 4, -+ .platform_data = &om5pacv2_an_at803x_data, -+ }, -+ { -+ .bus_id = "ag71xx-mdio.1", -+ .phy_addr = 1, -+ .platform_data = &om5pacv2_an_at8031_data, -+ }, -+}; -+ -+static void __init om5p_acv2_setup_qca955x_eth_cfg(u32 mask, -+ unsigned int rxd, -+ unsigned int rxdv, -+ unsigned int txd, -+ unsigned int txe) -+{ -+ void __iomem *base; -+ u32 t; -+ -+ base = ioremap(QCA955X_GMAC_BASE, QCA955X_GMAC_SIZE); -+ -+ t = mask; -+ t |= rxd << QCA955X_ETH_CFG_RXD_DELAY_SHIFT; -+ t |= rxdv << QCA955X_ETH_CFG_RDV_DELAY_SHIFT; -+ t |= txd << QCA955X_ETH_CFG_TXD_DELAY_SHIFT; -+ t |= txe << QCA955X_ETH_CFG_TXE_DELAY_SHIFT; -+ -+ __raw_writel(t, base + QCA955X_GMAC_REG_ETH_CFG); -+ -+ iounmap(base); -+} -+ -+static void __init om5p_acv2_setup(void) -+{ -+ u8 *art = (u8 *)KSEG1ADDR(0x1fff0000); -+ u8 mac[6]; -+ -+ /* power amplifier high power, 4.2V at RFFM4203/4503 instead of 3.3 */ -+ ath79_gpio_function_enable(QCA955X_GPIO_FUNC_JTAG_DISABLE); -+ ath79_gpio_output_select(OM5PACV2_GPIO_PA_DCDC, QCA955X_GPIO_OUT_GPIO); -+ ath79_gpio_output_select(OM5PACV2_GPIO_PA_HIGH, QCA955X_GPIO_OUT_GPIO); -+ gpio_request_one(OM5PACV2_GPIO_PA_DCDC, GPIOF_OUT_INIT_HIGH, -+ "PA DC/DC"); -+ gpio_request_one(OM5PACV2_GPIO_PA_HIGH, GPIOF_OUT_INIT_HIGH, "PA HIGH"); -+ -+ /* temperature sensor */ -+ platform_device_register(&om5pacv2_i2c_device); -+ i2c_register_board_info(0, om5pacv2_i2c_devs, -+ ARRAY_SIZE(om5pacv2_i2c_devs)); -+ -+ ath79_register_m25p80(&om5pacv2_flash_data); -+ ath79_register_leds_gpio(-1, ARRAY_SIZE(om5pacv2_leds_gpio), -+ om5pacv2_leds_gpio); -+ ath79_register_gpio_keys_polled(-1, OM5PACV2_KEYS_POLL_INTERVAL, -+ ARRAY_SIZE(om5pacv2_gpio_keys), -+ om5pacv2_gpio_keys); -+ -+ ath79_init_mac(mac, art, 0x02); -+ ath79_register_wmac(art + OM5PACV2_WMAC_CALDATA_OFFSET, mac); -+ -+ om5p_acv2_setup_qca955x_eth_cfg(QCA955X_ETH_CFG_RGMII_EN, 2, 2, 0, 0); -+ ath79_register_mdio(0, 0x0); -+ ath79_register_mdio(1, 0x0); -+ -+ mdiobus_register_board_info(om5pacv2_an_mdio0_info, -+ ARRAY_SIZE(om5pacv2_an_mdio0_info)); -+ -+ ath79_init_mac(ath79_eth0_data.mac_addr, art, 0x00); -+ ath79_init_mac(ath79_eth1_data.mac_addr, art, 0x01); -+ -+ /* GMAC0 is connected to the PHY4 */ -+ ath79_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; -+ ath79_eth0_data.mii_bus_dev = &ath79_mdio0_device.dev; -+ ath79_eth0_data.phy_mask = BIT(4); -+ ath79_eth0_pll_data.pll_1000 = 0x82000101; -+ ath79_eth0_pll_data.pll_100 = 0x80000101; -+ ath79_eth0_pll_data.pll_10 = 0x80001313; -+ ath79_register_eth(0); -+ -+ /* GMAC1 is connected to MDIO1 in SGMII mode */ -+ ath79_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_SGMII; -+ ath79_eth1_data.mii_bus_dev = &ath79_mdio1_device.dev; -+ ath79_eth1_data.phy_mask = BIT(1); -+ ath79_eth1_pll_data.pll_1000 = 0x03000101; -+ ath79_eth1_pll_data.pll_100 = 0x80000101; -+ ath79_eth1_pll_data.pll_10 = 0x80001313; -+ ath79_eth1_data.speed = SPEED_1000; -+ ath79_eth1_data.duplex = DUPLEX_FULL; -+ ath79_register_eth(1); -+ -+ ath79_register_pci(); -+} -+ -+MIPS_MACHINE(ATH79_MACH_OM5P_ACv2, "OM5P-ACv2", "OpenMesh OM5P ACv2", om5p_acv2_setup); -diff --git a/target/linux/ar71xx/patches-3.18/816-MIPS-ath79-add-om5pacv-support.patch b/target/linux/ar71xx/patches-3.18/816-MIPS-ath79-add-om5pacv-support.patch -new file mode 100644 -index 0000000..fbbf171 ---- /dev/null -+++ b/target/linux/ar71xx/patches-3.18/816-MIPS-ath79-add-om5pacv-support.patch -@@ -0,0 +1,39 @@ -+--- a/arch/mips/ath79/Kconfig -++++ b/arch/mips/ath79/Kconfig -+@@ -808,6 +808,16 @@ config ATH79_MACH_OM5P_AC -+ select ATH79_DEV_M25P80 -+ select ATH79_DEV_WMAC -+ -++config ATH79_MACH_OM5P_ACv2 -++ bool "OpenMesh OM5P-ACv2 board support" -++ select SOC_QCA955X -++ select ATH79_DEV_AP9X_PCI if PCI -++ select ATH79_DEV_ETH -++ select ATH79_DEV_GPIO_BUTTONS -++ select ATH79_DEV_LEDS_GPIO -++ select ATH79_DEV_M25P80 -++ select ATH79_DEV_WMAC -++ -+ config ATH79_MACH_ONION_OMEGA -+ bool "ONION OMEGA support" -+ select SOC_AR933X -+--- a/arch/mips/ath79/Makefile -++++ b/arch/mips/ath79/Makefile -+@@ -101,6 +101,7 @@ obj-$(CONFIG_ATH79_MACH_NBG460N) += mach -+ obj-$(CONFIG_ATH79_MACH_OM2P) += mach-om2p.o -+ obj-$(CONFIG_ATH79_MACH_OM5P) += mach-om5p.o -+ obj-$(CONFIG_ATH79_MACH_OM5P_AC) += mach-om5pac.o -++obj-$(CONFIG_ATH79_MACH_OM5P_ACv2) += mach-om5pacv2.o -+ obj-$(CONFIG_ATH79_MACH_ONION_OMEGA) += mach-onion-omega.o -+ obj-$(CONFIG_ATH79_MACH_PB42) += mach-pb42.o -+ obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.o -+--- a/arch/mips/ath79/machtypes.h -++++ b/arch/mips/ath79/machtypes.h -+@@ -96,6 +96,7 @@ enum ath79_mach_type { -+ ATH79_MACH_OM2Pv2, /* OpenMesh OM2Pv2 */ -+ ATH79_MACH_OM2P, /* OpenMesh OM2P */ -+ ATH79_MACH_OM5P_AC, /* OpenMesh OM5P-AC */ -++ ATH79_MACH_OM5P_ACv2, /* OpenMesh OM5P-ACv2 */ -+ ATH79_MACH_OM5P_AN, /* OpenMesh OM5P-AN */ -+ ATH79_MACH_OM5P, /* OpenMesh OM5P */ -+ ATH79_MACH_ONION_OMEGA, /* ONION OMEGA */ diff --git a/patches/openwrt/0074-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch b/patches/openwrt/0074-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch deleted file mode 100644 index 2ea0cb6a..00000000 --- a/patches/openwrt/0074-ar71xx-add-user-space-support-for-the-OpenMesh-OM5P-.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:18 +0000 -Subject: ar71xx: add user-space support for the OpenMesh OM5P-ACv2 - -Signed-off-by: Sven Eckelmann - -Backport of r49150 - -Forwarded: https://patchwork.ozlabs.org/patch/624200/ - -diff --git a/target/linux/ar71xx/base-files/etc/diag.sh b/target/linux/ar71xx/base-files/etc/diag.sh -index a4051f2..d4d8b4e 100644 ---- a/target/linux/ar71xx/base-files/etc/diag.sh -+++ b/target/linux/ar71xx/base-files/etc/diag.sh -@@ -178,7 +178,8 @@ get_status_led() { - om5p-an) - status_led="om5p:blue:power" - ;; -- om5p-ac) -+ om5p-ac | \ -+ om5p-acv2) - status_led="om5pac:blue:power" - ;; - onion-omega) -diff --git a/target/linux/ar71xx/base-files/lib/ar71xx.sh b/target/linux/ar71xx/base-files/lib/ar71xx.sh -index 10b8048..fbf76c8 100755 ---- a/target/linux/ar71xx/base-files/lib/ar71xx.sh -+++ b/target/linux/ar71xx/base-files/lib/ar71xx.sh -@@ -619,6 +619,9 @@ ar71xx_board_detect() { - *"OM5P AC") - name="om5p-ac" - ;; -+ *"OM5P ACv2") -+ name="om5p-acv2" -+ ;; - *"Onion Omega") - name="onion-omega" - ;; diff --git a/patches/openwrt/0075-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-ACv2.patch b/patches/openwrt/0075-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-ACv2.patch deleted file mode 100644 index 0c4cf031..00000000 --- a/patches/openwrt/0075-ar71xx-enable-sysupgrade-for-the-OpenMesh-OM5P-ACv2.patch +++ /dev/null @@ -1,46 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:22 +0000 -Subject: ar71xx: enable sysupgrade for the OpenMesh OM5P-ACv2 - -Signed-off-by: Sven Eckelmann - -Backport of r49151 - -Forwarded: https://patchwork.ozlabs.org/patch/624201/ - -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -index 1cfead9..209cdaa 100644 ---- a/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/openmesh.sh -@@ -74,6 +74,7 @@ platform_check_image_openmesh() - ;; - OM5PAC) - [ "$board" = "om5p-ac" ] && break -+ [ "$board" = "om5p-acv2" ] && break - echo "Invalid image board target ($img_board_target) for this platform: $board. Use the correct image for this platform" - return 1 - ;; -diff --git a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -index 67c0661..4a4c476 100755 ---- a/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -+++ b/target/linux/ar71xx/base-files/lib/upgrade/platform.sh -@@ -308,7 +308,8 @@ platform_check_image() { - om2p-lc | \ - om5p | \ - om5p-an | \ -- om5p-ac) -+ om5p-ac | \ -+ om5p-acv2) - platform_check_image_openmesh "$magic_long" "$1" && return 0 - return 1 - ;; -@@ -542,7 +543,8 @@ platform_do_upgrade() { - om2p-lc | \ - om5p | \ - om5p-an | \ -- om5p-ac) -+ om5p-ac | \ -+ om5p-acv2) - platform_do_upgrade_openmesh "$ARGV" - ;; - unifi-outdoor-plus | \ diff --git a/patches/openwrt/0076-om-watchdog-add-OpenMesh-OM5P-ACv2-support.patch b/patches/openwrt/0076-om-watchdog-add-OpenMesh-OM5P-ACv2-support.patch deleted file mode 100644 index b3c8c8fc..00000000 --- a/patches/openwrt/0076-om-watchdog-add-OpenMesh-OM5P-ACv2-support.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:25 +0000 -Subject: om-watchdog: add OpenMesh OM5P-ACv2 support - -Signed-off-by: Sven Eckelmann - -Backport of r49152 - -Forwarded: https://patchwork.ozlabs.org/patch/624202/ - -diff --git a/package/kernel/om-watchdog/files/om-watchdog.init b/package/kernel/om-watchdog/files/om-watchdog.init -index 8cec13b..6b96966 100644 ---- a/package/kernel/om-watchdog/files/om-watchdog.init -+++ b/package/kernel/om-watchdog/files/om-watchdog.init -@@ -13,7 +13,7 @@ boot() { - local board=$(ar71xx_board_name) - - case "$board" in -- "om2p"|"om2p-hs"|"om2p-hsv2") -+ "om2p"|"om2p-hs"|"om2p-hsv2"|"om5p-acv2") - service_start /sbin/om-watchdog 12 - ;; - "om2pv2"|"om2p-lc") diff --git a/patches/openwrt/0077-uboot-envtools-add-OpenMesh-OM5P-ACv2-support.patch b/patches/openwrt/0077-uboot-envtools-add-OpenMesh-OM5P-ACv2-support.patch deleted file mode 100644 index dd61c6fb..00000000 --- a/patches/openwrt/0077-uboot-envtools-add-OpenMesh-OM5P-ACv2-support.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:28 +0000 -Subject: uboot-envtools: add OpenMesh OM5P-ACv2 support - -Signed-off-by: Sven Eckelmann - -Backport of r49153 - -Forwarded: https://patchwork.ozlabs.org/patch/624203/ - -diff --git a/package/boot/uboot-envtools/files/ar71xx b/package/boot/uboot-envtools/files/ar71xx -index 657b25f..9071c11 100644 ---- a/package/boot/uboot-envtools/files/ar71xx -+++ b/package/boot/uboot-envtools/files/ar71xx -@@ -29,6 +29,7 @@ mr900v2 | \ - nbg6716 | \ - om5p-an | \ - om5p-ac | \ -+om5p-acv2 | \ - om5p | \ - tube2h | \ - wndr3700) diff --git a/patches/openwrt/0078-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch b/patches/openwrt/0078-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch deleted file mode 100644 index 90b634ce..00000000 --- a/patches/openwrt/0078-ar71xx-extract-ath10k-wifi-board.bin-for-the-OpenMes.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:31 +0000 -Subject: ar71xx: extract ath10k wifi board.bin for the OpenMesh OM5P-ACv2 board - -Signed-off-by: Sven Eckelmann - -Backport of r49154 - -Forwarded: https://patchwork.ozlabs.org/patch/624204/ - -diff --git a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -index c1f4b85..d925a85 100644 ---- a/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -+++ b/target/linux/ar71xx/base-files/etc/hotplug.d/firmware/11-ath10k-caldata -@@ -71,7 +71,8 @@ case "$FIRMWARE" in - ath10kcal_extract "caldata" 20480 2116 - ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +1) - ;; -- mr1750) -+ mr1750 | \ -+ om5p-acv2) - ath10kcal_extract "ART" 20480 2116 - ath10kcal_patch_mac $(macaddr_add $(cat /sys/class/net/eth0/address) +16) - ;; diff --git a/patches/openwrt/0079-ar71xx-add-OM5P-ACv2-to-the-OM5P-AC-profile.patch b/patches/openwrt/0079-ar71xx-add-OM5P-ACv2-to-the-OM5P-AC-profile.patch deleted file mode 100644 index d98a115f..00000000 --- a/patches/openwrt/0079-ar71xx-add-OM5P-ACv2-to-the-OM5P-AC-profile.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Sven Eckelmann -Date: Sat, 9 Apr 2016 10:26:34 +0000 -Subject: ar71xx: add OM5P-ACv2 to the OM5P-AC profile - -Signed-off-by: Sven Eckelmann - -Backport of r49155 - -Forwarded: https://patchwork.ozlabs.org/patch/624205/ - -diff --git a/target/linux/ar71xx/generic/profiles/openmesh.mk b/target/linux/ar71xx/generic/profiles/openmesh.mk -index 64aaa24..c0919ed 100644 ---- a/target/linux/ar71xx/generic/profiles/openmesh.mk -+++ b/target/linux/ar71xx/generic/profiles/openmesh.mk -@@ -28,12 +28,12 @@ endef - $(eval $(call Profile,OM5P)) - - define Profile/OM5PAC -- NAME:=OpenMesh OM5P-AC -+ NAME:=OpenMesh OM5P-AC/OM5P-ACv2 - PACKAGES:=kmod-ath9k kmod-ath10k om-watchdog ath10k-firmware-qca988x - endef - - define Profile/OM5PAC/Description -- Package set optimized for the OpenMesh OM5P-AC. -+ Package set optimized for the OpenMesh OM5P-AC/OM5P-ACv2. - endef - - $(eval $(call Profile,OM5PAC)) diff --git a/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch b/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch deleted file mode 100644 index 8a01351f..00000000 --- a/patches/packages/luci/0001-fvalue.html-add-label-that-can-be-styled.patch +++ /dev/null @@ -1,14 +0,0 @@ -From: Nils Schneider -Date: Sat, 9 Aug 2014 09:33:21 +0200 -Subject: fvalue.html: add label that can be styled - -diff --git a/modules/luci-base/luasrc/view/cbi/fvalue.htm b/modules/luci-base/luasrc/view/cbi/fvalue.htm -index a1e0808..a324ab2 100644 ---- a/modules/luci-base/luasrc/view/cbi/fvalue.htm -+++ b/modules/luci-base/luasrc/view/cbi/fvalue.htm -@@ -6,4 +6,5 @@ - attr("id", cbid) .. attr("name", cbid) .. attr("value", self.enabled or 1) .. - ifattr((self:cfgvalue(section) or self.default) == self.enabled, "checked", "checked") - %> /> -+ > - <%+cbi/valuefooter%> diff --git a/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch b/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch deleted file mode 100644 index 745e6cef..00000000 --- a/patches/packages/luci/0002-modules-base-dispatcher-set-default-language-if-none-provided-by-the-browser-matches.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Matthias Schiffer -Date: Thu, 19 Mar 2015 18:44:52 +0100 -Subject: modules/base: dispatcher: set default language if none provided by the browser matches - -diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua -index 8b8d1fa..27f9a15 100644 ---- a/modules/luci-base/luasrc/dispatcher.lua -+++ b/modules/luci-base/luasrc/dispatcher.lua -@@ -182,6 +182,7 @@ function dispatch(request) - assert(conf.main, - "/etc/config/luci seems to be corrupt, unable to find section 'main'") - -+ local i18n = require "luci.i18n" - local lang = conf.main.lang or "auto" - if lang == "auto" then - local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or "" -@@ -193,7 +194,10 @@ function dispatch(request) - end - end - end -- require "luci.i18n".setlanguage(lang) -+ if lang == "auto" then -+ lang = i18n.default -+ end -+ i18n.setlanguage(lang) - - local c = ctx.tree - local stat diff --git a/patches/packages/luci/0003-luci-lib-jsonc-Ignore-non-string-or-number-keys-in-tables.patch b/patches/packages/luci/0003-luci-lib-jsonc-Ignore-non-string-or-number-keys-in-tables.patch deleted file mode 100644 index 584a2fab..00000000 --- a/patches/packages/luci/0003-luci-lib-jsonc-Ignore-non-string-or-number-keys-in-tables.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Jan-Philipp Litza -Date: Sun, 30 Aug 2015 15:42:52 +0200 -Subject: luci-lib-jsonc: Ignore non-string-or-number keys in tables - -Previously, the following caused a segmentation fault: - - json.stringify({[{}] = true}) - -This was caused by lua_tostring() returning NULL for anything but -strings and numbers, letting json_object_object_add crash. - -This patch makes jsonc ignore all keys which have no string -representation altogether. - -Signed-off-by: Jan-Philipp Litza - -diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c -index 49cb21f..827fde8 100644 ---- a/libs/luci-lib-jsonc/src/jsonc.c -+++ b/libs/luci-lib-jsonc/src/jsonc.c -@@ -286,8 +286,9 @@ static struct json_object * _lua_to_json(lua_State *L, int index) - lua_pushvalue(L, -2); - key = lua_tostring(L, -1); - -- json_object_object_add(obj, key, -- _lua_to_json(L, lua_gettop(L) - 1)); -+ if (key) -+ json_object_object_add(obj, key, -+ _lua_to_json(L, lua_gettop(L) - 1)); - - lua_pop(L, 2); - } diff --git a/patches/packages/luci/0004-luci-lib-jsonc-allow-encoding-empty-lists.patch b/patches/packages/luci/0004-luci-lib-jsonc-allow-encoding-empty-lists.patch deleted file mode 100644 index 8d6b6842..00000000 --- a/patches/packages/luci/0004-luci-lib-jsonc-allow-encoding-empty-lists.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Jan-Philipp Litza -Date: Sun, 30 Aug 2015 15:45:49 +0200 -Subject: luci-lib-jsonc: allow encoding empty lists - -To be consistent with the behavior of luci-lib-json, an empty Lua table -should be encoded to an empty JSON list, not an empty JSON object. - -To still allow encoding empty JSON objects, the usage of anything other -than a number or a string as a key (for example an empty table or a -function) can be used to force encoding as an object: - - json.stringify({}) -- "[]" - json.stringify({[{}] = true}) -- "{}" - -Signed-off-by: Jan-Philipp Litza - -diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c -index 827fde8..971fb12 100644 ---- a/libs/luci-lib-jsonc/src/jsonc.c -+++ b/libs/luci-lib-jsonc/src/jsonc.c -@@ -222,7 +222,7 @@ static int _lua_test_array(lua_State *L, int index) - - out: - lua_pop(L, 2); -- return 0; -+ return -1; - } - - /* check for holes */ -@@ -254,7 +254,7 @@ static struct json_object * _lua_to_json(lua_State *L, int index) - case LUA_TTABLE: - max = _lua_test_array(L, index); - -- if (max > 0) -+ if (max >= 0) - { - obj = json_object_new_array(); - diff --git a/patches/packages/luci/0005-luci-lib-jsonc-Fix-memory-leak-in-stringify.patch b/patches/packages/luci/0005-luci-lib-jsonc-Fix-memory-leak-in-stringify.patch deleted file mode 100644 index 4e21055a..00000000 --- a/patches/packages/luci/0005-luci-lib-jsonc-Fix-memory-leak-in-stringify.patch +++ /dev/null @@ -1,16 +0,0 @@ -From: Jan-Philipp Litza -Date: Mon, 31 Aug 2015 19:52:36 +0200 -Subject: luci-lib-jsonc: Fix memory leak in stringify() - -diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c -index 971fb12..b857c97 100644 ---- a/libs/luci-lib-jsonc/src/jsonc.c -+++ b/libs/luci-lib-jsonc/src/jsonc.c -@@ -106,6 +106,7 @@ static int json_stringify(lua_State *L) - flags |= JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED; - - lua_pushstring(L, json_object_to_json_string_ext(obj, flags)); -+ json_object_put(obj); - return 1; - } - diff --git a/patches/packages/luci/0006-luci-lib-jsonc-Add-ltn12-compatible-sink-factory.patch b/patches/packages/luci/0006-luci-lib-jsonc-Add-ltn12-compatible-sink-factory.patch deleted file mode 100644 index 34c51c17..00000000 --- a/patches/packages/luci/0006-luci-lib-jsonc-Add-ltn12-compatible-sink-factory.patch +++ /dev/null @@ -1,133 +0,0 @@ -From: Jan-Philipp Litza -Date: Tue, 1 Sep 2015 16:17:23 +0200 -Subject: luci-lib-jsonc: Add ltn12-compatible sink factory - -To use the luci-lib-jsonc parser as sink for an ltn12 pump (for example -from stdin), the following code will now do: - - require 'luci.ltn12' - require 'luci.jsonc' - - local parser = luci.jsonc.new() - luci.ltn12.pump.all(luci.ltn12.source.file(io.input()), parser:sink()) - print(parser:get()) - -Signed-off-by: Jan-Philipp Litza - -diff --git a/libs/luci-lib-jsonc/src/jsonc.c b/libs/luci-lib-jsonc/src/jsonc.c -index b857c97..ef11101 100644 ---- a/libs/luci-lib-jsonc/src/jsonc.c -+++ b/libs/luci-lib-jsonc/src/jsonc.c -@@ -328,6 +328,76 @@ static int json_parse_set(lua_State *L) - return 0; - } - -+static int json_parse_sink_closure(lua_State *L) -+{ -+ bool finished = lua_toboolean(L, lua_upvalueindex(2)); -+ if (lua_isnil(L, 1)) -+ { -+ // no more data available -+ if (finished) -+ { -+ // we were finished parsing -+ lua_pushboolean(L, true); -+ return 1; -+ } -+ else -+ { -+ lua_pushnil(L); -+ lua_pushstring(L, "Incomplete JSON data"); -+ return 2; -+ } -+ } -+ else -+ { -+ if (finished) -+ { -+ lua_pushnil(L); -+ lua_pushstring(L, "Unexpected data after complete JSON object"); -+ return 2; -+ } -+ else -+ { -+ // luci.jsonc.parser.chunk() -+ lua_pushcfunction(L, json_parse_chunk); -+ // parser object from closure -+ lua_pushvalue(L, lua_upvalueindex(1)); -+ // chunk -+ lua_pushvalue(L, 1); -+ lua_call(L, 2, 2); -+ -+ if (lua_isnil(L, -2)) -+ { -+ // an error occurred, leave (nil, errmsg) on the stack and return it -+ return 2; -+ } -+ else if (lua_toboolean(L, -2)) -+ { -+ // finished reading, set finished=true and return nil to prevent further input -+ lua_pop(L, 2); -+ lua_pushboolean(L, true); -+ lua_replace(L, lua_upvalueindex(2)); -+ lua_pushnil(L); -+ return 1; -+ } -+ else -+ { -+ // not finished reading, return true -+ lua_pop(L, 2); -+ lua_pushboolean(L, true); -+ return 1; -+ } -+ } -+ } -+} -+ -+static int json_parse_sink(lua_State *L) -+{ -+ luaL_checkudata(L, 1, LUCI_JSONC_PARSER); -+ lua_pushboolean(L, false); -+ lua_pushcclosure(L, json_parse_sink_closure, 2); -+ return 1; -+} -+ - static int json_tostring(lua_State *L) - { - struct json_state *s = luaL_checkudata(L, 1, LUCI_JSONC_PARSER); -@@ -367,6 +437,7 @@ static const luaL_reg jsonc_parser_methods[] = { - { "parse", json_parse_chunk }, - { "get", json_parse_get }, - { "set", json_parse_set }, -+ { "sink", json_parse_sink }, - { "stringify", json_tostring }, - - { "__gc", json_gc }, -diff --git a/libs/luci-lib-jsonc/src/jsonc.luadoc b/libs/luci-lib-jsonc/src/jsonc.luadoc -index 2ee9ceb..720b17d 100644 ---- a/libs/luci-lib-jsonc/src/jsonc.luadoc -+++ b/libs/luci-lib-jsonc/src/jsonc.luadoc -@@ -121,10 +121,22 @@ parser:set({ "some", "data" })` - ]] - - ---[[ --Serialize current parser state as JSON. -+Generate an ltn12-compatible sink. - - @class function - @sort 4 -+@name parser.sink -+@return Returns a function that can be used as an ltn12 sink. -+@usage `parser = luci.jsonc.new() -+ltn12.pump.all(ltn12.source.file(io.input()), parser:sink()) -+print(parser:get())` -+]] -+ -+---[[ -+Serialize current parser state as JSON. -+ -+@class function -+@sort 5 - @name parser.stringify - @param pretty A boolean value indicating whether the resulting JSON should be pretty printed. - @return Returns the serialized JSON data of this parser instance. diff --git a/patches/packages/luci/0007-model.uci-add-add_to_set-remove_from_set.patch b/patches/packages/luci/0007-model.uci-add-add_to_set-remove_from_set.patch deleted file mode 100644 index 6c998311..00000000 --- a/patches/packages/luci/0007-model.uci-add-add_to_set-remove_from_set.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Nils Schneider -Date: Mon, 17 Aug 2015 20:39:58 +0200 -Subject: model.uci: add add_to_set / remove_from_set - -Adds two functions to simplify working with UCI lists: - -- add_to_set, which ensures a given value will be present in a list, and -- remove_from_set, which removes a value from list. - -I've called these methods "set" because they treat the list as a set, -i.e. duplicated values will be removed. Also, order is not preserved. - -Signed-off-by: Nils Schneider - -diff --git a/modules/luci-base/luasrc/model/uci.lua b/modules/luci-base/luasrc/model/uci.lua -index 1659137..d35b9d7 100644 ---- a/modules/luci-base/luasrc/model/uci.lua -+++ b/modules/luci-base/luasrc/model/uci.lua -@@ -9,7 +9,7 @@ local table = require "table" - - local setmetatable, rawget, rawset = setmetatable, rawget, rawset - local require, getmetatable = require, getmetatable --local error, pairs, ipairs = error, pairs, ipairs -+local error, pairs, ipairs, next = error, pairs, ipairs, next - local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack - - -- The typical workflow for UCI is: Get a cursor instance from the -@@ -147,6 +147,40 @@ function Cursor.set_list(self, config, section, option, value) - return false - end - -+function Cursor.add_to_set(self, config, section, option, value, remove) -+ local list = self:get_list(config, section, option) -+ -+ if not list then -+ return false -+ end -+ -+ local set = {} -+ for _, l in ipairs(list) do -+ set[l] = true -+ end -+ -+ if remove then -+ set[value] = nil -+ else -+ set[value] = true -+ end -+ -+ list = {} -+ for k, _ in pairs(set) do -+ table.insert(list, k) -+ end -+ -+ if next(list) == nil then -+ return self:delete(config, section, option) -+ else -+ return self:set(config, section, option, list) -+ end -+end -+ -+function Cursor.remove_from_set(self, config, section, option, value) -+ self:add_to_set(config, section, option, value, true) -+end -+ - -- Return a list of initscripts affected by configuration changes. - function Cursor._affected(self, configlist) - configlist = type(configlist) == "table" and configlist or {configlist} -diff --git a/modules/luci-base/luasrc/model/uci.luadoc b/modules/luci-base/luasrc/model/uci.luadoc -index 1c20866..281bdb2 100644 ---- a/modules/luci-base/luasrc/model/uci.luadoc -+++ b/modules/luci-base/luasrc/model/uci.luadoc -@@ -116,6 +116,30 @@ Set given values as list. - ]] - - ---[[ -+Add a given value to a list of unique values. -+ -+@class function -+@name Cursor.add_to_set -+@param config UCI config -+@param section UCI section name -+@param option UCI option -+@param value UCI value -+@return Boolean whether operation succeeded -+]] -+ -+---[[ -+Remove a given value from a list of unique values. -+ -+@class function -+@name Cursor.add_to_set -+@param config UCI config -+@param section UCI section name -+@param option UCI option -+@param value UCI value -+@return Boolean whether operation succeeded -+]] -+ -+---[[ - Create a sub-state of this cursor. The sub-state is tied to the parent - - curser, means it the parent unloads or loads configs, the sub state will diff --git a/patches/packages/luci/0008-Move-rpcd-dependency-from-luci-base-to-luci-mode-rpc.patch b/patches/packages/luci/0008-Move-rpcd-dependency-from-luci-base-to-luci-mode-rpc.patch deleted file mode 100644 index ceacdf5a..00000000 --- a/patches/packages/luci/0008-Move-rpcd-dependency-from-luci-base-to-luci-mode-rpc.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 6 Sep 2015 01:27:06 +0200 -Subject: Move rpcd dependency from luci-base to luci-mode-rpc - -LuCI's authentication won't work without rpcd, but we aren't using the -authentication anyways. Users who need it can just install rpcd explicitly. - -diff --git a/modules/luci-base/Makefile b/modules/luci-base/Makefile -index 54506b0..4457034 100644 ---- a/modules/luci-base/Makefile -+++ b/modules/luci-base/Makefile -@@ -12,7 +12,7 @@ LUCI_TYPE:=mod - LUCI_BASENAME:=base - - LUCI_TITLE:=LuCI core libraries --LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua -+LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +libubus-lua - - PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2 - PKG_SOURCE_URL:=https://luasrcdiet.googlecode.com/files -diff --git a/modules/luci-mod-rpc/Makefile b/modules/luci-mod-rpc/Makefile -index e64c86c..5f64a14 100644 ---- a/modules/luci-mod-rpc/Makefile -+++ b/modules/luci-mod-rpc/Makefile -@@ -7,7 +7,7 @@ - include $(TOPDIR)/rules.mk - - LUCI_TITLE:=LuCI RPC - JSON-RPC API --LUCI_DEPENDS:=+luci-lib-json -+LUCI_DEPENDS:=+luci-lib-json +rpcd - - include ../../luci.mk - diff --git a/patches/packages/openwrt/0001-node-add-python-host-to-HOST_BUILD_DEPENDS-as-well.patch b/patches/packages/openwrt/0001-node-add-python-host-to-HOST_BUILD_DEPENDS-as-well.patch deleted file mode 100644 index f0c746aa..00000000 --- a/patches/packages/openwrt/0001-node-add-python-host-to-HOST_BUILD_DEPENDS-as-well.patch +++ /dev/null @@ -1,18 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 28 Oct 2015 01:10:09 +0100 -Subject: node: add python/host to HOST_BUILD_DEPENDS as well - -Signed-off-by: Matthias Schiffer - -diff --git a/lang/node/Makefile b/lang/node/Makefile -index 65a5390..243c8a5 100644 ---- a/lang/node/Makefile -+++ b/lang/node/Makefile -@@ -14,6 +14,7 @@ PKG_RELEASE:=1 - PKG_SOURCE:=node-$(PKG_VERSION).tar.gz - PKG_SOURCE_URL:=http://nodejs.org/dist/${PKG_VERSION} - -+HOST_BUILD_DEPENDS:=python/host - PKG_BUILD_DEPENDS:=python/host - PKG_INSTALL:=1 - PKG_USE_MIPS16:=0 diff --git a/patches/packages/openwrt/0002-lua-cjson-add-host-build-support.patch b/patches/packages/openwrt/0002-lua-cjson-add-host-build-support.patch deleted file mode 100644 index 08fba881..00000000 --- a/patches/packages/openwrt/0002-lua-cjson-add-host-build-support.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Matthias Schiffer -Date: Wed, 30 Dec 2015 01:00:49 +0100 -Subject: lua-cjson: add host build support - -diff --git a/lang/lua-cjson/Makefile b/lang/lua-cjson/Makefile -index fbdcf17..1adfeb3 100644 ---- a/lang/lua-cjson/Makefile -+++ b/lang/lua-cjson/Makefile -@@ -20,6 +20,7 @@ PKG_MD5SUM:=24f270663e9f6ca8ba2a02cef19f7963 - - PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) - -+include $(INCLUDE_DIR)/host-build.mk - include $(INCLUDE_DIR)/package.mk - include $(INCLUDE_DIR)/cmake.mk - -@@ -39,6 +40,9 @@ endef - CMAKE_OPTIONS += \ - -DUSE_LUA=ON - -+CMAKE_HOST_OPTIONS += \ -+ -DLUA_MATH_LIBRARY=m -+ - define Package/lua-cjson/install - $(INSTALL_DIR) $(1)/usr/lib/lua - $(INSTALL_BIN) $(PKG_BUILD_DIR)/cjson.so $(1)/usr/lib/lua/ -@@ -47,4 +51,5 @@ define Package/lua-cjson/install - $(INSTALL_DATA) $(PKG_BUILD_DIR)/lua/cjson/util.lua $(1)/usr/lib/lua/cjson - endef - -+$(eval $(call HostBuild)) - $(eval $(call BuildPackage,lua-cjson)) diff --git a/patches/packages/openwrt/0003-libuecc-update-to-v7.patch b/patches/packages/openwrt/0003-libuecc-update-to-v7.patch deleted file mode 100644 index 379e0a27..00000000 --- a/patches/packages/openwrt/0003-libuecc-update-to-v7.patch +++ /dev/null @@ -1,34 +0,0 @@ -From: Matthias Schiffer -Date: Sun, 25 Oct 2015 17:11:30 +0100 -Subject: libuecc: update to v7 - -Signed-off-by: Matthias Schiffer - -diff --git a/libs/libuecc/Makefile b/libs/libuecc/Makefile -index 63b6ebe..c1ba53f 100644 ---- a/libs/libuecc/Makefile -+++ b/libs/libuecc/Makefile -@@ -1,5 +1,5 @@ - # --# Copyright (C) 2012-2015 OpenWrt.org -+# Copyright (C) 2012-2016 OpenWrt.org - # - # This is free software, licensed under the GNU General Public License v2. - # See /LICENSE for more information. -@@ -8,13 +8,13 @@ - include $(TOPDIR)/rules.mk - - PKG_NAME:=libuecc --PKG_VERSION:=5 -+PKG_VERSION:=7 - PKG_RELEASE:=1 - - PKG_MAINTAINER:=Matthias Schiffer - PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz --PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/80 --PKG_MD5SUM:=cd03c947931c2f4b0eea0bf45654bd34 -+PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/85 -+PKG_MD5SUM:=5cd543cb8e7bce83a22c07a0579c95a1 - - PKG_LICENSE:=BSD-2-Clause - PKG_LICENSE_FILES:=COPYRIGHT diff --git a/patches/packages/openwrt/0004-fastd-update-to-v18.patch b/patches/packages/openwrt/0004-fastd-update-to-v18.patch deleted file mode 100644 index fd947214..00000000 --- a/patches/packages/openwrt/0004-fastd-update-to-v18.patch +++ /dev/null @@ -1,88 +0,0 @@ -From: Matthias Schiffer -Date: Tue, 29 Mar 2016 00:24:00 +0200 -Subject: fastd: update to v18 - -Signed-off-by: Matthias Schiffer - -diff --git a/net/fastd/Config.in b/net/fastd/Config.in -index 5820b97..3350eb3 100644 ---- a/net/fastd/Config.in -+++ b/net/fastd/Config.in -@@ -74,6 +74,12 @@ config FASTD_ENABLE_MAC_UHASH - default y - - -+config FASTD_WITH_CAPABILITIES -+ bool "Enable POSIX capability support" -+ depends on PACKAGE_fastd -+ default n -+ -+ - config FASTD_WITH_CMDLINE_USER - bool "Include support for setting user/group related options on the command line" - depends on PACKAGE_fastd -diff --git a/net/fastd/Makefile b/net/fastd/Makefile -index 027f549..5c550d8 100644 ---- a/net/fastd/Makefile -+++ b/net/fastd/Makefile -@@ -8,13 +8,13 @@ - include $(TOPDIR)/rules.mk - - PKG_NAME:=fastd --PKG_VERSION:=17 -+PKG_VERSION:=18 - PKG_RELEASE:=1 - - PKG_MAINTAINER:=Matthias Schiffer - PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz --PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/81 --PKG_MD5SUM:=bad4f1948702f418b799578f83a0edb8 -+PKG_SOURCE_URL:=https://projects.universe-factory.net/attachments/download/86 -+PKG_MD5SUM:=e53236d3049f64f7955ad9556da099eb - - PKG_LICENSE:=BSD-2-Clause - PKG_LICENSE_FILES:=COPYRIGHT -@@ -34,6 +34,7 @@ PKG_CONFIG_DEPENDS:=\ - CONFIG_FASTD_ENABLE_CIPHER_SALSA2012 \ - CONFIG_FASTD_ENABLE_MAC_GHASH \ - CONFIG_FASTD_ENABLE_MAC_UHASH \ -+ CONFIG_FASTD_WITH_CAPABILITIES \ - CONFIG_FASTD_WITH_CMDLINE_USER \ - CONFIG_FASTD_WITH_CMDLINE_LOGGING \ - CONFIG_FASTD_WITH_CMDLINE_OPERATION \ -@@ -50,7 +51,7 @@ include $(INCLUDE_DIR)/cmake.mk - define Package/fastd - SECTION:=net - CATEGORY:=Network -- DEPENDS:=+kmod-tun +librt +libpthread +FASTD_WITH_STATUS_SOCKET:libjson-c -+ DEPENDS:=+kmod-tun +librt +libpthread +FASTD_WITH_STATUS_SOCKET:libjson-c +FASTD_WITH_CAPABILITIES:libcap - TITLE:=Fast and Secure Tunneling Daemon - URL:=https://projects.universe-factory.net/projects/fastd - SUBMENU:=VPN -@@ -79,13 +80,13 @@ CMAKE_OPTIONS += \ - -DWITH_CIPHER_SALSA2012:BOOL=FALSE \ - -DWITH_MAC_GHASH:BOOL=FALSE \ - -DWITH_MAC_UHASH:BOOL=FALSE \ -+ -DWITH_CAPABILITIES:BOOL=FALSE \ - -DWITH_CMDLINE_USER:BOOL=FALSE \ - -DWITH_CMDLINE_LOGGING:BOOL=FALSE \ - -DWITH_CMDLINE_OPERATION:BOOL=FALSE \ - -DWITH_CMDLINE_COMMANDS:BOOL=FALSE \ - -DWITH_DYNAMIC_PEERS:BOOL=FALSE \ - -DWITH_STATUS_SOCKET:BOOL=FALSE \ -- -DWITH_CAPABILITIES:BOOL=FALSE \ - -DENABLE_SYSTEMD:BOOL=FALSE \ - -DENABLE_LIBSODIUM:BOOL=FALSE \ - -DENABLE_LTO:BOOL=TRUE -@@ -150,6 +151,11 @@ CMAKE_OPTIONS += -DWITH_MAC_UHASH:BOOL=TRUE - endif - - -+ifeq ($(CONFIG_FASTD_WITH_CAPABILITIES),y) -+CMAKE_OPTIONS += -DWITH_CAPABILITIES:BOOL=TRUE -+endif -+ -+ - ifeq ($(CONFIG_FASTD_WITH_CMDLINE_USER),y) - CMAKE_OPTIONS += -DWITH_CMDLINE_USER:BOOL=TRUE - endif diff --git a/patches/packages/openwrt/0005-node-update-to-v0.12.14.patch b/patches/packages/openwrt/0005-node-update-to-v0.12.14.patch deleted file mode 100644 index 9b03cee4..00000000 --- a/patches/packages/openwrt/0005-node-update-to-v0.12.14.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 9 May 2016 15:57:18 +0200 -Subject: node: update to v0.12.14 - -While we're at it, also enable parallel builds. - -Signed-off-by: Matthias Schiffer - -diff --git a/lang/node/Makefile b/lang/node/Makefile -index 243c8a5..e6fe843 100644 ---- a/lang/node/Makefile -+++ b/lang/node/Makefile -@@ -8,17 +8,21 @@ - include $(TOPDIR)/rules.mk - - PKG_NAME:=node --PKG_VERSION:=v0.12.7 -+PKG_VERSION:=v0.12.14 - PKG_RELEASE:=1 - --PKG_SOURCE:=node-$(PKG_VERSION).tar.gz -+PKG_SOURCE:=node-$(PKG_VERSION).tar.xz - PKG_SOURCE_URL:=http://nodejs.org/dist/${PKG_VERSION} -+PKG_MD5SUM:=27f1a2cf00af32cbfe9401ca4b1a805f - - HOST_BUILD_DEPENDS:=python/host - PKG_BUILD_DEPENDS:=python/host - PKG_INSTALL:=1 - PKG_USE_MIPS16:=0 - -+HOST_BUILD_PARALLEL:=1 -+PKG_BUILD_PARALLEL:=1 -+ - PKG_MAINTAINER:=John Crispin - PKG_LICENSE:= - diff --git a/patches/packages/openwrt/0006-node-fix-undefined-behaviour-leading-to-broken-code-with-GCC-6.patch b/patches/packages/openwrt/0006-node-fix-undefined-behaviour-leading-to-broken-code-with-GCC-6.patch deleted file mode 100644 index ae5162e2..00000000 --- a/patches/packages/openwrt/0006-node-fix-undefined-behaviour-leading-to-broken-code-with-GCC-6.patch +++ /dev/null @@ -1,80 +0,0 @@ -From: Matthias Schiffer -Date: Mon, 9 May 2016 16:21:57 +0200 -Subject: node: fix undefined behaviour leading to broken code with GCC 6 - -Fixes segfaults occuring in the node host build when GCC 6 is used. - -Backport of upstream commit 96198d5bc710a4e3ca49eeeb3b3fa7b8cb61547d. - -Signed-off-by: Matthias Schiffer - -diff --git a/lang/node/patches/004-gcc6-undefined-behaviour.patch b/lang/node/patches/004-gcc6-undefined-behaviour.patch -new file mode 100644 -index 0000000..dbbbcf0 ---- /dev/null -+++ b/lang/node/patches/004-gcc6-undefined-behaviour.patch -@@ -0,0 +1,64 @@ -+diff --git a/deps/v8/src/heap/incremental-marking.cc b/deps/v8/src/heap/incremental-marking.cc -+index c922e83..2ead8be 100644 -+--- a/deps/v8/src/heap/incremental-marking.cc -++++ b/deps/v8/src/heap/incremental-marking.cc -+@@ -379,7 +379,7 @@ void IncrementalMarking::DeactivateIncrementalWriteBarrier() { -+ DeactivateIncrementalWriteBarrierForSpace(heap_->new_space()); -+ -+ LargePage* lop = heap_->lo_space()->first_page(); -+- while (lop->is_valid()) { -++ while (LargePage::IsValid(lop)) { -+ SetOldSpacePageFlags(lop, false, false); -+ lop = lop->next_page(); -+ } -+@@ -414,7 +414,7 @@ void IncrementalMarking::ActivateIncrementalWriteBarrier() { -+ ActivateIncrementalWriteBarrier(heap_->new_space()); -+ -+ LargePage* lop = heap_->lo_space()->first_page(); -+- while (lop->is_valid()) { -++ while (LargePage::IsValid(lop)) { -+ SetOldSpacePageFlags(lop, true, is_compacting_); -+ lop = lop->next_page(); -+ } -+diff --git a/deps/v8/src/heap/spaces-inl.h b/deps/v8/src/heap/spaces-inl.h -+index 56c2bad..1a45096 100644 -+--- a/deps/v8/src/heap/spaces-inl.h -++++ b/deps/v8/src/heap/spaces-inl.h -+@@ -148,7 +148,7 @@ Page* Page::Initialize(Heap* heap, MemoryChunk* chunk, Executability executable, -+ -+ bool PagedSpace::Contains(Address addr) { -+ Page* p = Page::FromAddress(addr); -+- if (!p->is_valid()) return false; -++ if (!Page::IsValid(p)) return false; -+ return p->owner() == this; -+ } -+ -+diff --git a/deps/v8/src/heap/spaces.cc b/deps/v8/src/heap/spaces.cc -+index e197f5a..2fe10eb 100644 -+--- a/deps/v8/src/heap/spaces.cc -++++ b/deps/v8/src/heap/spaces.cc -+@@ -2918,7 +2918,7 @@ LargePage* LargeObjectSpace::FindPage(Address a) { -+ if (e != NULL) { -+ DCHECK(e->value != NULL); -+ LargePage* page = reinterpret_cast(e->value); -+- DCHECK(page->is_valid()); -++ DCHECK(LargePage::IsValid(page)); -+ if (page->Contains(a)) { -+ return page; -+ } -+diff --git a/deps/v8/src/heap/spaces.h b/deps/v8/src/heap/spaces.h -+index 312d75f..1054672 100644 -+--- a/deps/v8/src/heap/spaces.h -++++ b/deps/v8/src/heap/spaces.h -+@@ -283,9 +283,9 @@ class MemoryChunk { -+ // Only works for addresses in pointer spaces, not data or code spaces. -+ static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); -+ -+- Address address() { return reinterpret_cast
(this); } -++ static bool IsValid(MemoryChunk* chunk) { return chunk != nullptr; } -+ -+- bool is_valid() { return address() != NULL; } -++ Address address() { return reinterpret_cast
(this); } -+ -+ MemoryChunk* next_chunk() const { -+ return reinterpret_cast(base::Acquire_Load(&next_chunk_)); diff --git a/patches/packages/routing/0001-alfred-adjust-intervals.patch b/patches/packages/routing/0001-alfred-adjust-intervals.patch index aabb1659..c8d0548a 100644 --- a/patches/packages/routing/0001-alfred-adjust-intervals.patch +++ b/patches/packages/routing/0001-alfred-adjust-intervals.patch @@ -4,13 +4,13 @@ Subject: alfred: adjust intervals diff --git a/alfred/patches/0001-alfred-adjust-intervals.patch b/alfred/patches/0001-alfred-adjust-intervals.patch new file mode 100644 -index 0000000..df70eea +index 0000000000000000000000000000000000000000..a6d1e40ac28fcf803b9129128be744b284529762 --- /dev/null +++ b/alfred/patches/0001-alfred-adjust-intervals.patch @@ -0,0 +1,15 @@ +--- a/alfred.h ++++ b/alfred.h -+@@ -33,10 +33,10 @@ ++@@ -36,10 +36,10 @@ + #include "list.h" + #include "packet.h" + diff --git a/patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch b/patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch deleted file mode 100644 index f6d1646a..00000000 --- a/patches/packages/routing/0002-batman-adv-introduce-no_rebroadcast-option.patch +++ /dev/null @@ -1,221 +0,0 @@ -From: Matthias Schiffer -Date: Thu, 2 Apr 2015 20:24:14 +0200 -Subject: batman-adv: introduce 'no_rebroadcast' option - -diff --git a/batman-adv/files/lib/netifd/proto/batadv.sh b/batman-adv/files/lib/netifd/proto/batadv.sh -index 632a209..01f567f 100644 ---- a/batman-adv/files/lib/netifd/proto/batadv.sh -+++ b/batman-adv/files/lib/netifd/proto/batadv.sh -@@ -6,16 +6,19 @@ init_proto "$@" - - proto_batadv_init_config() { - proto_config_add_string "mesh" -+ proto_config_add_string "mesh_no_rebroadcast" - } - - proto_batadv_setup() { - local config="$1" - local iface="$2" - -- local mesh -- json_get_vars mesh -+ local mesh mesh_no_rebroadcast -+ json_get_vars mesh mesh_no_rebroadcast - - echo "$mesh" > "/sys/class/net/$iface/batman_adv/mesh_iface" -+ [ -n "$mesh_no_rebroadcast" ] && echo "$mesh_no_rebroadcast" > "/sys/class/net/$iface/batman_adv/no_rebroadcast" -+ - proto_init_update "$iface" 1 - proto_send_update "$config" - } -diff --git a/batman-adv/patches/1001-batman-adv-introduce-no_rebroadcast-option.patch b/batman-adv/patches/1001-batman-adv-introduce-no_rebroadcast-option.patch -new file mode 100644 -index 0000000..3324102 ---- /dev/null -+++ b/batman-adv/patches/1001-batman-adv-introduce-no_rebroadcast-option.patch -@@ -0,0 +1,185 @@ -+From bb9feeed3b49a55034cce90be996b11cd095b1ce Mon Sep 17 00:00:00 2001 -+Message-Id: -+From: =?UTF-8?q?Linus=20L=C3=BCssing?= -+Date: Tue, 24 Sep 2013 04:36:27 +0200 -+Subject: [PATCH 1/2] batman-adv: introduce 'no_rebroadcast' option -+MIME-Version: 1.0 -+Content-Type: text/plain; charset=UTF-8 -+Content-Transfer-Encoding: 8bit -+ -+This patch introduces a new sysfs option named "no_rebroadcast" on -+a per hard interface basis. It allows manually enabling a split-horizon -+like behaviour for the layer 2 multicast payload frames, in that -+incoming multicast payload frames on such a hard interface are only -+being rebroadcasted on all interfaces except the incoming one instead -+of being rebroadcasted on all interfaces. -+ -+Such an option should only be enabled if you are certain that these -+rebroadcasts are unnecessary. This is usually the case for instance -+for point-to-point wifi longshots or wired links. -+ -+This option can especially safe a significant amount of upload overhead -+if the neighbourhood on a link is rather large, for instance in some -+transitive, symmetric VPN configurations. -+ -+Using this option wrongly will break your mesh network, use this option -+wisely and at your own risk! -+ -+Signed-off-by: Linus Lüssing -+--- -+ .../ABI/testing/sysfs-class-net-batman-adv | 10 ++++ -+ net/batman-adv/hard-interface.c | 2 + -+ net/batman-adv/send.c | 4 ++ -+ net/batman-adv/sysfs.c | 59 ++++++++++++++++++++++ -+ net/batman-adv/types.h | 1 + -+ 5 files changed, 76 insertions(+) -+ -+diff --git a/Documentation/ABI/testing/sysfs-class-net-batman-adv b/Documentation/ABI/testing/sysfs-class-net-batman-adv -+index 7f34a95..cf7fe00 100644 -+--- a/Documentation/ABI/testing/sysfs-class-net-batman-adv -++++ b/Documentation/ABI/testing/sysfs-class-net-batman-adv -+@@ -13,3 +13,13 @@ Description: -+ displays the batman mesh interface this -+ currently is associated with. -+ -++What: /sys/class/net//batman-adv/no_rebroadcast -++Date: Sep 2013 -++Contact: Linus Lüssing -++Description: -++ With this option set incoming multicast payload frames on -++ are not being rebroadcasted on again. This -++ option should be set on links which are known to be transitive -++ and symmetric only, for instance point-to-point wifi longshots -++ or wired links. Using this option wrongly is going to -++ break your mesh network, use at your own risk! -+diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c -+index aea4d06..66a703d 100644 -+--- a/net/batman-adv/hard-interface.c -++++ b/net/batman-adv/hard-interface.c -+@@ -657,6 +657,8 @@ batadv_hardif_add_interface(struct net_device *net_dev) -+ /* extra reference for return */ -+ atomic_set(&hard_iface->refcount, 2); -+ -++ atomic_set(&hard_iface->no_rebroadcast, 0); -++ -+ batadv_check_known_mac_addr(hard_iface->net_dev); -+ list_add_tail_rcu(&hard_iface->list, &batadv_hardif_list); -+ -+diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c -+index c188f46..145f7cb 100644 -+--- a/net/batman-adv/send.c -++++ b/net/batman-adv/send.c -+@@ -535,6 +535,10 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work) -+ if (forw_packet->num_packets >= hard_iface->num_bcasts) -+ continue; -+ -++ if (atomic_read(&hard_iface->no_rebroadcast) && -++ forw_packet->skb->dev == hard_iface->net_dev) -++ continue; -++ -+ /* send a copy of the saved skb */ -+ skb1 = skb_clone(forw_packet->skb, GFP_ATOMIC); -+ if (skb1) -+diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c -+index f38d7b7..600633c 100644 -+--- a/net/batman-adv/sysfs.c -++++ b/net/batman-adv/sysfs.c -+@@ -131,6 +131,17 @@ struct batadv_attribute batadv_attr_vlan_##_name = { \ -+ .store = _store, \ -+ } -+ -++/* Use this, if you have customized show and store functions -++ * for hard interface attrs -++ */ -++#define BATADV_ATTR_HIF(_name, _mode, _show, _store) \ -++struct batadv_attribute batadv_attr_hif_##_name = { \ -++ .attr = {.name = __stringify(_name), \ -++ .mode = _mode }, \ -++ .show = _show, \ -++ .store = _store, \ -++}; -++ -+ /* Use this, if you have customized show and store functions */ -+ #define BATADV_ATTR(_name, _mode, _show, _store) \ -+ struct batadv_attribute batadv_attr_##_name = { \ -+@@ -241,6 +252,52 @@ ssize_t batadv_show_vlan_##_name(struct kobject *kobj, \ -+ static BATADV_ATTR_VLAN(_name, _mode, batadv_show_vlan_##_name, \ -+ batadv_store_vlan_##_name) -+ -++#define BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func) \ -++ssize_t batadv_store_hif_##_name(struct kobject *kobj, \ -++ struct attribute *attr, char *buff, \ -++ size_t count) \ -++{ \ -++ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ -++ struct batadv_hard_iface *hard_iface; \ -++ size_t res; \ -++ \ -++ hard_iface = batadv_hardif_get_by_netdev(net_dev); \ -++ if (!hard_iface) \ -++ return 0; \ -++ \ -++ res = __batadv_store_bool_attr(buff, count, _post_func, \ -++ attr, &hard_iface->_name, \ -++ hard_iface->soft_iface); \ -++ batadv_hardif_free_ref(hard_iface); \ -++ return res; \ -++} -++ -++#define BATADV_ATTR_HIF_SHOW_BOOL(_name) \ -++ssize_t batadv_show_hif_##_name(struct kobject *kobj, \ -++ struct attribute *attr, char *buff) \ -++{ \ -++ struct net_device *net_dev = batadv_kobj_to_netdev(kobj); \ -++ struct batadv_hard_iface *hard_iface; \ -++ size_t res; \ -++ \ -++ hard_iface = batadv_hardif_get_by_netdev(net_dev); \ -++ if (!hard_iface) \ -++ return 0; \ -++ \ -++ res = sprintf(buff, "%s\n", \ -++ atomic_read(&hard_iface->_name) == 0 ? \ -++ "disabled" : "enabled"); \ -++ batadv_hardif_free_ref(hard_iface); \ -++ return res; \ -++} -++ -++/* Use this, if you are going to turn a [name] in the vlan struct on or off */ -++#define BATADV_ATTR_HIF_BOOL(_name, _mode, _post_func) \ -++ static BATADV_ATTR_HIF_STORE_BOOL(_name, _post_func) \ -++ static BATADV_ATTR_HIF_SHOW_BOOL(_name) \ -++ static BATADV_ATTR_HIF(_name, _mode, batadv_show_hif_##_name, \ -++ batadv_store_hif_##_name) -++ -+ static int batadv_store_bool_attr(char *buff, size_t count, -+ struct net_device *net_dev, -+ const char *attr_name, atomic_t *attr, -+@@ -870,10 +927,12 @@ static ssize_t batadv_show_iface_status(struct kobject *kobj, -+ static BATADV_ATTR(mesh_iface, S_IRUGO | S_IWUSR, batadv_show_mesh_iface, -+ batadv_store_mesh_iface); -+ static BATADV_ATTR(iface_status, S_IRUGO, batadv_show_iface_status, NULL); -++BATADV_ATTR_HIF_BOOL(no_rebroadcast, S_IRUGO | S_IWUSR, NULL); -+ -+ static struct batadv_attribute *batadv_batman_attrs[] = { -+ &batadv_attr_mesh_iface, -+ &batadv_attr_iface_status, -++ &batadv_attr_hif_no_rebroadcast, -+ NULL, -+ }; -+ -+diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h -+index 5e8c8df..913f104 100644 -+--- a/net/batman-adv/types.h -++++ b/net/batman-adv/types.h -+@@ -120,6 +120,7 @@ struct batadv_hard_iface { -+ struct hlist_head neigh_list; -+ /* neigh_list_lock protects: neigh_list */ -+ spinlock_t neigh_list_lock; -++ atomic_t no_rebroadcast; -+ }; -+ -+ /** -+-- -+2.7.0 -+ diff --git a/patches/packages/routing/0003-batman-adv-decrease-maximum-fragment-size.patch b/patches/packages/routing/0003-batman-adv-decrease-maximum-fragment-size.patch deleted file mode 100644 index a53bef28..00000000 --- a/patches/packages/routing/0003-batman-adv-decrease-maximum-fragment-size.patch +++ /dev/null @@ -1,38 +0,0 @@ -From: Matthias Schiffer -Date: Thu, 6 Aug 2015 21:29:47 +0200 -Subject: batman-adv: decrease maximum fragment size - -diff --git a/batman-adv/patches/1002-batman-adv-decrease-maximum-fragment-size.patch b/batman-adv/patches/1002-batman-adv-decrease-maximum-fragment-size.patch -new file mode 100644 -index 0000000..56311ea ---- /dev/null -+++ b/batman-adv/patches/1002-batman-adv-decrease-maximum-fragment-size.patch -@@ -0,0 +1,28 @@ -+From 3de3f885d441f9059a4d4c88504845851667a68c Mon Sep 17 00:00:00 2001 -+Message-Id: <3de3f885d441f9059a4d4c88504845851667a68c.1454958586.git.mschiffer@universe-factory.net> -+In-Reply-To: -+References: -+From: Matthias Schiffer -+Date: Thu, 6 Aug 2015 22:27:01 +0200 -+Subject: [PATCH 2/2] batman-adv: decrease maximum fragment size -+ -+--- -+ net/batman-adv/main.h | 2 +- -+ 1 file changed, 1 insertion(+), 1 deletion(-) -+ -+diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h -+index 34f56ef..81a7cc2 100644 -+--- a/net/batman-adv/main.h -++++ b/net/batman-adv/main.h -+@@ -147,7 +147,7 @@ enum batadv_uev_type { -+ /* Maximum number of fragments for one packet */ -+ #define BATADV_FRAG_MAX_FRAGMENTS 16 -+ /* Maxumim size of each fragment */ -+-#define BATADV_FRAG_MAX_FRAG_SIZE 1400 -++#define BATADV_FRAG_MAX_FRAG_SIZE 1280 -+ /* Time to keep fragments while waiting for rest of the fragments */ -+ #define BATADV_FRAG_TIMEOUT 10000 -+ -+-- -+2.7.0 -+ diff --git a/scripts/check_site.lua b/scripts/check_site.lua new file mode 100644 index 00000000..41944cb0 --- /dev/null +++ b/scripts/check_site.lua @@ -0,0 +1,330 @@ +local cjson = require 'cjson' + +local function config_error(src, ...) + error(src .. ' error: ' .. string.format(...), 0) +end + + +local has_domains = (os.execute('ls -d "$IPKG_INSTROOT"/lib/gluon/domains/ >/dev/null 2>&1') == 0) + + +local function load_json(filename) + local f = assert(io.open(filename)) + local json = cjson.decode(f:read('*a')) + f:close() + return json +end + + +local function get_domains() + local domains = {} + local dirs = io.popen("find \"$IPKG_INSTROOT\"/lib/gluon/domains/ -name '*.json'") + for filename in dirs:lines() do + local name = string.match(filename, '([^/]+).json$') + domains[name] = load_json(filename) + end + dirs:close() + + if not next(domains) then + config_error('site', 'no domain configurations found') + end + + return domains +end + +local site, domain_code, domain, conf + + +local function merge(a, b) + local function is_array(t) + local n = 0 + for k, v in pairs(t) do + n = n + 1 + end + return n == #t + end + + if not b then return a end + if type(a) ~= type(b) then return b end + if type(b) ~= 'table' then return b end + if not next(b) then return a end + if is_array(a) ~= is_array(b) then return b end + + local m = {} + for k, v in pairs(a) do + m[k] = v + end + for k, v in pairs(b) do + m[k] = merge(m[k], v) + end + + return m +end + + +local function path_to_string(path) + return table.concat(path, '.') +end + +local function array_to_string(array) + return '[' .. table.concat(array, ', ') .. ']' +end + +function table_keys(tbl) + local keys = {} + for k, _ in pairs(tbl) do + keys[#keys + 1] = k + end + return keys +end + + +local loadpath + +local function site_src() + return 'site.conf' +end + +local function domain_src() + return 'domains/' .. domain_code .. '.conf' +end + +local function var_error(path, val, msg) + if type(val) == 'string' then + val = string.format('%q', val) + end + + local src + + if has_domains then + if loadpath(nil, domain, unpack(path)) ~= nil then + src = domain_src() + elseif loadpath(nil, site, unpack(path)) ~= nil then + src = site_src() + else + src = site_src() .. ' / ' .. domain_src() + end + else + src = site_src() + end + + local found = 'unset' + if val ~= nil then + found = string.format('%s (a %s value)', tostring(val), type(val)) + end + + config_error(src, 'expected %s to %s, but it is %s', path_to_string(path), msg, found) +end + + +function in_site(path) + if has_domains and loadpath(nil, domain, unpack(path)) ~= nil then + config_error(domain_src(), '%s is allowed in site configuration only', path_to_string(path)) + end + + return path +end + +function in_domain(path) + if has_domains and loadpath(nil, site, unpack(path)) ~= nil then + config_error(site_src(), '%s is allowed in domain configuration only', path_to_string(path)) + end + + return path +end + +function this_domain() + return domain_code +end + + +function extend(path, c) + if not path then return nil end + + local p = {unpack(path)} + + for _, e in ipairs(c) do + p[#p+1] = e + end + return p +end + +function loadpath(path, base, c, ...) + if not c or base == nil then + return base + end + + if type(base) ~= 'table' then + if path then + var_error(path, base, 'be a table') + else + return nil + end + end + + return loadpath(extend(path, {c}), base[c], ...) +end + +local function loadvar(path) + return loadpath({}, conf, unpack(path)) +end + +local function check_type(t) + return function(val) + return type(val) == t + end +end + +local function check_one_of(array) + return function(val) + for _, v in ipairs(array) do + if v == val then + return true + end + end + return false + end +end + + +function alternatives(...) + local errs = {'All of the following alternatives have failed:'} + for i, f in ipairs({...}) do + local ok, err = pcall(f) + if ok then + return + end + errs[#errs+1] = string.format('%i) %s', i, err) + end + + error(table.concat(errs, '\n '), 0) +end + + +function need(path, check, required, msg) + local val = loadvar(path) + if required == false and val == nil then + return nil + end + + if not check(val) then + var_error(path, val, msg) + end + + return val +end + +local function need_type(path, type, required, msg) + return need(path, check_type(type), required, msg) +end + + +function need_alphanumeric_key(path) + local val = path[#path] + -- We don't use character classes like %w here to be independent of the locale + if type(val) ~= 'string' or not val:match('^[0-9a-zA-Z_]+$') then + var_error(path, val, 'have a string key using only alphanumeric characters and underscores') + end +end + + +function need_string(path, required) + return need_type(path, 'string', required, 'be a string') +end + +function need_string_match(path, pat, required) + local val = need_string(path, required) + if not val then + return nil + end + + if not val:match(pat) then + var_error(path, val, "match pattern '" .. pat .. "'") + end + + return val +end + +function need_number(path, required) + return need_type(path, 'number', required, 'be a number') +end + +function need_boolean(path, required) + return need_type(path, 'boolean', required, 'be a boolean') +end + +function need_array(path, subcheck, required) + local val = need_type(path, 'table', required, 'be an array') + if not val then + return nil + end + + if subcheck then + for i = 1, #val do + subcheck(extend(path, {i})) + end + end + + return val +end + +function need_table(path, subcheck, required) + local val = need_type(path, 'table', required, 'be a table') + if not val then + return nil + end + + if subcheck then + for k, _ in pairs(val) do + subcheck(extend(path, {k})) + end + end + + return val +end + +function need_value(path, value, required) + return need(path, function(v) + return v == value + end, required, 'be ' .. tostring(value)) +end + +function need_one_of(path, array, required) + return need(path, check_one_of(array), required, 'be one of the given array ' .. array_to_string(array)) +end + +function need_string_array(path, required) + return need_array(path, need_string, required) +end + +function need_string_array_match(path, pat, required) + return need_array(path, function(e) need_string_match(e, pat) end, required) +end + +function need_array_of(path, array, required) + return need_array(path, function(e) need_one_of(e, array) end, required) +end + + +local check = assert(loadfile()) + +site = load_json(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/site.json') + +local ok, err = pcall(function() + if has_domains then + for k, v in pairs(get_domains()) do + domain_code = k + domain = v + conf = merge(site, domain) + check() + end + else + conf = site + check() + end +end) + +if not ok then + io.stderr:write('*** ', err, '\n') + os.exit(1) +end diff --git a/scripts/check_site.sh b/scripts/check_site.sh deleted file mode 100755 index 0ca30316..00000000 --- a/scripts/check_site.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -SITE_CONFIG_LUA=scripts/site_config.lua -CHECK_SITE_LIB=scripts/check_site_lib.lua - -"$GLUONDIR"/openwrt/staging_dir/host/bin/lua -e "site = dofile(os.getenv('GLUONDIR') .. '/${SITE_CONFIG_LUA}'); dofile(os.getenv('GLUONDIR') .. '/${CHECK_SITE_LIB}'); dofile()" diff --git a/scripts/check_site_lib.lua b/scripts/check_site_lib.lua deleted file mode 100644 index 766b94a9..00000000 --- a/scripts/check_site_lib.lua +++ /dev/null @@ -1,105 +0,0 @@ -local function loadvar(varname) - local ok, val = pcall(assert(loadstring('return site.' .. varname))) - if ok then - return val - else - return nil - end -end - -local function assert_type(var, t, msg) - assert(type(var) == t, msg) -end - - -function assert_uci_name(var) - -- We don't use character classes like %w here to be independent of the locale - assert(var:match('^[0-9a-zA-Z_]+$'), "site.conf error: `" .. var .. "' is not a valid config section name (only alphanumeric characters and the underscore are allowed)") -end - - -function need_string(varname, required) - local var = loadvar(varname) - - if required == false and var == nil then - return nil - end - - assert_type(var, 'string', "site.conf error: expected `" .. varname .. "' to be a string") - return var -end - -function need_string_match(varname, pat, required) - local var = need_string(varname, required) - - if not var then - return nil - end - - assert(var:match(pat), "site.conf error: expected `" .. varname .. "' to match pattern `" .. pat .. "'") - - return var -end - -function need_number(varname, required) - local var = loadvar(varname) - - if required == false and var == nil then - return nil - end - - assert_type(var, 'number', "site.conf error: expected `" .. varname .. "' to be a number") - - return var -end - -function need_boolean(varname, required) - local var = loadvar(varname) - - if required == false and var == nil then - return nil - end - - assert_type(var, 'boolean', "site.conf error: expected `" .. varname .. "' to be a boolean") - - return var -end - -function need_array(varname, subcheck, required) - local var = loadvar(varname) - - if required == false and var == nil then - return nil - end - - assert_type(var, 'table', "site.conf error: expected `" .. varname .. "' to be an array") - - for _, e in ipairs(var) do - subcheck(e) - end - - return var -end - -function need_table(varname, subcheck, required) - local var = loadvar(varname) - - if required == false and var == nil then - return nil - end - - assert_type(var, 'table', "site.conf error: expected `" .. varname .. "' to be a table") - - if subcheck then - for k, v in pairs(var) do - subcheck(k, v) - end - end - - return var -end - -function need_string_array(varname, required) - return assert(pcall(need_array, varname, function(e) assert_type(e, 'string') end, required), - "site.conf error: expected `" .. varname .. "' to be a string array") -end diff --git a/scripts/clean_output.sh b/scripts/clean_output.sh new file mode 100755 index 00000000..f6c967c5 --- /dev/null +++ b/scripts/clean_output.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +set -e + +[ "$LEDE_TARGET" ] || exit 1 + + +. scripts/common.inc.sh + + +if [ "$(expr match "$LEDE_TARGET" '.*-.*')" -gt 0 ]; then + LEDE_BINDIR="${LEDE_TARGET//-/\/}" +else + LEDE_BINDIR="${LEDE_TARGET}/generic" +fi + +rm -f "lede/bin/targets/${LEDE_BINDIR}"/* 2>/dev/null || true + +# Full builds will output the "packages" directory, so clean up first +[ "$DEVICES" ] || rm -rf "lede/bin/targets/${LEDE_BINDIR}/packages" diff --git a/scripts/common.inc.sh b/scripts/common.inc.sh new file mode 100644 index 00000000..bcda8514 --- /dev/null +++ b/scripts/common.inc.sh @@ -0,0 +1,74 @@ +config() { + : +} + +try_config() { + : +} + +device() { + : +} + +factory_image() { + : +} + +sysupgrade_image() { + : +} + +alias() { + : +} + +manifest_alias() { + : +} + +packages() { + : +} + +factory() { + : +} + +sysupgrade() { + : +} + +no_opkg() { + : +} + + +unknown_devices="$DEVICES" + +want_device() { + [ "$DEVICES" ] || return 0 + + local new_devices='' + + for device in $unknown_devices; do + if [ "$device" != "$1" ]; then + new_devices="${new_devices:+${new_devices} }$device" + fi + done + unknown_devices=$new_devices + + for device in $DEVICES; do + if [ "$device" = "$1" ]; then + return 0 + fi + done + + return 1 +} + +check_devices() { + if [ "$unknown_devices" ]; then + echo "Error: unknown devices given: ${unknown_devices}" >&2 + exit 1 + fi +} diff --git a/scripts/copy_output.sh b/scripts/copy_output.sh new file mode 100755 index 00000000..0917746d --- /dev/null +++ b/scripts/copy_output.sh @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +set -e + +[ "$GLUON_IMAGEDIR" -a "$GLUON_PACKAGEDIR" -a "$LEDE_TARGET" -a "$GLUON_RELEASE" -a "$GLUON_SITEDIR" ] || exit 1 + + +default_factory_ext='.bin' +default_factory_suffix='-squashfs-factory' +default_sysupgrade_ext='.bin' +default_sysupgrade_suffix='-squashfs-sysupgrade' + +output= +profile= +aliases= + +factory_ext= +factory_suffix= +sysupgrade_ext= +sysupgrade_suffix= + +no_opkg= + + +mkdir -p "${GLUON_IMAGEDIR}/factory" "${GLUON_IMAGEDIR}/sysupgrade" + +if [ "$(expr match "$LEDE_TARGET" '.*-.*')" -gt 0 ]; then + LEDE_BINDIR="${LEDE_TARGET//-/\/}" +else + LEDE_BINDIR="${LEDE_TARGET}/generic" +fi + +SITE_CODE="$(scripts/site.sh site_code)" +PACKAGE_PREFIX="gluon-${SITE_CODE}-${GLUON_RELEASE}" + +copy() { + [ "${output}" ] || return 0 + want_device "${output}" || return 0 + + if [ "$factory_ext" ]; then + rm -f "${GLUON_IMAGEDIR}/factory/gluon-"*"-${output}${factory_ext}" + cp "lede/bin/targets/${LEDE_BINDIR}/lede-${LEDE_TARGET}${profile}${factory_suffix}${factory_ext}" \ + "${GLUON_IMAGEDIR}/factory/gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}${factory_ext}" + + for alias in $aliases; do + rm -f "${GLUON_IMAGEDIR}/factory/gluon-"*"-${alias}${factory_ext}" + ln -s "gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}${factory_ext}" \ + "${GLUON_IMAGEDIR}/factory/gluon-${SITE_CODE}-${GLUON_RELEASE}-${alias}${factory_ext}" + done + fi + + if [ "$sysupgrade_ext" ]; then + rm -f "${GLUON_IMAGEDIR}/sysupgrade/gluon-"*"-${output}-sysupgrade${sysupgrade_ext}" + cp "lede/bin/targets/${LEDE_BINDIR}/lede-${LEDE_TARGET}${profile}${sysupgrade_suffix}${sysupgrade_ext}" \ + "${GLUON_IMAGEDIR}/sysupgrade/gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}-sysupgrade${sysupgrade_ext}" + + for alias in $aliases; do + rm -f "${GLUON_IMAGEDIR}/sysupgrade/gluon-"*"-${alias}-sysupgrade${sysupgrade_ext}" + ln -s "gluon-${SITE_CODE}-${GLUON_RELEASE}-${output}-sysupgrade${sysupgrade_ext}" \ + "${GLUON_IMAGEDIR}/sysupgrade/gluon-${SITE_CODE}-${GLUON_RELEASE}-${alias}-sysupgrade${sysupgrade_ext}" + done + fi +} + + +. scripts/common.inc.sh + +device() { + copy + + output="$1" + profile="-$2" + aliases= + + factory_ext="$default_factory_ext" + factory_suffix="$default_factory_suffix" + sysupgrade_ext="$default_sysupgrade_ext" + sysupgrade_suffix="$default_sysupgrade_suffix" +} + +factory_image() { + copy + + output="$1" + aliases= + + if [ "$3" ]; then + profile="-$2" + factory_ext="$3" + else + profile="" + factory_ext="$2" + fi + + factory_suffix= + sysupgrade_ext= + sysupgrade_suffix= +} + +sysupgrade_image() { + copy + + output="$1" + aliases= + + if [ "$3" ]; then + profile="-$2" + sysupgrade_ext="$3" + else + profile="" + sysupgrade_ext="$2" + fi + + factory_ext= + factory_suffix= + sysupgrade_suffix= +} + +alias() { + aliases="$aliases $1" +} + +factory() { + if [ "$2" ]; then + factory_suffix="$1" + factory_ext="$2" + else + factory_ext="$1" + fi + + if [ -z "$profile" ]; then + default_factory_ext="$factory_ext" + default_factory_suffix="$factory_suffix" + fi +} + +sysupgrade() { + if [ "$2" ]; then + sysupgrade_suffix="$1" + sysupgrade_ext="$2" + else + sysupgrade_ext="$1" + fi + + if [ -z "$output" ]; then + default_sysupgrade_ext="$sysupgrade_ext" + default_sysupgrade_suffix="$sysupgrade_suffix" + fi +} + +no_opkg() { + no_opkg=1 +} + + +. targets/"$1"; copy + +# Copy opkg repo +if [ -z "$no_opkg" -a -z "$DEVICES" ]; then + rm -f "$GLUON_PACKAGEDIR"/*/"$LEDE_BINDIR"/* + rmdir -p "$GLUON_PACKAGEDIR"/*/"$LEDE_BINDIR" 2>/dev/null || true + mkdir -p "${GLUON_PACKAGEDIR}/${PACKAGE_PREFIX}/${LEDE_BINDIR}" + cp "lede/bin/targets/${LEDE_BINDIR}/packages"/* "${GLUON_PACKAGEDIR}/${PACKAGE_PREFIX}/${LEDE_BINDIR}" +fi diff --git a/scripts/domain_aliases.lua b/scripts/domain_aliases.lua new file mode 100644 index 00000000..ea7fbf3a --- /dev/null +++ b/scripts/domain_aliases.lua @@ -0,0 +1,13 @@ +local cjson = require 'cjson' + +local function load_json(filename) + local f = assert(io.open(filename)) + local json = cjson.decode(f:read('*a')) + f:close() + return json +end + +local domain = load_json(arg[1]) +for k, _ in pairs(domain.domain_names) do + print(k) +end diff --git a/scripts/features.sh b/scripts/features.sh new file mode 100755 index 00000000..2d35fdee --- /dev/null +++ b/scripts/features.sh @@ -0,0 +1,76 @@ +#!/bin/bash --norc + +set -e +shopt -s nullglob + + +nodefault() { + # We define a function instead of a variable, as variables could + # be predefined in the environment (in theory) + eval "gluon_feature_nodefault_$1() { + : + }" +} + +packages() { + : +} + +for f in package/features packages/*/features; do + . "$f" +done + + +# Shell variables can't contain minus signs, so we escape them +# using underscores (and also escape underscores to avoid mapping +# multiple inputs to the same output) +sanitize() { + local v="$1" + v="${v//_/_1}" + v="${v//-/_2}" + echo -n "$v" +} + +vars= + +for feature in $1; do + if [ "$(type -t gluon_feature_nodefault_${feature})" != 'function' ]; then + echo "gluon-${feature}" + fi + + vars="$vars $(sanitize "$feature")=1" +done + + +nodefault() { + : +} + +packages() { + local cond="$(sanitize "$1")" + shift + + # We only allow variable names, parentheses and the operators: & | ! + if [ "$(expr match "$cond" '.*[^A-Za-z0-9_()&|! ].*')" -gt 0 ]; then + exit 1 + fi + + # Let will return false when the result of the passed expression is 0, + # so we always add 1. This way false is only returned for syntax errors. + local ret="$(env -i $vars bash --norc -ec "let _result_='1+($cond)'; echo -n \"\$_result_\"" 2>/dev/null)" + case "$ret" in + 2) + for pkg in "$@"; do + echo "$pkg" + done + ;; + 1) + ;; + *) + exit 1 + esac +} + +for f in package/features packages/*/features; do + . "$f" +done diff --git a/scripts/feeds.sh b/scripts/feeds.sh new file mode 100755 index 00000000..dd833e8c --- /dev/null +++ b/scripts/feeds.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -e + +. scripts/modules.sh + +FEEDS="$GLUON_SITE_FEEDS $GLUON_FEEDS" + +( + cat lede/feeds.conf.default + echo 'src-link gluon ../../package' + for feed in $FEEDS; do + echo "src-link packages_$feed ../../packages/$feed" + done +) > lede/feeds.conf + +rm -rf lede/tmp +rm -rf lede/feeds +rm -rf lede/package/feeds + +mkdir -p lede/overlay +rm -f lede/overlay/gluon +ln -s ../../overlay lede/overlay/gluon + +lede/scripts/feeds update 'gluon' +for feed in $FEEDS; do + lede/scripts/feeds update "packages_$feed" +done + +lede/scripts/feeds install -a diff --git a/scripts/filesize.sh b/scripts/filesize.sh new file mode 100755 index 00000000..1a6ea4dd --- /dev/null +++ b/scripts/filesize.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +check_command() { + which "$1" >/dev/null 2>&1 +} + +if check_command gnustat; then + gnustat -c%s "$@" +elif check_command gstat; then + gstat -c%s "$@" +elif check_command stat; then + stat -c%s "$@" +else + echo "$0: no suitable stat implementation was found" >&2 + exit 1 +fi diff --git a/scripts/generate_manifest.sh b/scripts/generate_manifest.sh new file mode 100755 index 00000000..85e3ef53 --- /dev/null +++ b/scripts/generate_manifest.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +set -e + +[ "$GLUON_IMAGEDIR" -a "$GLUON_RELEASE" -a "$GLUON_SITEDIR" ] || exit 1 + + +default_sysupgrade_ext='.bin' + +output= +aliases= +manifest_aliases= + +sysupgrade_ext= + + +SITE_CODE="$(scripts/site.sh site_code)" + + +get_filename() { + local name="$1" + echo -n "gluon-${SITE_CODE}-${GLUON_RELEASE}-${name}-sysupgrade${sysupgrade_ext}" +} + +get_filepath() { + local filename="$1" + echo -n "${GLUON_IMAGEDIR}/sysupgrade/${filename}" +} + +generate_line() { + local model="$1" + local filename="$2" + local filesize="$3" + + local filepath="$(get_filepath "$filename")" + [ -e "$filepath" ] || return 0 + + local file256sum="$(scripts/sha256sum.sh "$filepath")" + local file512sum="$(scripts/sha512sum.sh "$filepath")" + + echo "$model $GLUON_RELEASE $file256sum $filesize $filename" + echo "$model $GLUON_RELEASE $file256sum $filename" + echo "$model $GLUON_RELEASE $file512sum $filename" +} + +generate() { + [ "${output}" ] || return 0 + [ "$sysupgrade_ext" ] || return 0 + + local filename="$(get_filename "$output")" + local filepath="$(get_filepath "$filename")" + [ -e "$filepath" ] || return 0 + local filesize="$(scripts/filesize.sh "$filepath")" + + generate_line "$output" "$filename" "$filesize" + + for alias in $aliases; do + generate_line "$alias" "$(get_filename "$alias")" "$filesize" + done + + for alias in $manifest_aliases; do + generate_line "$alias" "$filename" "$filesize" + done +} + + +. scripts/common.inc.sh + +device() { + generate + + output="$1" + aliases= + manifest_aliases= + + sysupgrade_ext="$default_sysupgrade_ext" +} + +sysupgrade_image() { + generate + + output="$1" + aliases= + manifest_aliases= + + if [ "$3" ]; then + sysupgrade_ext="$3" + else + sysupgrade_ext="$2" + fi +} + +alias() { + aliases="$aliases $1" +} + +manifest_alias() { + manifest_aliases="$manifest_aliases $1" +} + +sysupgrade() { + if [ "$2" ]; then + sysupgrade_ext="$2" + else + sysupgrade_ext="$1" + fi + + if [ -z "$output" ]; then + default_sysupgrade_ext="$sysupgrade_ext" + fi +} + +. targets/"$1"; generate diff --git a/scripts/modules.sh b/scripts/modules.sh index 8a875b65..09b7b0fc 100644 --- a/scripts/modules.sh +++ b/scripts/modules.sh @@ -1,7 +1,7 @@ -. "$GLUONDIR"/modules +. ./modules [ ! -f "$GLUON_SITEDIR"/modules ] || . "$GLUON_SITEDIR"/modules -GLUON_MODULES=openwrt +GLUON_MODULES=lede for feed in $GLUON_SITE_FEEDS $GLUON_FEEDS; do GLUON_MODULES="$GLUON_MODULES packages/$feed" diff --git a/scripts/patch.sh b/scripts/patch.sh index 90d2de7b..61d5f455 100755 --- a/scripts/patch.sh +++ b/scripts/patch.sh @@ -3,21 +3,34 @@ set -e shopt -s nullglob -. "$GLUONDIR"/scripts/modules.sh +. scripts/modules.sh + + +mkdir -p "$GLUON_TMPDIR" + +GLUONDIR="$(pwd)" + +PATCHDIR="$GLUON_TMPDIR"/patching +trap 'rm -rf "$PATCHDIR"' EXIT for module in $GLUON_MODULES; do echo "--- Patching module '$module' ---" - cd "$GLUONDIR"/$module - git checkout -B patching base + git clone -s -b base --single-branch "$GLUONDIR/$module" "$PATCHDIR" 2>/dev/null - for patch in "$GLUONDIR"/patches/$module/*.patch; do - if ! git -c user.name='Gluon Patch Manager' -c user.email='gluon@void.example.com' -c commit.gpgsign=false am --whitespace=nowarn --committer-date-is-author-date "$patch"; then - git am --abort - git checkout patched - git branch -D patching - exit 1 - fi + cd "$PATCHDIR" + for patch in "$GLUONDIR/patches/$module"/*.patch; do + git -c user.name='Gluon Patch Manager' -c user.email='gluon@void.example.com' -c commit.gpgsign=false am --whitespace=nowarn --committer-date-is-author-date "$patch" done - git branch -M patched + + cd "$GLUONDIR/$module" + git fetch "$PATCHDIR" 2>/dev/null + git checkout -B patched FETCH_HEAD >/dev/null + + git config branch.patched.remote . + git config branch.patched.merge refs/heads/base + + git submodule update --init --recursive + + rm -rf "$PATCHDIR" done diff --git a/scripts/sha256sum.sh b/scripts/sha256sum.sh new file mode 100755 index 00000000..e4f6f3e5 --- /dev/null +++ b/scripts/sha256sum.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +check_command() { + which "$1" >/dev/null 2>&1 +} + +if check_command sha256sum; then + ret="$(sha256sum "$@")" +elif check_command shasum; then + ret="$(shasum -a 256 "$@")" +elif check_command cksum; then + ret="$(cksum -q -a sha256 "$@")" +else + echo "$0: no suitable sha256sum implementation was found" >&2 + exit 1 +fi + +[ "$?" -eq 0 ] || exit 1 + +echo "$ret" | awk '{ print $1 }' diff --git a/scripts/sha512sum.sh b/scripts/sha512sum.sh index 921e5c6c..d9fd544d 100755 --- a/scripts/sha512sum.sh +++ b/scripts/sha512sum.sh @@ -1,7 +1,7 @@ #!/bin/sh check_command() { - which $1 >/dev/null 2>&1 + which "$1" >/dev/null 2>&1 } if check_command sha512sum; then @@ -11,7 +11,7 @@ elif check_command shasum; then elif check_command cksum; then ret="$(cksum -q -a sha512 "$@")" else - echo "$0: no suitable sha512sum implementation was found" >&1 + echo "$0: no suitable sha512sum implementation was found" >&2 exit 1 fi diff --git a/scripts/site.sh b/scripts/site.sh index 5038438a..11da1676 100755 --- a/scripts/site.sh +++ b/scripts/site.sh @@ -1,5 +1,4 @@ #!/bin/sh -SITE_CONFIG_LUA=scripts/site_config.lua - -"$GLUONDIR"/openwrt/staging_dir/host/bin/lua -e "print(assert(dofile(os.getenv('GLUONDIR') .. '/${SITE_CONFIG_LUA}').$1))" 2>/dev/null +export GLUON_SITE_CONFIG=site.conf +exec lede/staging_dir/hostpkg/bin/lua -e "print(assert(dofile('scripts/site_config.lua').$1))" 2>/dev/null diff --git a/scripts/site_config.lua b/scripts/site_config.lua index a50f115b..2ac95de1 100644 --- a/scripts/site_config.lua +++ b/scripts/site_config.lua @@ -1,9 +1,10 @@ +local site = os.getenv('GLUON_SITEDIR') .. '/' local config = os.getenv('GLUON_SITE_CONFIG') local function loader() coroutine.yield('return ') - coroutine.yield(io.open(config):read('*a')) + coroutine.yield(io.open(site..config):read('*a')) end -- setfenv doesn't work with Lua 5.2 anymore, but we're using 5.1 -return setfenv(assert(load(coroutine.wrap(loader), 'site.conf')), {})() +return setfenv(assert(load(coroutine.wrap(loader), config)), {})() diff --git a/scripts/target_config.inc.sh b/scripts/target_config.inc.sh new file mode 100644 index 00000000..b2d6fa8b --- /dev/null +++ b/scripts/target_config.inc.sh @@ -0,0 +1,18 @@ +site_packages() { + MAKEFLAGS= make print PROFILE="$1" --no-print-directory -s -f - <<'END_MAKE' +include $(GLUON_SITEDIR)/site.mk + +print: + echo '$(GLUON_$(PROFILE)_SITE_PACKAGES)' +END_MAKE +} + + +. scripts/common.inc.sh + + +no_opkg() { + config '# CONFIG_SIGNED_PACKAGES is not set' + config 'CONFIG_CLEAN_IPKG=y' + packages '-opkg' +} diff --git a/scripts/target_config.sh b/scripts/target_config.sh new file mode 100755 index 00000000..66db26e4 --- /dev/null +++ b/scripts/target_config.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash + +set -e + +[ "$LEDE_TARGET" ] || exit 1 + +target="$1" +packages=$2 + + +output= +profile= +default_packages= +profile_packages= + + +LEDE_CONFIG_TARGET="${LEDE_TARGET//-/_}" + + +emit() { + [ "${output}" ] || return 0 + want_device "${output}" || return 0 + + profile_packages="${profile_packages} $(site_packages "$output")" + + for package in $profile_packages; do + [ "${package:0:1}" = '-' ] || echo "CONFIG_PACKAGE_${package}=m" + done + + echo "CONFIG_TARGET_DEVICE_${LEDE_CONFIG_TARGET}_DEVICE_${profile}=y" + echo "CONFIG_TARGET_DEVICE_PACKAGES_${LEDE_CONFIG_TARGET}_DEVICE_${profile}=\"${profile_packages}\"" +} + + +. scripts/target_config.inc.sh + +config() { + echo "$1" +} + +try_config() { + echo "$1" +} + +device() { + emit + + output="$1" + profile="$3" + if [ -z "$profile" ]; then + profile="$2" + fi + + profile_packages="${default_packages}" +} + +packages() { + if [ "${output}" ]; then + profile_packages="${profile_packages} $@" + else + default_packages="${default_packages} $@" + + for package in "$@"; do + if [ "${package:0:1}" = '-' ]; then + echo "# CONFIG_PACKAGE_${package:1} is not set" + else + echo "CONFIG_PACKAGE_${package}=y" + fi + done + fi +} + + +# The sort will not only remove duplicate entries, +# but also magically make =y entries override =m ones +( + . targets/generic + packages $packages + + . targets/"$target" + emit +) | sort -u diff --git a/scripts/target_config_check.sh b/scripts/target_config_check.sh new file mode 100755 index 00000000..c9ae0528 --- /dev/null +++ b/scripts/target_config_check.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +set -e + +[ "$LEDE_TARGET" ] || exit 1 + +target="$1" +packages=$2 + +output= + +ret=0 + +LEDE_CONFIG_TARGET="${LEDE_TARGET//-/_}" + + +fail() { + local message="$1" + + if [ $ret -eq 0 ]; then + ret=1 + echo "Configuration failed:" >&2 + fi + + echo " * $message" >&2 +} + +check_config() { + grep -q "$1" lede/.config +} + +check_package() { + local package="$1" + local value="$2" + + if ! check_config "^CONFIG_PACKAGE_${package}=${value}"; then + fail "unable to enable package '${package}'" + fi +} + + +. scripts/target_config.inc.sh + +config() { + local config="$1" + + if ! check_config "^${config}\$"; then + fail "unable to set '${config}'" + fi +} + +device() { + output="$1" + want_device "${output}" || return 0 + + local profile="$3" + if [ -z "$profile" ]; then + profile="$2" + fi + + if ! check_config "CONFIG_TARGET_DEVICE_${LEDE_CONFIG_TARGET}_DEVICE_${profile}=y"; then + fail "unable to enable device '${profile}'" + fi + + for package in $(site_packages "$output"); do + [ "${package:0:1}" = '-' ] || check_package "$package" + done +} + +factory_image() { + output="$1" + want_device "${output}" || return 0 +} + +sysupgrade_image() { + output="$1" + want_device "${output}" || return 0 +} + +packages() { + if [ "${output}" ]; then + want_device "${output}" || return 0 + + for package in "$@"; do + [ "${package:0:1}" = '-' ] || check_package "$package" + done + else + for package in "$@"; do + [ "${package:0:1}" = '-' ] || check_package "$package" 'y' + done + fi +} + + +. targets/generic +packages $packages + +. targets/"$target" +check_devices + + +exit $ret diff --git a/scripts/update-patches.sh b/scripts/update-patches.sh index cfdeb58e..c8464646 100755 --- a/scripts/update-patches.sh +++ b/scripts/update-patches.sh @@ -3,19 +3,22 @@ set -e shopt -s nullglob -. "$GLUONDIR"/scripts/modules.sh +. scripts/modules.sh + + +GLUONDIR="$(pwd)" for module in $GLUON_MODULES; do echo "--- Updating patches for module '$module' ---" - rm -f "$GLUONDIR"/patches/$module/*.patch - mkdir -p "$GLUONDIR"/patches/$module + rm -rf "$GLUONDIR"/patches/"$module" - cd "$GLUONDIR"/$module + cd "$GLUONDIR"/"$module" n=0 for commit in $(git rev-list --reverse --no-merges base..patched); do let n=n+1 - git show --pretty=format:'From: %an <%ae>%nDate: %aD%nSubject: %B' $commit > "$GLUONDIR"/patches/$module/"$(printf '%04u' $n)-$(git show -s --pretty=format:%f $commit).patch" + mkdir -p "$GLUONDIR"/patches/"$module" + git -c core.abbrev=40 show --pretty=format:'From: %an <%ae>%nDate: %aD%nSubject: %B' --no-renames "$commit" > "$GLUONDIR/patches/$module/$(printf '%04u' $n)-$(git show -s --pretty=format:%f "$commit").patch" done done diff --git a/scripts/update.sh b/scripts/update.sh index 86c69628..99a7e409 100755 --- a/scripts/update.sh +++ b/scripts/update.sh @@ -2,20 +2,24 @@ set -e -. "$GLUONDIR"/scripts/modules.sh +. scripts/modules.sh + + +GLUONDIR="$(pwd)" for module in $GLUON_MODULES; do echo "--- Updating module '$module' ---" - var=$(echo $module | tr '[:lower:]/' '[:upper:]_') + var=$(echo "$module" | tr '[:lower:]/' '[:upper:]_') eval repo=\${${var}_REPO} eval branch=\${${var}_BRANCH} eval commit=\${${var}_COMMIT} - mkdir -p "$GLUONDIR"/$module - cd "$GLUONDIR"/$module + mkdir -p "$GLUONDIR/$module" + cd "$GLUONDIR/$module" git init - git checkout $commit 2>/dev/null || git fetch $repo $branch - git checkout -B base $commit - git submodule update --init --recursive + if ! git branch -f base "$commit" 2>/dev/null; then + git fetch "$repo" "$branch" + git branch -f base "$commit" + fi done diff --git a/targets/ar71xx-generic b/targets/ar71xx-generic new file mode 100644 index 00000000..0aaef371 --- /dev/null +++ b/targets/ar71xx-generic @@ -0,0 +1,295 @@ +config 'CONFIG_GLUON_SPECIALIZE_KERNEL=y' + +ATH10K_PACKAGES='-kmod-ath10k kmod-ath10k-ct' +ATH10K_PACKAGES_QCA9887= +if [ "$GLUON_WLAN_MESH" = 'ibss' ]; then + ATH10K_PACKAGES='-kmod-ath10k kmod-ath10k-ct -ath10k-firmware-qca988x ath10k-firmware-qca988x-ct' + ATH10K_PACKAGES_QCA9887='-kmod-ath10k kmod-ath10k-ct -ath10k-firmware-qca9887 ath10k-firmware-qca9887-ct' +fi + + +# 8devices + +device 8devices-carambola2-board carambola2 +factory + + +# ALFA NETWORK + +device alfa-network-ap121f ap121f ap121f +factory + +device alfa-network-hornet-ub hornet-ub HORNETUB +alias alfa-network-ap121 +alias alfa-network-ap121u + +device alfa-network-tube2h tube2h-8M TUBE2H8M +device alfa-network-n2-n5 alfa-nx ALFANX + + +# Allnet + +device allnet-all0315n all0315n ALL0315N +factory + + +# AVM +device avm-fritz-box-4020 fritz4020 fritz4020 +factory + +# Buffalo + +device buffalo-wzr-hp-g300nh wzr-hp-g300nh WZRHPG300NH +device buffalo-wzr-hp-g300nh2 wzr-hp-g300nh2 WZRHPG300NH2 +device buffalo-wzr-hp-g450h wzr-hp-g450h WZRHPG450H + + +device buffalo-wzr-hp-ag300h wzr-hp-ag300h WZRHPAG300H +sysupgrade +device buffalo-wzr-600dhp wzr-600dhp WZR600DHP +sysupgrade +sysupgrade_image buffalo-wzr-hp-ag300h-wzr-600dhp wzr-hp-ag300h-squashfs-sysupgrade .bin + + +# D-Link + +device d-link-dir-505-rev-a1 dir-505-a1 DIR505A1 +alias d-link-dir-505-rev-a2 + +device d-link-dir-825-rev-b1 dir-825-b1 DIR825B1 +factory + + +# GL Innovations + +device gl-inet-6408a-v1 gl-inet-6408A-v1 +device gl-inet-6416a-v1 gl-inet-6416A-v1 + +device gl-ar150 gl-ar150 +factory +device gl-ar300m gl-ar300m +factory + +device gl-ar750 gl-ar750 +packages $ATH10K_PACKAGES +factory + +# Linksys by Cisco + +device linksys-wrt160nl wrt160nl WRT160NL + + +# Meraki + +# BROKEN: MAC address uniqueness issues +if [ "$BROKEN" ]; then +device meraki-mr12 mr12 +alias meraki-mr62 +factory + +device meraki-mr16 mr16 +alias meraki-mr66 +factory +fi + + +# Netgear + +device netgear-wndr3700 wndr3700 +factory .img + +device netgear-wndr3700v2 wndr3700v2 +factory .img + +device netgear-wndr3800 wndr3800 +factory .img + +device netgear-wndrmacv2 wndrmacv2 +factory .img + +if [ "$BROKEN" ]; then +device netgear-wndrmac wndrmac # BROKEN: Untested +factory .img + +device netgear-wnr2200 wnr2200 WNR2200 # BROKEN: Untested +factory .img +fi + + +# Onion + +device onion-omega onion-omega + + +# OpenMesh + +device openmesh-a60 a60 A60 +alias openmesh-a40 +packages $ATH10K_PACKAGES + +device openmesh-mr1750 mr1750 MR1750 +alias openmesh-mr1750v2 +packages $ATH10K_PACKAGES + +device openmesh-mr600 mr600 MR600 +alias openmesh-mr600v2 + +device openmesh-mr900 mr900 MR900 +alias openmesh-mr900v2 + +device openmesh-om2p om2p OM2P +alias openmesh-om2pv2 +alias openmesh-om2pv4 +alias openmesh-om2p-hs +alias openmesh-om2p-hsv2 +alias openmesh-om2p-hsv3 +alias openmesh-om2p-hsv4 +alias openmesh-om2p-lc + +device openmesh-om5p om5p OM5P +alias openmesh-om5p-an + +device openmesh-om5p-ac om5pac OM5PAC +alias openmesh-om5p-acv2 +packages $ATH10K_PACKAGES + + +# TP-Link + +device tp-link-cpe210-v1.0 cpe210-220 +alias tp-link-cpe210-v1.1 +alias tp-link-cpe220-v1.1 + +device tp-link-cpe210-v2.0 cpe210-v2 + +device tp-link-cpe510-v1.0 cpe510-520 +alias tp-link-cpe510-v1.1 +alias tp-link-cpe520-v1.1 + +device tp-link-wbs210-v1.20 wbs210 +device tp-link-wbs510-v1.20 wbs510 + +device tp-link-tl-wr710n-v1 tl-wr710n-v1 +device tp-link-tl-wr710n-v2.1 tl-wr710n-v2.1 + +if [ "$BROKEN" ]; then +device tp-link-tl-wr810n-v1 tl-wr810n # BROKEN: Untested +fi + +device tp-link-tl-wr842n-nd-v1 tl-wr842n-v1 +device tp-link-tl-wr842n-nd-v2 tl-wr842n-v2 +device tp-link-tl-wr842n-nd-v3 tl-wr842n-v3 + +device tp-link-tl-wr1043n-nd-v1 tl-wr1043nd-v1 +device tp-link-tl-wr1043n-nd-v2 tl-wr1043nd-v2 +device tp-link-tl-wr1043n-nd-v3 tl-wr1043nd-v3 +device tp-link-tl-wr1043n-nd-v4 tl-wr1043nd-v4 +device tp-link-tl-wr1043n-v5 tl-wr1043n-v5 + +device tp-link-tl-wdr3500-v1 tl-wdr3500-v1 +device tp-link-tl-wdr3600-v1 tl-wdr3600-v1 +device tp-link-tl-wdr4300-v1 tl-wdr4300-v1 + +device tp-link-tl-wr2543n-nd-v1 tl-wr2543-v1 + +device tp-link-archer-c5-v1 archer-c5-v1 +packages $ATH10K_PACKAGES + +device tp-link-archer-c7-v2 archer-c7-v2 +packages $ATH10K_PACKAGES +factory -squashfs-factory${GLUON_REGION:+-${GLUON_REGION}} .bin + +device tp-link-archer-c7-v4 archer-c7-v4 +packages $ATH10K_PACKAGES + +if [ "$BROKEN" ]; then +device tp-link-archer-c25-v1 archer-c25-v1 # BROKEN: OOM with 5GHz enabled in most environments +packages $ATH10K_PACKAGES_QCA9887 +fi + +if [ "$BROKEN" ]; then +device tp-link-archer-c58-v1 archer-c58-v1 # BROKEN: OOM with 5GHz enabled in most environments +fi + +if [ "$BROKEN" ] || [ "$GLUON_WLAN_MESH" = '11s' ]; then +device tp-link-archer-c59-v1 archer-c59-v1 # BROKEN: IBSS meshing not working +fi + +if [ "$BROKEN" ]; then +device tp-link-archer-c60-v1 archer-c60-v1 # BROKEN: OOM with 5GHz enabled in most environments +fi + +device tp-link-re450 re450 +packages $ATH10K_PACKAGES + + +# Ubiquiti + +device ubiquiti-airgateway ubnt-air-gateway +alias ubiquiti-airgateway-lr + +device ubiquiti-airgateway-pro ubnt-air-gateway-pro + +device ubiquiti-airrouter ubnt-airrouter + +device ubiquiti-bullet-m ubnt-bullet-m +alias ubiquiti-nanostation-loco-m2 +alias ubiquiti-nanostation-loco-m5 +alias ubiquiti-bullet-m2 +alias ubiquiti-bullet-m5 +alias ubiquiti-picostation-m2 + +device ubiquiti-rocket-m ubnt-rocket-m +alias ubiquiti-rocket-m2 +alias ubiquiti-rocket-m5 + +device ubiquiti-nanostation-m ubnt-nano-m +alias ubiquiti-nanostation-m2 +alias ubiquiti-nanostation-m5 + +device ubiquiti-loco-m-xw ubnt-loco-m-xw +alias ubiquiti-nanostation-loco-m2-xw +alias ubiquiti-nanostation-loco-m5-xw +if [ "$BROKEN" ]; then +alias ubiquiti-nanobeam-m5 # BROKEN: Untested +fi + +device ubiquiti-nanostation-m-xw ubnt-nano-m-xw +alias ubiquiti-nanostation-m2-xw +alias ubiquiti-nanostation-m5-xw + +device ubiquiti-rocket-m-xw ubnt-rocket-m-xw +alias ubiquiti-rocket-m2-xw +alias ubiquiti-rocket-m5-xw + +device ubiquiti-rocket-m-ti ubnt-rocket-m-ti +alias ubiquiti-rocket-m2-ti +alias ubiquiti-rocket-m5-ti + +device ubiquiti-unifi ubnt-unifi +alias ubiquiti-unifi-ap +alias ubiquiti-unifi-ap-lr + +device ubiquiti-unifi-ap-pro ubnt-uap-pro +device ubiquiti-unifiap-outdoor ubnt-unifi-outdoor +device ubiquiti-unifiap-outdoor+ ubnt-unifi-outdoor-plus + +if [ "$BROKEN" ]; then +device ubiquiti-ls-sr71 ubnt-ls-sr71 # BROKEN: Untested +fi + +device ubiquiti-unifi-ac-lite ubnt-unifiac-lite +alias ubiquiti-unifi-ac-mesh +alias ubiquiti-unifi-ac-lr +packages $ATH10K_PACKAGES +factory + +device ubiquiti-unifi-ac-pro ubnt-unifiac-pro +packages $ATH10K_PACKAGES +factory + + +# Western Digital + +device wd-my-net-n600 mynet-n600 +device wd-my-net-n750 mynet-n750 diff --git a/targets/ar71xx-generic/config b/targets/ar71xx-generic/config deleted file mode 100644 index acf4627a..00000000 --- a/targets/ar71xx-generic/config +++ /dev/null @@ -1 +0,0 @@ -# CONFIG_PACKAGE_uboot-ar71xx-nbg460n_550n_550nh is not set diff --git a/targets/ar71xx-generic/profiles.mk b/targets/ar71xx-generic/profiles.mk deleted file mode 100644 index 55d4b1b0..00000000 --- a/targets/ar71xx-generic/profiles.mk +++ /dev/null @@ -1,359 +0,0 @@ -# List of hardware profiles - -## TP-Link - -# CPE210/220/510/520 -$(eval $(call GluonProfile,CPE510,rssileds)) -$(eval $(call GluonModel,CPE510,cpe210-220-510-520,tp-link-cpe510-v1.0)) - -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe210-v1.0)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe220-v1.0)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe520-v1.0)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe210-v1.1)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe220-v1.1)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe510-v1.1)) -$(eval $(call GluonModelAlias,CPE510,tp-link-cpe510-v1.0,tp-link-cpe520-v1.1)) - -# TL-WA701N/ND v1, v2 -$(eval $(call GluonProfile,TLWA701)) -$(eval $(call GluonModel,TLWA701,tl-wa701n-v1,tp-link-tl-wa701n-nd-v1)) -$(eval $(call GluonModel,TLWA701,tl-wa701nd-v2,tp-link-tl-wa701n-nd-v2)) - -# TL-WA7510 v1 -$(eval $(call GluonProfile,TLWA7510)) -$(eval $(call GluonModel,TLWA7510,tl-wa7510n,tp-link-tl-wa7510n-v1)) - -# TL-WR703N v1 -$(eval $(call GluonProfile,TLWR703)) -$(eval $(call GluonModel,TLWR703,tl-wr703n-v1,tp-link-tl-wr703n-v1)) - -# TL-WR710N v1, v2, v2.1 -$(eval $(call GluonProfile,TLWR710)) -$(eval $(call GluonModel,TLWR710,tl-wr710n-v1,tp-link-tl-wr710n-v1)) -$(eval $(call GluonModel,TLWR710,tl-wr710n-v2,tp-link-tl-wr710n-v2)) -$(eval $(call GluonModel,TLWR710,tl-wr710n-v2.1,tp-link-tl-wr710n-v2.1)) - -# TL-WR740N v1, v3, v4, v5 -$(eval $(call GluonProfile,TLWR740)) -$(eval $(call GluonModel,TLWR740,tl-wr740n-v1,tp-link-tl-wr740n-nd-v1)) -$(eval $(call GluonModel,TLWR740,tl-wr740n-v3,tp-link-tl-wr740n-nd-v3)) -$(eval $(call GluonModel,TLWR740,tl-wr740n-v4,tp-link-tl-wr740n-nd-v4)) -$(eval $(call GluonModel,TLWR740,tl-wr740n-v5,tp-link-tl-wr740n-nd-v5)) - -# TL-WR741N/ND v1, v2, v4, v5 -$(eval $(call GluonProfile,TLWR741)) -$(eval $(call GluonModel,TLWR741,tl-wr741nd-v1,tp-link-tl-wr741n-nd-v1)) -$(eval $(call GluonModel,TLWR741,tl-wr741nd-v2,tp-link-tl-wr741n-nd-v2)) -$(eval $(call GluonModel,TLWR741,tl-wr741nd-v4,tp-link-tl-wr741n-nd-v4)) -$(eval $(call GluonModel,TLWR741,tl-wr741nd-v5,tp-link-tl-wr741n-nd-v5)) - -# TL-WR743N/ND v1, v1.1, v2 -$(eval $(call GluonProfile,TLWR743)) -$(eval $(call GluonModel,TLWR743,tl-wr743nd-v1,tp-link-tl-wr743n-nd-v1)) -$(eval $(call GluonModel,TLWR743,tl-wr743nd-v2,tp-link-tl-wr743n-nd-v2)) - -# TL-WR801N/ND v1, v2 -$(eval $(call GluonProfile,TLWA801)) -$(eval $(call GluonModel,TLWA801,tl-wa801nd-v1,tp-link-tl-wa801n-nd-v1)) -$(eval $(call GluonModel,TLWA801,tl-wa801nd-v2,tp-link-tl-wa801n-nd-v2)) - -# TL-WR841N/ND v3, v5, v7, v8, v9, v10, v11 -$(eval $(call GluonProfile,TLWR841)) -$(eval $(call GluonModel,TLWR841,tl-wr841nd-v3,tp-link-tl-wr841n-nd-v3)) -$(eval $(call GluonModel,TLWR841,tl-wr841nd-v5,tp-link-tl-wr841n-nd-v5)) -$(eval $(call GluonModel,TLWR841,tl-wr841nd-v7,tp-link-tl-wr841n-nd-v7)) -$(eval $(call GluonModel,TLWR841,tl-wr841n-v8,tp-link-tl-wr841n-nd-v8)) -$(eval $(call GluonModel,TLWR841,tl-wr841n-v9,tp-link-tl-wr841n-nd-v9)) -$(eval $(call GluonModel,TLWR841,tl-wr841n-v10,tp-link-tl-wr841n-nd-v10)) -$(eval $(call GluonModel,TLWR841,tl-wr841n-v11,tp-link-tl-wr841n-nd-v11)) - -# TL-WR842N/ND v1, v2 -$(eval $(call GluonProfile,TLWR842)) -$(eval $(call GluonModel,TLWR842,tl-wr842n-v1,tp-link-tl-wr842n-nd-v1)) -$(eval $(call GluonModel,TLWR842,tl-wr842n-v2,tp-link-tl-wr842n-nd-v2)) - -# TL-WR843N/ND v1 -$(eval $(call GluonProfile,TLWR843)) -$(eval $(call GluonModel,TLWR843,tl-wr843nd-v1,tp-link-tl-wr843n-nd-v1)) - -# TL-WR941N/ND v2, v3, v4, v5, v6; TL-WR940N/ND v1, v2, v3 -$(eval $(call GluonProfile,TLWR941)) -$(eval $(call GluonModel,TLWR941,tl-wr941nd-v2,tp-link-tl-wr941n-nd-v2)) -$(eval $(call GluonModel,TLWR941,tl-wr941nd-v3,tp-link-tl-wr941n-nd-v3)) -$(eval $(call GluonModel,TLWR941,tl-wr941nd-v4,tp-link-tl-wr941n-nd-v4)) -$(eval $(call GluonModel,TLWR941,tl-wr941nd-v5,tp-link-tl-wr941n-nd-v5)) -$(eval $(call GluonModel,TLWR941,tl-wr941nd-v6,tp-link-tl-wr941n-nd-v6)) - -$(eval $(call GluonModelAlias,TLWR941,tp-link-tl-wr941n-nd-v4,tp-link-tl-wr940n-nd-v1)) -$(eval $(call GluonModelAlias,TLWR941,tp-link-tl-wr941n-nd-v5,tp-link-tl-wr940n-nd-v2)) -$(eval $(call GluonModelAlias,TLWR941,tp-link-tl-wr941n-nd-v6,tp-link-tl-wr940n-nd-v3)) - -# TL-WR1043N/ND v1, v2, v3 -$(eval $(call GluonProfile,TLWR1043)) -$(eval $(call GluonModel,TLWR1043,tl-wr1043nd-v1,tp-link-tl-wr1043n-nd-v1)) -$(eval $(call GluonModel,TLWR1043,tl-wr1043nd-v2,tp-link-tl-wr1043n-nd-v2)) -$(eval $(call GluonModel,TLWR1043,tl-wr1043nd-v3,tp-link-tl-wr1043n-nd-v3)) - -# TL-WDR3500/3600/4300 v1 -$(eval $(call GluonProfile,TLWDR4300)) -$(eval $(call GluonModel,TLWDR4300,tl-wdr3500-v1,tp-link-tl-wdr3500-v1)) -$(eval $(call GluonModel,TLWDR4300,tl-wdr3600-v1,tp-link-tl-wdr3600-v1)) -$(eval $(call GluonModel,TLWDR4300,tl-wdr4300-v1,tp-link-tl-wdr4300-v1)) - -# TL-WA750RE v1 -$(eval $(call GluonProfile,TLWA750)) -$(eval $(call GluonModel,TLWA750,tl-wa750re-v1,tp-link-tl-wa750re-v1)) - -# TL-WA830RE v1, v2 -$(eval $(call GluonProfile,TLWA830)) -$(eval $(call GluonModel,TLWA830,tl-wa830re-v1,tp-link-tl-wa830re-v1)) -$(eval $(call GluonModel,TLWA830,tl-wa830re-v2,tp-link-tl-wa830re-v2)) - -# TL-WA850RE v1 -$(eval $(call GluonProfile,TLWA850)) -$(eval $(call GluonModel,TLWA850,tl-wa850re-v1,tp-link-tl-wa850re-v1)) - -# TL-WA860RE v1 -$(eval $(call GluonProfile,TLWA860)) -$(eval $(call GluonModel,TLWA860,tl-wa860re-v1,tp-link-tl-wa860re-v1)) - -# TL-WA901N/ND v1, v2, v3, v4 -$(eval $(call GluonProfile,TLWA901)) -$(eval $(call GluonModel,TLWA901,tl-wa901nd-v1,tp-link-tl-wa901n-nd-v1)) -$(eval $(call GluonModel,TLWA901,tl-wa901nd-v2,tp-link-tl-wa901n-nd-v2)) -$(eval $(call GluonModel,TLWA901,tl-wa901nd-v3,tp-link-tl-wa901n-nd-v3)) -ifneq ($(BROKEN),) -$(eval $(call GluonModel,TLWA901,tl-wa901nd-v4,tp-link-tl-wa901n-nd-v4)) # BROKEN: untested -endif - -# TL-MR13U v1 -$(eval $(call GluonProfile,TLMR13U)) -$(eval $(call GluonModel,TLMR13U,tl-mr13u-v1,tp-link-tl-mr13u-v1)) - -# TL-MR3020 v1 -$(eval $(call GluonProfile,TLMR3020)) -$(eval $(call GluonModel,TLMR3020,tl-mr3020-v1,tp-link-tl-mr3020-v1)) - -# TL-MR3040 v1, v2 -$(eval $(call GluonProfile,TLMR3040)) -$(eval $(call GluonModel,TLMR3040,tl-mr3040-v1,tp-link-tl-mr3040-v1)) -$(eval $(call GluonModel,TLMR3040,tl-mr3040-v2,tp-link-tl-mr3040-v2)) - -# TL-MR3220 v1, v2 -$(eval $(call GluonProfile,TLMR3220)) -$(eval $(call GluonModel,TLMR3220,tl-mr3220-v1,tp-link-tl-mr3220-v1)) -$(eval $(call GluonModel,TLMR3220,tl-mr3220-v2,tp-link-tl-mr3220-v2)) - -# TL-MR3420 v1, v2 -$(eval $(call GluonProfile,TLMR3420)) -$(eval $(call GluonModel,TLMR3420,tl-mr3420-v1,tp-link-tl-mr3420-v1)) -$(eval $(call GluonModel,TLMR3420,tl-mr3420-v2,tp-link-tl-mr3420-v2)) - -# TL-WR2543N/ND v1 -$(eval $(call GluonProfile,TLWR2543)) -$(eval $(call GluonModel,TLWR2543,tl-wr2543-v1,tp-link-tl-wr2543n-nd-v1)) - -ifneq ($(BROKEN),) -# Archer C5 v1, C7 v2 -$(eval $(call GluonProfile,ARCHERC7,kmod-ath10k ath10k-firmware-qca988x-ct)) -$(eval $(call GluonModel,ARCHERC7,archer-c5,tp-link-archer-c5-v1)) # BROKEN: ath10k -$(eval $(call GluonModel,ARCHERC7,archer-c7-v2,tp-link-archer-c7-v2)) # BROKEN: ath10k -endif - -## Ubiquiti (almost everything) -$(eval $(call GluonProfile,UBNT)) -$(eval $(call GluonModel,UBNT,ubnt-air-gateway,ubiquiti-airgateway)) -$(eval $(call GluonModel,UBNT,ubnt-airrouter,ubiquiti-airrouter)) - -$(eval $(call GluonModel,UBNT,ubnt-bullet-m,ubiquiti-bullet-m)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-nanostation-loco-m2)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-nanostation-loco-m5)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-rocket-m2)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-rocket-m5)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-bullet-m2)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-bullet-m5)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-bullet-m,ubiquiti-picostation-m2)) - -$(eval $(call GluonModel,UBNT,ubnt-nano-m,ubiquiti-nanostation-m)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-nanostation-m,ubiquiti-nanostation-m2)) -$(eval $(call GluonModelAlias,UBNT,ubiquiti-nanostation-m,ubiquiti-nanostation-m5)) - -$(eval $(call GluonModel,UBNT,ubnt-loco-m-xw,ubiquiti-loco-m-xw)) -$(eval $(call GluonModel,UBNT,ubnt-nano-m-xw,ubiquiti-nanostation-m-xw)) -$(eval $(call GluonModel,UBNT,ubnt-rocket-m-xw,ubiquiti-rocket-m-xw)) -$(eval $(call GluonModel,UBNT,ubnt-uap-pro,ubiquiti-unifi-ap-pro)) -$(eval $(call GluonModel,UBNT,ubnt-unifi,ubiquiti-unifi)) -$(eval $(call GluonModel,UBNT,ubnt-unifi-outdoor,ubiquiti-unifiap-outdoor)) -$(eval $(call GluonModel,UBNT,ubnt-unifi-outdoor-plus,ubiquiti-unifiap-outdoor+)) - -ifneq ($(BROKEN),) -$(eval $(call GluonModel,UBNT,ubnt-ls-sr71,ubiquiti-ls-sr71)) # BROKEN: Untested -endif - -# Ubiquiti (ath10k) -ifneq ($(BROKEN),) -$(eval $(call GluonProfile,UBNTUNIFIACLITE,kmod-ath10k ath10k-firmware-qca988x-ct)) -$(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACLITE)) -$(eval $(call GluonModel,UBNTUNIFIACLITE,ubnt-unifiac-lite,ubiquiti-unifi-ac-lite)) # BROKEN: untested, ath10k - -$(eval $(call GluonProfile,UBNTUNIFIACPRO,kmod-ath10k ath10k-firmware-qca988x-ct)) -$(eval $(call GluonProfileFactorySuffix,UBNTUNIFIACPRO)) -$(eval $(call GluonModel,UBNTUNIFIACPRO,ubnt-unifiac-pro,ubiquiti-unifi-ac-pro)) # BROKEN: ath10k -endif - -## D-Link - -# D-Link DIR-505 rev. A1 - -$(eval $(call GluonProfile,DIR505A1)) -$(eval $(call GluonModel,DIR505A1,dir-505-a1,d-link-dir-505-rev-a1)) - -# D-Link DIR-615 rev. C1 -$(eval $(call GluonProfile,DIR615C1)) -$(eval $(call GluonModel,DIR615C1,dir-615-c1,d-link-dir-615-rev-c1)) - -# D-Link DIR-825 rev. B1 -$(eval $(call GluonProfile,DIR825B1)) -$(eval $(call GluonModel,DIR825B1,dir-825-b1,d-link-dir-825-rev-b1)) - - -## Linksys by Cisco - -# WRT160NL -$(eval $(call GluonProfile,WRT160NL)) -$(eval $(call GluonModel,WRT160NL,wrt160nl,linksys-wrt160nl)) - -## Buffalo - -# WZR-HP-G450H -$(eval $(call GluonProfile,WZRHPG450H)) -$(eval $(call GluonModel,WZRHPG450H,wzr-hp-g450h,buffalo-wzr-hp-g450h)) - -# WZR-HP-G300NH -$(eval $(call GluonProfile,WZRHPG300NH)) -$(eval $(call GluonModel,WZRHPG300NH,wzr-hp-g300nh,buffalo-wzr-hp-g300nh)) - -# WZR-HP-AG300H (factory) -$(eval $(call GluonProfile,WZRHPAG300H)) -$(eval $(call GluonProfileSysupgradeSuffix,WZRHPAG300H)) -$(eval $(call GluonModel,WZRHPAG300H,wzr-hp-ag300h,buffalo-wzr-hp-ag300h)) - -# WZR-600DHP (factory) -$(eval $(call GluonProfile,WZR600DHP)) -$(eval $(call GluonProfileSysupgradeSuffix,WZR600DHP)) -$(eval $(call GluonModel,WZR600DHP,wzr-600dhp,buffalo-wzr-600dhp)) - -# WZR-HP-AG300H/WZR-600DHP (sysupgrade) -$(eval $(call GluonProfile,WZRHPAG300H_WZR600DHP,,WZRHPAG300H)) -$(eval $(call GluonProfileFactorySuffix,WZRHPAG300H_WZR600DHP)) -$(eval $(call GluonModel,WZRHPAG300H_WZR600DHP,wzr-hp-ag300h,buffalo-wzr-hp-ag300h-wzr-600dhp)) - -# WHR-HP-G300N -#$(eval $(call GluonProfile,WHRHPG300N)) -#$(eval $(call GluonModel,WHRHPG300N,whr-hp-g300n,buffalo-whr-hp-g300n)) - -## Netgear - -# WNDR3700 (v1, v2) / WNDR3800 / WNDRMAC (v1, v2) -$(eval $(call GluonProfile,WNDR3700)) -$(eval $(call GluonProfileFactorySuffix,WNDR3700,-squashfs-factory,.img)) -$(eval $(call GluonModel,WNDR3700,wndr3700,netgear-wndr3700)) -$(eval $(call GluonModel,WNDR3700,wndr3700v2,netgear-wndr3700v2)) -$(eval $(call GluonModel,WNDR3700,wndr3800,netgear-wndr3800)) -ifneq ($(BROKEN),) -$(eval $(call GluonModel,WNDR3700,wndrmac,netgear-wndrmac)) # BROKEN: untested -endif -$(eval $(call GluonModel,WNDR3700,wndrmacv2,netgear-wndrmacv2)) - -## Allnet - -# ALL0315N -$(eval $(call GluonProfile,ALL0315N,uboot-envtools rssileds)) -$(eval $(call GluonProfileFactorySuffix,ALL0315N)) -$(eval $(call GluonModel,ALL0315N,all0315n,allnet-all0315n)) - -## GL-iNet - -# GL-iNet 1.0 -$(eval $(call GluonProfile,GLINET)) -$(eval $(call GluonModel,GLINET,gl-inet-6408A-v1,gl-inet-6408a-v1)) -$(eval $(call GluonModel,GLINET,gl-inet-6416A-v1,gl-inet-6416a-v1)) - -## Western Digital - -# WD MyNet N600 -$(eval $(call GluonProfile,MYNETN600)) -$(eval $(call GluonModel,MYNETN600,mynet-n600,wd-my-net-n600)) - -# WD MyNet N750 -$(eval $(call GluonProfile,MYNETN750)) -$(eval $(call GluonModel,MYNETN750,mynet-n750,wd-my-net-n750)) - -## Onion - -# Omega -$(eval $(call GluonProfile,OMEGA)) -$(eval $(call GluonModel,OMEGA,onion-omega,onion-omega)) - -## OpenMesh - -# MR1750 -$(eval $(call GluonProfile,MR1750,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct)) -$(eval $(call GluonModel,MR1750,mr1750,openmesh-mr1750)) - -# MR600 -$(eval $(call GluonProfile,MR600,om-watchdog uboot-envtools)) -$(eval $(call GluonModel,MR600,mr600,openmesh-mr600)) -$(eval $(call GluonModelAlias,MR600,openmesh-mr600,openmesh-mr600v2)) - -# MR900 -$(eval $(call GluonProfile,MR900,om-watchdog uboot-envtools)) -$(eval $(call GluonModel,MR900,mr900,openmesh-mr900)) -$(eval $(call GluonModelAlias,MR900,openmesh-mr900,openmesh-mr900v2)) - -# OM2P -$(eval $(call GluonProfile,OM2P,om-watchdog uboot-envtools)) -$(eval $(call GluonModel,OM2P,om2p,openmesh-om2p)) -$(eval $(call GluonModelAlias,OM2P,openmesh-om2p,openmesh-om2pv2)) -$(eval $(call GluonModelAlias,OM2P,openmesh-om2p,openmesh-om2p-hs)) -$(eval $(call GluonModelAlias,OM2P,openmesh-om2p,openmesh-om2p-hsv2)) -$(eval $(call GluonModelAlias,OM2P,openmesh-om2p,openmesh-om2p-lc)) - -# OM5P -$(eval $(call GluonProfile,OM5P,om-watchdog uboot-envtools)) -$(eval $(call GluonModel,OM5P,om5p,openmesh-om5p)) -$(eval $(call GluonModelAlias,OM5P,openmesh-om5p,openmesh-om5p-an)) - -# OM5P-AC -$(eval $(call GluonProfile,OM5PAC,om-watchdog uboot-envtools kmod-ath10k ath10k-firmware-qca988x-ct)) -$(eval $(call GluonModel,OM5PAC,om5pac,openmesh-om5p-ac)) -$(eval $(call GluonModelAlias,OM5PAC,openmesh-om5p-ac,openmesh-om5p-acv2)) - -## ALFA - -# Hornet-UB -$(eval $(call GluonProfile,HORNETUB)) -$(eval $(call GluonModel,HORNETUB,hornet-ub,alfa-hornet-ub)) -$(eval $(call GluonModelAlias,HORNETUB,alfa-hornet-ub,alfa-ap121)) -$(eval $(call GluonModelAlias,HORNETUB,alfa-hornet-ub,alfa-ap121u)) - -## Meraki - -# Meraki MR12/MR62 -$(eval $(call GluonProfile,MR12,rssileds)) -$(eval $(call GluonProfileFactorySuffix,MR12)) -$(eval $(call GluonModel,MR12,mr12,meraki-mr12)) -$(eval $(call GluonModelAlias,MR12,meraki-mr12,meraki-mr62)) - -# Meraki MR16/MR66 -$(eval $(call GluonProfile,MR16,rssileds)) -$(eval $(call GluonProfileFactorySuffix,MR16)) -$(eval $(call GluonModel,MR16,mr16,meraki-mr16)) -$(eval $(call GluonModelAlias,MR16,meraki-mr16,meraki-mr66)) - -## 8devices - -# Carambola 2 -$(eval $(call GluonProfile,CARAMBOLA2)) -$(eval $(call GluonModel,CARAMBOLA2,carambola2,8devices-carambola2-board)) -$(eval $(call GluonProfileFactorySuffix,CARAMBOLA2)) diff --git a/targets/ar71xx-mikrotik b/targets/ar71xx-mikrotik new file mode 100644 index 00000000..56ac8159 --- /dev/null +++ b/targets/ar71xx-mikrotik @@ -0,0 +1,11 @@ +config 'CONFIG_GLUON_SPECIALIZE_KERNEL=y' + +# Enable ath5k in addition to ath9k +# ath5k cards are commonly used with Mikrotik hardware +packages 'kmod-ath5k' + +device mikrotik-nand-64m nand-64m +factory + +device mikrotik-nand-large nand-large +factory diff --git a/targets/ar71xx-nand b/targets/ar71xx-nand new file mode 100644 index 00000000..223a6ccc --- /dev/null +++ b/targets/ar71xx-nand @@ -0,0 +1,14 @@ +config 'CONFIG_GLUON_SPECIALIZE_KERNEL=y' + +factory -ubi-factory .img +sysupgrade -squashfs-sysupgrade .tar + +# Netgear + +device netgear-wndr3700v4 wndr3700v4 WNDR3700V4 +device netgear-wndr4300 wndr4300 WNDR4300V1 + +# ZyXEL +device zyxel-nbg6716 nbg6716 NBG6716 +packages $ATH10K_PACKAGES +factory -squashfs-factory .bin diff --git a/targets/ar71xx-nand/profiles.mk b/targets/ar71xx-nand/profiles.mk deleted file mode 100644 index 1fc253b0..00000000 --- a/targets/ar71xx-nand/profiles.mk +++ /dev/null @@ -1,10 +0,0 @@ -# List of hardware profiles - -## NETGEAR - -# WNDR3700 v4, WNDR4300 v1 -$(eval $(call GluonProfile,WNDR4300)) -$(eval $(call GluonProfileFactorySuffix,WNDR4300,-ubi-factory,.img)) -$(eval $(call GluonProfileSysupgradeSuffix,WNDR4300,-squashfs-sysupgrade,.tar)) -$(eval $(call GluonModel,WNDR4300,wndr3700v4,netgear-wndr3700v4)) -$(eval $(call GluonModel,WNDR4300,wndr4300,netgear-wndr4300)) diff --git a/targets/ar71xx-tiny b/targets/ar71xx-tiny new file mode 100644 index 00000000..9962de7b --- /dev/null +++ b/targets/ar71xx-tiny @@ -0,0 +1,105 @@ +config 'CONFIG_GLUON_SPECIALIZE_KERNEL=y' + +no_opkg +packages '-uboot-envtools' '-kmod-usb-core' '-kmod-usb-ohci' '-kmod-usb2' '-kmod-usb-ledtrig-usbport' + + +# D-Link + +device d-link-dir-615-rev-c1 dir-615-c1 DIR615C1 + + +# TP-Link + +device tp-link-tl-wa701n-nd-v1 tl-wa701nd-v1 +device tp-link-tl-wa701n-nd-v2 tl-wa701nd-v2 + +device tp-link-tl-wa7210n-v2 tl-wa7210n-v2 +device tp-link-tl-wa7510n-v1 tl-wa7510n + +device tp-link-tl-wr703n-v1 tl-wr703n-v1 + +device tp-link-tl-wr710n-v2 tl-wr710n-v2 + +device tp-link-tl-wr740n-nd-v1 tl-wr740n-v1 +device tp-link-tl-wr740n-nd-v3 tl-wr740n-v3 +device tp-link-tl-wr740n-nd-v4 tl-wr740n-v4 +device tp-link-tl-wr740n-nd-v5 tl-wr740n-v5 + +device tp-link-tl-wr741n-nd-v1 tl-wr741nd-v1 +device tp-link-tl-wr741n-nd-v2 tl-wr741nd-v2 +device tp-link-tl-wr741n-nd-v4 tl-wr741nd-v4 +device tp-link-tl-wr741n-nd-v5 tl-wr741nd-v5 + +device tp-link-tl-wr743n-nd-v1 tl-wr743nd-v1 +device tp-link-tl-wr743n-nd-v2 tl-wr743nd-v2 + +device tp-link-tl-wa801n-nd-v1 tl-wa801nd-v1 +device tp-link-tl-wa801n-nd-v2 tl-wa801nd-v2 +device tp-link-tl-wa801n-nd-v3 tl-wa801nd-v3 + +if [ "$BROKEN" ]; then +device tp-link-tl-wr802n-v1 tl-wr802n-v1 # BROKEN: Untested +fi + +device tp-link-tl-wr841n-nd-v3 tl-wr841-v3 +device tp-link-tl-wr841n-nd-v5 tl-wr841-v5 +device tp-link-tl-wr841n-nd-v7 tl-wr841-v7 +device tp-link-tl-wr841n-nd-v8 tl-wr841-v8 +device tp-link-tl-wr841n-nd-v9 tl-wr841-v9 +device tp-link-tl-wr841n-nd-v10 tl-wr841-v10 +device tp-link-tl-wr841n-nd-v11 tl-wr841-v11 +factory -squashfs-factory${GLUON_REGION:+-${GLUON_REGION}} .bin +device tp-link-tl-wr841n-nd-v12 tl-wr841-v12 +factory -squashfs-factory${GLUON_REGION:+-${GLUON_REGION}} .bin + +device tp-link-tl-wr843n-nd-v1 tl-wr843nd-v1 + +device tp-link-tl-wr941n-nd-v2 tl-wr941nd-v2 +device tp-link-tl-wr941n-nd-v3 tl-wr941nd-v3 + +device tp-link-tl-wr941n-nd-v4 tl-wr941nd-v4 +alias tp-link-tl-wr940n-v1 + +device tp-link-tl-wr941n-nd-v5 tl-wr941nd-v5 +alias tp-link-tl-wr940n-v2 + +device tp-link-tl-wr941n-nd-v6 tl-wr941nd-v6 +alias tp-link-tl-wr940n-v3 + +device tp-link-tl-wr940n-v4 tl-wr940n-v4 +alias tp-link-tl-wr940n-v5 +factory -squashfs-factory${GLUON_REGION:+-${GLUON_REGION}} .bin + +device tp-link-tl-wr940n-v6 tl-wr940n-v6 +factory -squashfs-factory${GLUON_REGION:+-${GLUON_REGION}} .bin + +device tp-link-tl-wa730re-v1 tl-wa730re-v1 + +device tp-link-tl-wa750re-v1 tl-wa750re-v1 + +device tp-link-tl-wa830re-v1 tl-wa830re-v1 +device tp-link-tl-wa830re-v2 tl-wa830re-v2 + +device tp-link-tl-wa850re-v1 tl-wa850re-v1 + +device tp-link-tl-wa860re-v1 tl-wa860re-v1 + +device tp-link-tl-wa901n-nd-v1 tl-wa901nd-v1 +device tp-link-tl-wa901n-nd-v2 tl-wa901nd-v2 +device tp-link-tl-wa901n-nd-v3 tl-wa901nd-v3 +device tp-link-tl-wa901n-nd-v4 tl-wa901nd-v4 +device tp-link-tl-wa901n-nd-v5 tl-wa901nd-v5 + +device tp-link-tl-mr13u-v1 tl-mr13u-v1 + +device tp-link-tl-mr3020-v1 tl-mr3020-v1 + +device tp-link-tl-mr3040-v1 tl-mr3040-v1 +device tp-link-tl-mr3040-v2 tl-mr3040-v2 + +device tp-link-tl-mr3220-v1 tl-mr3220-v1 +device tp-link-tl-mr3220-v2 tl-mr3220-v2 + +device tp-link-tl-mr3420-v1 tl-mr3420-v1 +device tp-link-tl-mr3420-v2 tl-mr3420-v2 diff --git a/targets/brcm2708-bcm2708 b/targets/brcm2708-bcm2708 new file mode 100644 index 00000000..00bd9a38 --- /dev/null +++ b/targets/brcm2708-bcm2708 @@ -0,0 +1,4 @@ +device raspberry-pi rpi +manifest_alias raspberry-pi-model-b-rev-2 +factory -ext4-sdcard .img.gz +sysupgrade -ext4-sdcard .img.gz diff --git a/targets/brcm2708-bcm2708/profiles.mk b/targets/brcm2708-bcm2708/profiles.mk deleted file mode 100644 index 4261913a..00000000 --- a/targets/brcm2708-bcm2708/profiles.mk +++ /dev/null @@ -1,4 +0,0 @@ -$(eval $(call GluonProfile,RaspberryPi)) -$(eval $(call GluonProfileFactorySuffix,RaspberryPi,-vfat-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,RaspberryPi,-vfat-ext4,.img.gz)) -$(eval $(call GluonModel,RaspberryPi,sdcard,raspberry-pi)) diff --git a/targets/brcm2708-bcm2709 b/targets/brcm2708-bcm2709 new file mode 100644 index 00000000..6ede78a4 --- /dev/null +++ b/targets/brcm2708-bcm2709 @@ -0,0 +1,4 @@ +device raspberry-pi-2 rpi-2 +manifest_alias raspberry-pi-2-model-b-rev-1.1 +factory -ext4-sdcard .img.gz +sysupgrade -ext4-sdcard .img.gz diff --git a/targets/brcm2708-bcm2709/profiles.mk b/targets/brcm2708-bcm2709/profiles.mk deleted file mode 100644 index 74b17215..00000000 --- a/targets/brcm2708-bcm2709/profiles.mk +++ /dev/null @@ -1,4 +0,0 @@ -$(eval $(call GluonProfile,RaspberryPi2)) -$(eval $(call GluonProfileFactorySuffix,RaspberryPi2,-vfat-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,RaspberryPi2,-vfat-ext4,.img.gz)) -$(eval $(call GluonModel,RaspberryPi2,sdcard,raspberry-pi-2)) diff --git a/targets/brcm2708-bcm2710 b/targets/brcm2708-bcm2710 new file mode 100644 index 00000000..5c93449c --- /dev/null +++ b/targets/brcm2708-bcm2710 @@ -0,0 +1,3 @@ +device raspberry-pi-3 rpi-3 +factory -ext4-sdcard .img.gz +sysupgrade -ext4-sdcard .img.gz diff --git a/targets/generic b/targets/generic new file mode 100644 index 00000000..37c16be0 --- /dev/null +++ b/targets/generic @@ -0,0 +1,42 @@ +[ "$GLUON_SITEDIR" -a "$GLUON_RELEASE" -a "$BOARD" ] || exit 1 + +config "CONFIG_GLUON_SITEDIR=\"$GLUON_SITEDIR\"" +config "CONFIG_GLUON_RELEASE=\"$GLUON_RELEASE\"" +try_config "CONFIG_GLUON_BRANCH=\"$GLUON_BRANCH\"" + +for lang in $GLUON_LANGS; do + try_config "CONFIG_GLUON_WEB_LANG_${lang}=y" +done + +[ "$BOARD" ] && config "CONFIG_TARGET_${BOARD}=y" +[ -z "$SUBTARGET" ] || config "CONFIG_TARGET_${BOARD}_${SUBTARGET}=y" + + +config '# CONFIG_TARGET_ROOTFS_INITRAMFS is not set' + +config 'CONFIG_ALL_NONSHARED=y' + +config '# CONFIG_PACKAGE_usbip is not set' # fails to build + +config 'CONFIG_BUSYBOX_CUSTOM=y' +config '# CONFIG_BUSYBOX_CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set' + +config 'CONFIG_PACKAGE_ATH_DEBUG=y' + +try_config 'CONFIG_TARGET_MULTI_PROFILE=y' +try_config 'CONFIG_TARGET_PER_DEVICE_ROOTFS=y' + +if [ "$GLUON_MULTIDOMAIN" = 1 ]; then + config 'CONFIG_GLUON_MULTIDOMAIN=y' +fi + +if [ "$GLUON_DEBUG" = 1 ]; then + config 'CONFIG_DEBUG=y' + config 'CONFIG_NO_STRIP=y' + config '# CONFIG_USE_STRIP is not set' + config '# CONFIG_USE_SSTRIP is not set' +fi + + +packages '-odhcpd' '-ppp' '-ppp-mod-pppoe' '-wpad-mini' +packages 'gluon-core' 'ip6tables' 'hostapd-mini' diff --git a/targets/ipq806x b/targets/ipq806x new file mode 100644 index 00000000..b512db95 --- /dev/null +++ b/targets/ipq806x @@ -0,0 +1,7 @@ +ATH10K_PACKAGES='-kmod-ath10k kmod-ath10k-ct -ath10k-firmware-qca99x0 ath10k-firmware-qca99x0-ct' + + +# TP-Link + +device tp-link-archer-c2600 C2600 +packages $ATH10K_PACKAGES diff --git a/targets/mpc85xx-generic b/targets/mpc85xx-generic new file mode 100644 index 00000000..f2a1db4f --- /dev/null +++ b/targets/mpc85xx-generic @@ -0,0 +1,5 @@ +# There is no per-device rootfs support on mpc85xx-generic yet, +# so we can't use 'device' +config 'CONFIG_TARGET_mpc85xx_generic_TLWDR4900=y' +factory_image tp-link-tl-wdr4900-v1 tl-wdr4900-v1-squashfs-factory .bin +sysupgrade_image tp-link-tl-wdr4900-v1 tl-wdr4900-v1-squashfs-sysupgrade .bin diff --git a/targets/mpc85xx-generic/profiles.mk b/targets/mpc85xx-generic/profiles.mk deleted file mode 100644 index 913f12b1..00000000 --- a/targets/mpc85xx-generic/profiles.mk +++ /dev/null @@ -1,7 +0,0 @@ -# List of hardware profiles - -## TP-Link - -# TL-WDR4900 v1 -$(eval $(call GluonProfile,TLWDR4900)) -$(eval $(call GluonModel,TLWDR4900,tl-wdr4900-v1,tp-link-tl-wdr4900-v1)) diff --git a/targets/mvebu b/targets/mvebu new file mode 100644 index 00000000..ee4bbbee --- /dev/null +++ b/targets/mvebu @@ -0,0 +1,2 @@ +device linksys-wrt1200ac linksys-wrt1200ac +factory .img diff --git a/targets/ramips-mt7620 b/targets/ramips-mt7620 new file mode 100644 index 00000000..2f70cd65 --- /dev/null +++ b/targets/ramips-mt7620 @@ -0,0 +1,9 @@ +# GL Innovations +device gl-mt300a gl-mt300a +factory + +device gl-mt300n gl-mt300n +factory + +device gl-mt750 gl-mt750 +factory diff --git a/targets/ramips-mt7621 b/targets/ramips-mt7621 new file mode 100644 index 00000000..08a82690 --- /dev/null +++ b/targets/ramips-mt7621 @@ -0,0 +1,39 @@ +# BROKEN: No AP+IBSS support (plus individual issues) +if [ "$BROKEN" ]; then + +## D-Link + +device d-link-dir-860l-b1 dir-860l-b1 # BROKEN: 2.4 GHz Mesh unreliable + + +## Netgear + +device netgear-wndr3700v5 wndr3700v5 # BROKEN: Untested +factory + + +## ZBT + +device zbt-wg3526-16m zbt-wg3526-16M # BROKEN: Untested +factory +manifest_alias zbt-wg3526 + +device zbt-wg3526-32m zbt-wg3526-32M # BROKEN: Untested +factory + +fi + + +# Devices without WLAN + +## Ubiquiti + +device ubnt-erx ubnt-erx +packages '-hostapd-mini' +factory +sysupgrade '.tar' + +device ubnt-erx-sfp ubnt-erx-sfp +packages '-hostapd-mini' +factory +sysupgrade '.tar' diff --git a/targets/ramips-mt7628 b/targets/ramips-mt7628 new file mode 100644 index 00000000..158ff55e --- /dev/null +++ b/targets/ramips-mt7628 @@ -0,0 +1,4 @@ +# VoCore 2 + +device vocore2 vocore2 +factory diff --git a/targets/ramips-rt305x b/targets/ramips-rt305x new file mode 100644 index 00000000..5f1c979e --- /dev/null +++ b/targets/ramips-rt305x @@ -0,0 +1,23 @@ +# A5 + +device a5-v11 a5-v11 + + +# D-Link + +device d-link-dir-615-h1 dir-615-h1 + +device d-link-dir-615-d dir-615-d +alias d-link-dir-615-d1 +alias d-link-dir-615-d2 +alias d-link-dir-615-d3 +alias d-link-dir-615-d4 + + +# VoCore + +device vocore-8M vocore-8M +factory + +device vocore-16M vocore-16M +factory diff --git a/targets/ramips-rt305x/profiles.mk b/targets/ramips-rt305x/profiles.mk deleted file mode 100644 index 4aee5eae..00000000 --- a/targets/ramips-rt305x/profiles.mk +++ /dev/null @@ -1,6 +0,0 @@ -# List of hardware profiles - -# VoCore -$(eval $(call GluonProfile,VOCORE)) -$(eval $(call GluonProfileFactorySuffix,VOCORE)) -$(eval $(call GluonModel,VOCORE,vocore,vocore)) diff --git a/targets/sunxi b/targets/sunxi new file mode 100644 index 00000000..418fcefa --- /dev/null +++ b/targets/sunxi @@ -0,0 +1,13 @@ +factory -ext4-sdcard .img.gz +sysupgrade -ext4-sdcard .img.gz + + +device lemaker-banana-pi sun7i-a20-bananapi + +if [ "$BROKEN" ]; then + +device lemaker-banana-pro sun7i-a20-bananapro # BROKEN: WiFi chip not supported + +device lamobo-r1 sun7i-a20-lamobo-r1 # BROKEN: AP+IBSS and AP+11s not working + +fi diff --git a/targets/sunxi/profiles.mk b/targets/sunxi/profiles.mk deleted file mode 100644 index b54eea7b..00000000 --- a/targets/sunxi/profiles.mk +++ /dev/null @@ -1,4 +0,0 @@ -$(eval $(call GluonProfile,Bananapi,uboot-sunxi-Bananapi kmod-rtc-sunxi)) -$(eval $(call GluonProfileFactorySuffix,Bananapi,-sdcard-vfat-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,Bananapi)) -$(eval $(call GluonModel,Bananapi,Bananapi,lemaker-banana-pi)) diff --git a/targets/targets.mk b/targets/targets.mk index 95b868be..c02af678 100644 --- a/targets/targets.mk +++ b/targets/targets.mk @@ -1,14 +1,26 @@ +GLUON_WLAN_MESH_11s := $(filter 11s,$(GLUON_WLAN_MESH)) + $(eval $(call GluonTarget,ar71xx,generic)) +$(eval $(call GluonTarget,ar71xx,tiny,generic)) $(eval $(call GluonTarget,ar71xx,nand)) +$(eval $(call GluonTarget,brcm2708,bcm2708)) +$(eval $(call GluonTarget,brcm2708,bcm2709)) $(eval $(call GluonTarget,mpc85xx,generic)) +$(eval $(call GluonTarget,ramips,mt7621)) +$(eval $(call GluonTarget,sunxi)) $(eval $(call GluonTarget,x86,generic)) -$(eval $(call GluonTarget,x86,kvm_guest)) +$(eval $(call GluonTarget,x86,geode)) $(eval $(call GluonTarget,x86,64)) -$(eval $(call GluonTarget,x86,xen_domu)) + +ifneq ($(GLUON_WLAN_MESH_11s)$(BROKEN),) +$(eval $(call GluonTarget,ipq806x)) +$(eval $(call GluonTarget,ramips,mt7620)) +$(eval $(call GluonTarget,ramips,mt7628)) +$(eval $(call GluonTarget,ramips,rt305x)) +endif ifneq ($(BROKEN),) -$(eval $(call GluonTarget,ramips,rt305x)) # BROKEN: No AP+IBSS support -$(eval $(call GluonTarget,brcm2708,bcm2708)) # BROKEN: Needs more testing -$(eval $(call GluonTarget,brcm2708,bcm2709)) # BROKEN: Needs more testing -$(eval $(call GluonTarget,sunxi)) # BROKEN: Untested, no sysupgrade support +$(eval $(call GluonTarget,ar71xx,mikrotik)) # BROKEN: no sysupgrade support +$(eval $(call GluonTarget,brcm2708,bcm2710)) # BROKEN: Untested +$(eval $(call GluonTarget,mvebu)) # BROKEN: No AP+IBSS or 11s support endif diff --git a/targets/x86-64 b/targets/x86-64 new file mode 100644 index 00000000..9d690285 --- /dev/null +++ b/targets/x86-64 @@ -0,0 +1,6 @@ +. targets/x86.inc + +factory_image x86-64 combined-ext4 .img.gz +factory_image x86-64 combined-ext4 .vdi +factory_image x86-64 combined-ext4 .vmdk +sysupgrade_image x86-64 combined-ext4 .img.gz diff --git a/targets/x86-64/config b/targets/x86-64/config deleted file mode 100644 index 85016e81..00000000 --- a/targets/x86-64/config +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_VDI_IMAGES=y -CONFIG_VMDK_IMAGES=y diff --git a/targets/x86-64/profiles.mk b/targets/x86-64/profiles.mk deleted file mode 100644 index 8f561fc1..00000000 --- a/targets/x86-64/profiles.mk +++ /dev/null @@ -1,17 +0,0 @@ -X86_64_NETWORK_MODULES := kmod-3c59x kmod-e100 kmod-e1000 kmod-e1000e kmod-natsemi kmod-ne2k-pci kmod-pcnet32 kmod-8139too kmod-r8169 kmod-sis900 kmod-tg3 kmod-via-rhine kmod-via-velocity kmod-forcedeth - - -$(eval $(call GluonProfile,GENERIC,$(X86_64_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonModel,GENERIC,combined,x86-64)) - -$(eval $(call GluonProfile,VDI,$(X86_64_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,VDI,-ext4,.vdi)) -$(eval $(call GluonProfileSysupgradeSuffix,VDI)) -$(eval $(call GluonModel,VDI,combined,x86-64-virtualbox)) - -$(eval $(call GluonProfile,VMDK,$(X86_64_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,VMDK,-ext4,.vmdk)) -$(eval $(call GluonProfileSysupgradeSuffix,VMDK)) -$(eval $(call GluonModel,VMDK,combined,x86-64-vmware)) diff --git a/targets/x86-generic b/targets/x86-generic new file mode 100644 index 00000000..9158a8aa --- /dev/null +++ b/targets/x86-generic @@ -0,0 +1,8 @@ +. targets/x86.inc + +factory_image x86-generic combined-ext4 .img.gz +factory_image x86-generic combined-ext4 .vdi +factory_image x86-generic combined-ext4 .vmdk +sysupgrade_image x86-generic combined-ext4 .img.gz +manifest_alias x86-kvm +manifest_alias x86-xen_domu diff --git a/targets/x86-generic/config b/targets/x86-generic/config deleted file mode 100644 index 85016e81..00000000 --- a/targets/x86-generic/config +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_VDI_IMAGES=y -CONFIG_VMDK_IMAGES=y diff --git a/targets/x86-generic/profiles.mk b/targets/x86-generic/profiles.mk deleted file mode 100644 index a8ca3dbb..00000000 --- a/targets/x86-generic/profiles.mk +++ /dev/null @@ -1,17 +0,0 @@ -X86_GENERIC_NETWORK_MODULES := kmod-3c59x kmod-e100 kmod-e1000 kmod-e1000e kmod-natsemi kmod-ne2k-pci kmod-pcnet32 kmod-8139too kmod-r8169 kmod-sis900 kmod-tg3 kmod-via-rhine kmod-via-velocity kmod-forcedeth - - -$(eval $(call GluonProfile,GENERIC,$(X86_GENERIC_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonModel,GENERIC,combined,x86-generic)) - -$(eval $(call GluonProfile,VDI,$(X86_GENERIC_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,VDI,-ext4,.vdi)) -$(eval $(call GluonProfileSysupgradeSuffix,VDI)) -$(eval $(call GluonModel,VDI,combined,x86-virtualbox)) - -$(eval $(call GluonProfile,VMDK,$(X86_GENERIC_NETWORK_MODULES))) -$(eval $(call GluonProfileFactorySuffix,VMDK,-ext4,.vmdk)) -$(eval $(call GluonProfileSysupgradeSuffix,VMDK)) -$(eval $(call GluonModel,VMDK,combined,x86-vmware)) diff --git a/targets/x86-geode b/targets/x86-geode new file mode 100644 index 00000000..faa771d2 --- /dev/null +++ b/targets/x86-geode @@ -0,0 +1,5 @@ +packages 'kmod-3c59x' 'kmod-8139cp' 'kmod-8139too' 'kmod-e100' 'kmod-e1000' 'kmod-forcedeth' 'kmod-igb' 'kmod-natsemi' 'kmod-ne2k-pci' +packages 'kmod-pcnet32' 'kmod-r8169' 'kmod-sis900' 'kmod-sky2' 'kmod-tg3' 'kmod-tulip' 'kmod-via-rhine' 'kmod-via-velocity' + +factory_image x86-geode combined-ext4 .img.gz +sysupgrade_image x86-geode combined-ext4 .img.gz diff --git a/targets/x86-kvm_guest/profiles.mk b/targets/x86-kvm_guest/profiles.mk deleted file mode 100644 index 22fb8903..00000000 --- a/targets/x86-kvm_guest/profiles.mk +++ /dev/null @@ -1,4 +0,0 @@ -$(eval $(call GluonProfile,KVM,kmod-virtio-balloon kmod-virtio-net kmod-virtio-random)) -$(eval $(call GluonProfileFactorySuffix,KVM,-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,KVM,-ext4,.img.gz)) -$(eval $(call GluonModel,KVM,combined,x86-kvm)) diff --git a/targets/x86-xen_domu/profiles.mk b/targets/x86-xen_domu/profiles.mk deleted file mode 100644 index c104067b..00000000 --- a/targets/x86-xen_domu/profiles.mk +++ /dev/null @@ -1,4 +0,0 @@ -$(eval $(call GluonProfile,GENERIC)) -$(eval $(call GluonProfileFactorySuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonProfileSysupgradeSuffix,GENERIC,-ext4,.img.gz)) -$(eval $(call GluonModel,GENERIC,combined,x86-xen)) diff --git a/targets/x86.inc b/targets/x86.inc new file mode 100644 index 00000000..d1f21189 --- /dev/null +++ b/targets/x86.inc @@ -0,0 +1,14 @@ +config 'CONFIG_VDI_IMAGES=y' +config 'CONFIG_VMDK_IMAGES=y' + +ATH10K_PACKAGES='kmod-ath10k-ct ath10k-firmware-qca9887 ath10k-firmware-qca988x' +if [ "$GLUON_WLAN_MESH" = 'ibss' ]; then + ATH10K_PACKAGES='kmod-ath10k-ct ath10k-firmware-qca9887-ct ath10k-firmware-qca988x-ct' +fi + +packages 'kmod-3c59x' 'kmod-8139cp' 'kmod-8139too' 'kmod-e100' 'kmod-e1000' 'kmod-e1000e' 'kmod-forcedeth' 'kmod-igb' 'kmod-natsemi' 'kmod-ne2k-pci' +packages 'kmod-pcnet32' 'kmod-r8169' 'kmod-sis900' 'kmod-sky2' 'kmod-tg3' 'kmod-tulip' 'kmod-via-rhine' 'kmod-via-velocity' +packages 'kmod-ath9k' +packages $ATH10K_PACKAGES +packages 'kmod-gpio-button-hotplug' 'kmod-gpio-nct5104d' 'kmod-hwmon-core' 'kmod-hwmon-k10temp' 'kmod-leds-gpio' 'kmod-leds-apu2' 'kmod-sp5100_tco' +packages 'kmod-usb-core' 'kmod-usb-ohci' 'kmod-usb2' 'kmod-usb3' 'kmod-usb-serial'