diff --git a/.github/filters.yml b/.github/filters.yml new file mode 100644 index 00000000..0a812af9 --- /dev/null +++ b/.github/filters.yml @@ -0,0 +1,186 @@ +{ + "ath79-generic": [ + "targets/ath79-generic", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "ath79-nand": [ + "targets/ath79-nand", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "bcm27xx-bcm2708": [ + "targets/bcm27xx-bcm2708", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/bcm27xx.inc" + ], + "bcm27xx-bcm2709": [ + "targets/bcm27xx-bcm2709", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/bcm27xx.inc" + ], + "ipq40xx-generic": [ + "targets/ipq40xx-generic", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "ipq806x-generic": [ + "targets/ipq806x-generic", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "lantiq-xrx200": [ + "targets/lantiq-xrx200", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "lantiq-xway": [ + "targets/lantiq-xway", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "mediatek-mt7622": [ + "targets/mediatek-mt7622", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "mpc85xx-p1010": [ + "targets/mpc85xx-p1010", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "mpc85xx-p1020": [ + "targets/mpc85xx-p1020", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "ramips-mt7620": [ + "targets/ramips-mt7620", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "ramips-mt7621": [ + "targets/ramips-mt7621", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "ramips-mt76x8": [ + "targets/ramips-mt76x8", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "rockchip-armv8": [ + "targets/rockchip-armv8", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "sunxi-cortexa7": [ + "targets/sunxi-cortexa7", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "x86-generic": [ + "targets/x86-generic", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/x86.inc" + ], + "x86-geode": [ + "targets/x86-geode", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ], + "x86-legacy": [ + "targets/x86-legacy", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/x86.inc" + ], + "x86-64": [ + "targets/x86-64", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/x86.inc", + "contrib/ci/minimal-site/**", + "package/**" + ], + "bcm27xx-bcm2710": [ + "targets/bcm27xx-bcm2710", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", + "targets/bcm27xx.inc" + ], + "mvebu-cortexa9": [ + "targets/mvebu-cortexa9", + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk" + ] +} diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 2312b47b..ccd51090 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -14,7 +14,7 @@ jobs: name: docs runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Install Dependencies run: sudo pip3 install sphinx-rtd-theme - name: Build documentation diff --git a/.github/workflows/build-gluon.yml b/.github/workflows/build-gluon.yml index 904612b6..897e7744 100644 --- a/.github/workflows/build-gluon.yml +++ b/.github/workflows/build-gluon.yml @@ -9,43 +9,47 @@ on: - master - next* - v20* - paths: - - "modules" - - "Makefile" - - "scripts/**" - - "package/**" - - "patches/**" - - "targets/**" - - ".github/workflows/build-gluon.yml" pull_request: types: [opened, synchronize, reopened] - paths: - - "modules" - - "Makefile" - - "scripts/**" - - "package/**" - - "patches/**" - - "targets/**" - - ".github/workflows/build-gluon.yml" + jobs: + changed: + runs-on: ubuntu-latest + outputs: + targets: ${{ steps.filter.outputs.changes }} + steps: + - uses: actions/checkout@v2 + + # Filter targets based on changed files + - uses: dorny/paths-filter@v2 + id: filter + with: + filters: .github/filters.yml + build_firmware: + needs: changed strategy: fail-fast: false matrix: - target: [ath79-generic, ath79-nand, bcm27xx-bcm2708, bcm27xx-bcm2709, ipq40xx-generic, ipq806x-generic, lantiq-xrx200, lantiq-xway, mediatek-mt7622, mpc85xx-p1010, mpc85xx-p1020, ramips-mt7620, ramips-mt7621, ramips-mt76x8, ramips-rt305x, rockchip-armv8, sunxi-cortexa7, x86-generic, x86-geode, x86-legacy, x86-64, bcm27xx-bcm2710, mvebu-cortexa9] + # Read back changd targets to create build matrix + target: ${{ fromJSON(needs.changed.outputs.targets) }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + - name: Install Dependencies run: sudo contrib/actions/install-dependencies.sh + - name: Build run: contrib/actions/run-build.sh ${{ matrix.target }} + - name: Archive build logs if: ${{ !cancelled() }} uses: actions/upload-artifact@v1 with: name: ${{ matrix.target }}_logs path: openwrt/logs + - name: Archive build output uses: actions/upload-artifact@v1 with: diff --git a/.github/workflows/check-patches.yml b/.github/workflows/check-patches.yml index 2aeb09fd..f9cb6f11 100644 --- a/.github/workflows/check-patches.yml +++ b/.github/workflows/check-patches.yml @@ -17,7 +17,7 @@ jobs: name: Check patches runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Refresh patches run: make refresh-patches GLUON_SITEDIR="contrib/ci/minimal-site" - name: Show diff diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d079b235..ebc5817e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -8,7 +8,7 @@ jobs: name: Lua runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Install Dependencies run: sudo apt install lua-check - name: Install example site @@ -20,7 +20,7 @@ jobs: name: Shell runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Install Dependencies run: sudo apt install shellcheck - name: Install example site diff --git a/.gitignore b/.gitignore index a929851e..c8127218 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ .bash_history .subversion .wget-hsts +/.scmversion diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 00000000..81f82c55 --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,16 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/conf.py + +# Optionally set the version of Python and requirements required to build your docs +python: + version: 3.8 + install: + - requirements: docs/requirements.txt diff --git a/Makefile b/Makefile index 4ff9f0c6..760335a2 100644 --- a/Makefile +++ b/Makefile @@ -52,6 +52,9 @@ $(eval $(call mkabspath,GLUON_PACKAGEDIR)) $(eval $(call mkabspath,GLUON_TARGETSDIR)) $(eval $(call mkabspath,GLUON_PATCHESDIR)) +GLUON_VERSION := $(shell scripts/getversion.sh '.') +GLUON_SITE_VERSION := $(shell scripts/getversion.sh '$(GLUON_SITEDIR)') + GLUON_MULTIDOMAIN ?= 0 GLUON_AUTOREMOVE ?= 0 GLUON_DEBUG ?= 0 @@ -64,6 +67,7 @@ src-link gluon_base ../../package endef GLUON_VARS = \ + GLUON_VERSION GLUON_SITE_VERSION \ GLUON_RELEASE GLUON_REGION GLUON_MULTIDOMAIN GLUON_AUTOREMOVE GLUON_DEBUG GLUON_MINIFY GLUON_DEPRECATED \ GLUON_DEVICES GLUON_TARGETSDIR GLUON_PATCHESDIR GLUON_TMPDIR GLUON_IMAGEDIR GLUON_PACKAGEDIR GLUON_DEBUGDIR \ GLUON_SITEDIR GLUON_RELEASE GLUON_AUTOUPDATER_BRANCH GLUON_AUTOUPDATER_ENABLED GLUON_LANGS GLUON_BASE_FEEDS \ @@ -100,6 +104,11 @@ refresh-patches: FORCE update-feeds: FORCE @$(GLUON_ENV) scripts/feeds.sh +update-modules: FORCE + @scripts/update-modules.sh + +update-ci: FORCE + @$(GLUON_ENV) scripts/update-ci.sh GLUON_TARGETS := diff --git a/contrib/actions/generate-actions.py b/contrib/actions/generate-actions.py deleted file mode 100755 index 3b3ea8f2..00000000 --- a/contrib/actions/generate-actions.py +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env python3 - -import sys - -ACTIONS_HEAD = """ -# Update this file after adding/removing/renaming a target by running -# `make list-targets BROKEN=1 | ./contrib/actions/generate-actions.py > ./.github/workflows/build-gluon.yml` - -name: Build Gluon -on: - push: - branches: - - master - - next* - - v20* - paths: - - "modules" - - "Makefile" - - "scripts/**" - - "package/**" - - "patches/**" - - "targets/**" - - ".github/workflows/build-gluon.yml" - pull_request: - types: [opened, synchronize, reopened] - paths: - - "modules" - - "Makefile" - - "scripts/**" - - "package/**" - - "patches/**" - - "targets/**" - - ".github/workflows/build-gluon.yml" -jobs: - build_firmware: - strategy: - fail-fast: false - matrix: - target: [{matrix}] - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - name: Install Dependencies - run: sudo contrib/actions/install-dependencies.sh - - name: Build - run: contrib/actions/run-build.sh ${{{{ matrix.target }}}} - - name: Archive build logs - if: ${{{{ !cancelled() }}}} - uses: actions/upload-artifact@v1 - with: - name: ${{{{ matrix.target }}}}_logs - path: openwrt/logs - - name: Archive build output - uses: actions/upload-artifact@v1 - with: - name: ${{{{ matrix.target }}}}_output - path: output -""" - -targets = [] - -for target in sys.stdin: - targets.append(target.strip()) - -output = ACTIONS_HEAD.format(matrix=", ".join(targets)) - -print(output) diff --git a/contrib/actions/generate-target-filters.py b/contrib/actions/generate-target-filters.py new file mode 100755 index 00000000..b74bfe4e --- /dev/null +++ b/contrib/actions/generate-target-filters.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +# Update target filters using +# make update-ci + +import re +import os +import sys +import json + +# these changes trigger rebuilds on all targets +common = [ + "modules", + "Makefile", + "patches/**", + "targets/generic", + "targets/targets.mk", +] + +# these changes are only built on x86-64 +extra = [ + "contrib/ci/minimal-site/**", + "package/**" +] + +_filter = dict() + +# INCLUDE_PATTERN matches: +# include '...' +# include "..." +# include("...") +# include('...') +INCLUDE_PATTERN = "^\\s*include *\\(? *[\"']([^\"']+)[\"']" + +# construct filters map from stdin +for target in sys.stdin: + target = target.strip() + + _filter[target] = [ + f"targets/{target}" + ] + common + + target_file = os.path.join(os.environ['GLUON_TARGETSDIR'], target) + with open(target_file) as f: + includes = re.findall(INCLUDE_PATTERN, f.read(), re.MULTILINE) + _filter[target].extend([f"targets/{i}" for i in includes]) + + if target == "x86-64": + _filter[target].extend(extra) + +# print filters to stdout in json format, because json is stdlib and yaml compatible. +print(json.dumps(_filter, indent=2)) diff --git a/contrib/actions/install-dependencies.sh b/contrib/actions/install-dependencies.sh index bb35cc31..3f21e056 100755 --- a/contrib/actions/install-dependencies.sh +++ b/contrib/actions/install-dependencies.sh @@ -3,6 +3,6 @@ set -e apt-get -y update -apt-get -y install git subversion build-essential python gawk unzip libncurses5-dev zlib1g-dev libssl-dev wget time qemu-utils +apt-get -y install git subversion build-essential python3 gawk unzip libncurses5-dev zlib1g-dev libssl-dev wget time qemu-utils apt-get -y clean rm -rf /var/lib/apt/lists/* diff --git a/contrib/ci/Jenkinsfile b/contrib/ci/Jenkinsfile deleted file mode 100644 index 8acfa492..00000000 --- a/contrib/ci/Jenkinsfile +++ /dev/null @@ -1,82 +0,0 @@ -pipeline { - agent none - environment { - GLUON_SITEDIR = "contrib/ci/minimal-site" - GLUON_TARGET = "x86-64" - BUILD_LOG = "1" - } - stages { - stage('lint') { - parallel { - stage('lint-lua') { - agent { label 'gluon-docker' } - steps { - sh label: 'Identify runner', script: 'echo $SLAVE_NAME' - sh 'make lint-lua' - } - } - stage('lint-sh') { - agent { label 'gluon-docker-v1' } - steps { - sh label: 'Identify runner', script: 'echo $SLAVE_NAME' - sh 'make lint-sh' - } - } - } - } - stage('docs') { - agent { label 'gluon-docker' } - steps { - sh label: 'Identify runner', script: 'echo $SLAVE_NAME' - sh 'make -C docs html' - } - } - stage('build') { - agent { label 'gluon-docker-v2' } - steps { - sh label: 'Identify runner', script: 'echo $SLAVE_NAME' - sh 'make update' - sh 'test -d /dl_cache && ln -s /dl_cache openwrt/dl || true' - timeout(time: 2, unit: "HOURS") { - sh 'make -j$(nproc) V=s' - } - stash includes: '**/output/images/factory/*-x86-64.img.gz', name: 'gluon-x86-64-factory' - } - } - stage('test') { - agent { label 'gluon-vmx' } - steps { - sh label: 'Identify runner', script: 'echo $SLAVE_NAME' - unstash 'gluon-x86-64-factory' - sh label: 'Unpack image', script: 'gunzip -cd ./output/images/factory/*x86-64*.img.gz > ./image.img' - sh label: 'Print python environment', script: 'python3 -m pip freeze' - script { - for (f in findFiles(glob: 'tests/*.py')) { - timeout(time: 10, unit: "MINUTES") { - sh label: "Test ${f.name}", script: "python3 tests/${f.name} --use-tmp-workdir" - } - } - } - } - } - } -} - -/* - api-history: - - Every time the build dependencies of gluon change, the version - every container has to be rebuilt. Therefore, we use Jenkins - labels which intoduce a version number which is documented here. - As soon, as you properly rebuilt your docker container, you - can notify lemoer, that you have updated your node. - - - gluon-docker-v1: - - add shellcheck binary to the build environment - - gluon-docker-v2: - - add qemu-testlab testing, requires KVM virtualization support - - require rsync dependency to be able to build the next branch - - gluon-vmx - - splits the qemu testing from the gluon-docker-v2 label to accomodate - nodes without the vmx cpu flag -*/ diff --git a/contrib/ci/jenkins-community-slave/Dockerfile b/contrib/ci/jenkins-community-slave/Dockerfile deleted file mode 100644 index 5f4de901..00000000 --- a/contrib/ci/jenkins-community-slave/Dockerfile +++ /dev/null @@ -1,33 +0,0 @@ -FROM gluonmesh/build:latest - -USER root - -# this is needed to install default-jre-headless in debian slim images -RUN mkdir -p /usr/share/man/man1 - -RUN apt-get update && apt-get install -y default-jre-headless curl git netcat-openbsd python3 python3-pip qemu-system-x86 iproute2 openssh-client rsync -RUN python3 -m pip install jenkins-webapi sphinx sphinx_rtd_theme gluon-qemu-testlab==0.0.5 - -# Get docker-compose in the agent container -RUN mkdir -p /home/jenkins -RUN mkdir -p /var/lib/jenkins -RUN mkdir -p /remoting -RUN chown gluon /home/jenkins -RUN chown gluon /var/lib/jenkins -RUN chown gluon /remoting - -# Start-up script to attach the slave to the master -ADD slave.py /var/lib/jenkins/slave.py - -USER gluon - -WORKDIR /home/jenkins - -ENV JENKINS_URL "https://build.ffh.zone/" -ENV JENKINS_SLAVE_ADDRESS "" -ENV SLAVE_EXECUTORS "1" -ENV SLAVE_LABELS "docker" -ENV SLAVE_WORING_DIR "" -ENV CLEAN_WORKING_DIR "true" - -CMD [ "python3", "-u", "/var/lib/jenkins/slave.py" ] diff --git a/contrib/ci/jenkins-community-slave/README.md b/contrib/ci/jenkins-community-slave/README.md deleted file mode 100644 index 45ff12ba..00000000 --- a/contrib/ci/jenkins-community-slave/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# Gluon CI using Jenkins - -## Requirements -- Linux system - - with docker installed - - with Hardware Virtualisation (KVM Support) - - Verify using: `lscpu | grep vmx` - - If machine is virtualized host needs to load `kvm_intel` with `nested=1` option and cpuflags need to include `vmx` - -## Architecture - -![Screenshot from 2019-09-24 00-20-32](https://user-images.githubusercontent.com/601153/65468827-9edf2c80-de65-11e9-9fe0-56c3487719c3.png) - -## Installation -You can support the gluon CI with your infrastructure: -1. You need to query @lemoer (freifunk@irrelefant.net) for credentials. -2. He will give you a `SLAVE_NAME` and a `SLAVE_SECRET` for your host. -3. Then go to your docker host and substitute the values for `SLAVE_NAME` and a `SLAVE_SECRET` in the following statements: -``` shell -git clone https://github.com/freifunk-gluon/gluon/ -cd gluon/contrib/ci/jenkins-community-slave/ -docker build -t gluon-jenkins . -mkdir /var/cache/openwrt_dl_cache/ -chown 1000:1000 /var/cache/openwrt_dl_cache -echo "z /dev/kvm 0666 - kvm -" > /etc/tmpfiles.d/kvm.conf -systemd-tmpfiles --create -docker run --detach --restart always \ - --env "SLAVE_NAME=whoareyou" \ - --env "SLAVE_SECRET=changeme" \ - --device /dev/kvm:/dev/kvm \ - --volume /var/cache/openwrt_dl_cache/:/dl_cache \ - gluon-jenkins -``` -4. Check whether the instance is running correctly: - - Your node should appear [here](https://build.ffh.zone/label/gluon-docker/). - - When clicking on it, Jenkins should state "Agent is connected." like here: -![Screenshot from 2019-09-24 01-00-52](https://user-images.githubusercontent.com/601153/65469209-dac6c180-de66-11e9-9d62-0d1c3b6b940b.png) -5. **Your docker container needs to be rebuilt, when the build dependencies of gluon change. As soon as build dependencies have changed, the build dependency api level has to be raised.** After you rebuilt your docker container, notify @lemoer, so he can bump the versioning number. - -## Backoff -- If @lemoer is not reachable, please be patient at first if possible. Otherwise contact info@hannover.freifunk.net or join the channel `#freifunkh` on hackint. diff --git a/contrib/ci/jenkins-community-slave/slave.py b/contrib/ci/jenkins-community-slave/slave.py deleted file mode 100644 index 7efa1f2e..00000000 --- a/contrib/ci/jenkins-community-slave/slave.py +++ /dev/null @@ -1,103 +0,0 @@ -from jenkins import Jenkins, JenkinsError, NodeLaunchMethod -import os -import signal -import sys -import subprocess -import shutil -import requests -import time - -slave_jar = '/var/lib/jenkins/slave.jar' -slave_name = os.environ['SLAVE_NAME'] if os.environ['SLAVE_NAME'] != '' else 'docker-slave-' + os.environ['HOSTNAME'] -jnlp_url = os.environ['JENKINS_URL'] + '/computer/' + slave_name + '/slave-agent.jnlp' -slave_jar_url = os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar' -print(slave_jar_url) -process = None - -def clean_dir(dir): - for root, dirs, files in os.walk(dir): - for f in files: - os.unlink(os.path.join(root, f)) - for d in dirs: - shutil.rmtree(os.path.join(root, d)) - -def slave_create(node_name, working_dir, executors, labels): - j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS']) - j.node_create(node_name, working_dir, num_executors = int(executors), labels = labels, launcher = NodeLaunchMethod.JNLP) - -def slave_delete(node_name): - j = Jenkins(os.environ['JENKINS_URL'], os.environ['JENKINS_USER'], os.environ['JENKINS_PASS']) - j.node_delete(node_name) - -def slave_download(target): - if os.path.isfile(slave_jar): - os.remove(slave_jar) - - r = requests.get(os.environ['JENKINS_URL'] + '/jnlpJars/slave.jar') - with open('/var/lib/jenkins/slave.jar', 'wb') as f: - f.write(r.content) - -def slave_run(slave_jar, jnlp_url): - params = [ 'java', '-jar', slave_jar, '-jnlpUrl', jnlp_url ] - if os.environ['JENKINS_SLAVE_ADDRESS'] != '': - params.extend([ '-connectTo', os.environ['JENKINS_SLAVE_ADDRESS' ] ]) - - if os.environ['SLAVE_SECRET'] == '': - params.extend([ '-jnlpCredentials', os.environ['JENKINS_USER'] + ':' + os.environ['JENKINS_PASS'] ]) - else: - params.extend([ '-secret', os.environ['SLAVE_SECRET'] ]) - return subprocess.Popen(params, stdout=subprocess.PIPE) - -def signal_handler(sig, frame): - if process != None: - process.send_signal(signal.SIGINT) - -signal.signal(signal.SIGINT, signal_handler) -signal.signal(signal.SIGTERM, signal_handler) - -def h(): - print("ERROR!: please specify environment variables") - print("") - print('docker run -e "SLAVE_NAME=test" -e "SLAVE_SECRET=..." jenkins') - -if os.environ.get('SLAVE_NAME') is None: - h() - sys.exit(1) - -if os.environ.get('SLAVE_SECRET') is None: - h() - sys.exit(1) - -def master_ready(url): - try: - r = requests.head(url, timeout=None) - return r.status_code == requests.codes.ok - except: - return False - -while not master_ready(slave_jar_url): - print("Master not ready yet, sleeping for 10sec!") - time.sleep(10) - -slave_download(slave_jar) -print('Downloaded Jenkins slave jar.') - -if os.environ['SLAVE_WORING_DIR']: - os.setcwd(os.environ['SLAVE_WORING_DIR']) - -if os.environ['CLEAN_WORKING_DIR'] == 'true': - clean_dir(os.getcwd()) - print("Cleaned up working directory.") - -if os.environ['SLAVE_NAME'] == '': - slave_create(slave_name, os.getcwd(), os.environ['SLAVE_EXECUTORS'], os.environ['SLAVE_LABELS']) - print('Created temporary Jenkins slave.') - -process = slave_run(slave_jar, jnlp_url) -print('Started Jenkins slave with name "' + slave_name + '" and labels [' + os.environ['SLAVE_LABELS'] + '].') -process.wait() - -print('Jenkins slave stopped.') -if os.environ['SLAVE_NAME'] == '': - slave_delete(slave_name) - print('Removed temporary Jenkins slave.') diff --git a/contrib/ci/minimal-site/site.conf b/contrib/ci/minimal-site/site.conf index b7cb1ac4..3f7373f6 100644 --- a/contrib/ci/minimal-site/site.conf +++ b/contrib/ci/minimal-site/site.conf @@ -64,6 +64,8 @@ outdoor_chanlist = '100-140', ap = { ssid = 'gluon-ci-ssid', + owe_ssid = "owe.gluon-ci-ssid", + owe_transition_mode = false, }, mesh = { -- Adjust these values! diff --git a/contrib/push_pkg.sh b/contrib/push_pkg.sh new file mode 100755 index 00000000..4b9fe740 --- /dev/null +++ b/contrib/push_pkg.sh @@ -0,0 +1,149 @@ +#!/bin/sh + +set -e + +topdir="$(realpath "$(dirname "${0}")/../openwrt")" + +# defaults to qemu run script +ssh_host=localhost +build_only=0 +preserve_config=1 + +print_help() { + echo "$0 [OPTIONS] PACAKGE_DIR [PACKAGE_DIR] ..." + echo "" + echo " -h print this help" + echo " -r HOST use a remote machine as target machine. By default if this" + echo " option is not given, push_pkg.sh will use a locally" + echo " running qemu instance started by run_qemu.sh." + echo " -p PORT use PORT as ssh port (default is 22)" + echo " -b build only, do not push" + echo " -P do not preserve /etc/config. By default, if a package" + echo " defines a config file in /etc/config, this config file" + echo " will be preserved. If you specify this flag, the package" + echo " default will be installed instead." + echo "" + echo ' To change gluon variables, run e.g. "make config GLUON_MINIFY=0"' + echo ' because then the gluon logic will be triggered, and openwrt/.config' + echo ' will be regenerated. The variables from openwrt/.config are already' + echo ' automatically used for this script.' + echo +} + +while getopts "p:r:hbP" opt +do + case $opt in + P) preserve_config=0;; + p) ssh_port="${OPTARG}";; + r) ssh_host="${OPTARG}"; [ -z "$ssh_port" ] && ssh_port=22;; + b) build_only=1;; + h) print_help; exit 0;; + *) ;; + esac +done +shift $(( OPTIND - 1 )) + +[ -z "$ssh_port" ] && ssh_port=2223 + +if [ "$build_only" -eq 0 ]; then + remote_info=$(ssh -p "${ssh_port}" "root@${ssh_host}" ' + source /etc/os-release + printf "%s\t%s\n" "$OPENWRT_BOARD" "$OPENWRT_ARCH" + ') + REMOTE_OPENWRT_BOARD="$(echo "$remote_info" | cut -f 1)" + REMOTE_OPENWRT_ARCH="$(echo "$remote_info" | cut -f 2)" + + # check target + if ! grep -q "CONFIG_TARGET_ARCH_PACKAGES=\"${REMOTE_OPENWRT_ARCH}\"" "${topdir}/.config"; then + echo "Configured OpenWrt Target is not matching with the target machine!" 1>&2 + echo + printf "%s" " Configured architecture: " 1>&2 + grep "CONFIG_TARGET_ARCH_PACKAGES" "${topdir}/.config" 1>&2 + echo "Target machine architecture: ${REMOTE_OPENWRT_ARCH}" 1>&2 + echo 1>&2 + echo "To switch the local with the run with the corresponding GLUON_TARGET:" 1>&2 + echo " make GLUON_TARGET=... config" 1>&2 + exit 1 + fi +fi + +if [ $# -lt 1 ]; then + echo ERROR: Please specify a PACKAGE_DIR. For example: + echo + echo " \$ $0 package/gluon-core" + exit 1 +fi + +while [ $# -gt 0 ]; do + + pkgdir="$1"; shift + echo "Package: ${pkgdir}" + + if ! [ -f "${pkgdir}/Makefile" ]; then + echo "ERROR: ${pkgdir} does not contain a Makefile" + exit 1 + fi + + if ! grep -q BuildPackage "${pkgdir}/Makefile"; then + echo "ERROR: ${pkgdir}/Makefile does not contain a BuildPackage command" + exit 1 + fi + + opkg_packages="$(make TOPDIR="${topdir}" -C "${pkgdir}" DUMP=1 | awk '/^Package: / { print $2 }')" + + search_package() { + find "$2" -name "$1_*.ipk" -printf "%f\n" + } + + make TOPDIR="${topdir}" -C "${pkgdir}" clean + make TOPDIR="${topdir}" -C "${pkgdir}" compile + + if [ "$build_only" -eq 1 ]; then + continue + fi + + # IPv6 addresses need brackets around the ${ssh_host} for scp! + if echo "${ssh_host}" | grep -q :; then + BL=[ + BR=] + fi + + for pkg in ${opkg_packages}; do + + for feed in "${topdir}/bin/packages/${REMOTE_OPENWRT_ARCH}/"*/ "${topdir}/bin/targets/${REMOTE_OPENWRT_BOARD}/packages/"; do + printf "%s" "searching ${pkg} in ${feed}: " + filename=$(search_package "${pkg}" "${feed}") + if [ -n "${filename}" ]; then + echo found! + break + else + echo not found + fi + done + + if [ "$preserve_config" -eq 0 ]; then + opkg_flags=" --force-maintainer" + fi + + # shellcheck disable=SC2029 + if [ -n "$filename" ]; then + scp -P "${ssh_port}" "$feed/$filename" "root@${BL}${ssh_host}${BR}:/tmp/${filename}" + ssh -p "${ssh_port}" "root@${ssh_host}" " + set -e + echo Running opkg: + opkg install --force-reinstall ${opkg_flags} '/tmp/${filename}' + rm '/tmp/${filename}' + gluon-reconfigure + " + else + # Some packages (e.g. procd-seccomp) seem to contain BuildPackage commands + # which do not generate *.ipk files. Till this point, I am not aware why + # this is happening. However, dropping a warning if the corresponding + # *.ipk is not found (maybe due to other reasons as well), seems to + # be more reasonable than aborting. Before this commit, the command + # has failed. + echo "Warning: ${pkg}*.ipk not found! Ignoring." 1>&2 + fi + + done +done diff --git a/contrib/run_qemu.sh b/contrib/run_qemu.sh new file mode 100755 index 00000000..3166f7e0 --- /dev/null +++ b/contrib/run_qemu.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Note: You can exit the qemu instance by first pressing "CTRL + a" then "c". +# Then you enter the command mode of qemu and can exit by typing "quit". + +qemu-system-x86_64 \ + -d 'cpu_reset' \ + -enable-kvm \ + -gdb tcp::1234 \ + -nographic \ + -netdev user,id=wan,hostfwd=tcp::2223-10.0.2.15:22 \ + -device virtio-net-pci,netdev=wan,addr=0x06,id=nic1 \ + -netdev user,id=lan,hostfwd=tcp::6080-192.168.1.1:80,hostfwd=tcp::2222-192.168.1.1:22,net=192.168.1.100/24 \ + -device virtio-net-pci,netdev=lan,addr=0x05,id=nic2 \ + "$@" diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css index 38458950..b4fd2586 100644 --- a/docs/_static/css/custom.css +++ b/docs/_static/css/custom.css @@ -8,38 +8,3 @@ .rst-content div[class^='highlight'] pre { overflow: visible; } - - -/* - This fixes the bottom margin of paragraphs inside lists, where margins inside - a single list item would incorrectly be displayed larger than margins between - the list items. - - Upstream fix (not fixed on readthedocs.io yet): - https://github.com/readthedocs/sphinx_rtd_theme/commit/ac20ce75d426efeb40fe2af1f89ea9bad285a45b -*/ -.rst-content .section ol li > p, -.rst-content .section ol li > p:last-child, -.rst-content .section ul li > p, -.rst-content .section ul li > p:last-child { - margin-bottom: 12px; -} -.rst-content .section ol li > p:only-child, -.rst-content .section ol li > p:only-child:last-child, -.rst-content .section ul li > p:only-child, -.rst-content .section ul li > p:only-child:last-child { - margin-bottom: 0rem; -} - -/* - This fixes the bottom margin of nested lists - - Based on upstream fix (not on readthedocs.io yet): - https://github.com/readthedocs/sphinx_rtd_theme/commit/6f0de13baff93f25204aa2cdf0308aae47d71312 -*/ -.rst-content .section ul li > ul, -.rst-content .section ul li > ol, -.rst-content .section ol li > ul, -.rst-content .section ol li > ol { - margin-bottom: 12px; -} diff --git a/docs/dev/build.rst b/docs/dev/build.rst index 74b9aa11..92fd672b 100644 --- a/docs/dev/build.rst +++ b/docs/dev/build.rst @@ -88,3 +88,17 @@ update.sh source and installs it into *packages/* directory. It simply tries to set the *base* branch of the cloned repo to the correct commit. If this fails it fetches the upstream branch and tries again to set the local *base* branch. + +getversion.sh + Used to determine the version numbers of the repositories of Gluon and the + site configuraiton, to be included in the built firmware images as + */lib/gluon/gluon-version* and */lib/gluon/site-version*. + + By default, this uses ``git describe`` to generate a version number based + on the last git tag. This can be overridden by putting a file called + *.scmversion* into the root of the respective repositories. + + A command like ``rm -f .scmversion; echo "$(./scripts/getversion.sh .)" > .scmversion`` + can be used before applying local patches to ensure that the reported + version numbers refer to an upstream commit ID rather than an arbitrary + local one after ``git am``. diff --git a/docs/dev/packages.rst b/docs/dev/packages.rst index b6032b2e..098b0276 100644 --- a/docs/dev/packages.rst +++ b/docs/dev/packages.rst @@ -3,6 +3,85 @@ Package development Gluon packages are OpenWrt packages and follow the same rules described at https://openwrt.org/docs/guide-developer/packages. +Development workflow +==================== + +When you are developing packages, it often happens that you iteratively want to deploy +and verify the state your development. There are two ways to verify your changes: + +1) One way is to rebuild the complete firmware, flash it, configure it and verify your + development then. This usually takes at least a few minutes to get your changes + working so you can test them. Especially if you iterate a lot, this becomes tedious. +2) Another way is to rebuild only the package you are currently working on and + to deploy this package to your test system. Here not even a reboot is required. + This makes iterating relatively fast. Your test system could be real hardware or + even a qemu in most cases. + +Gluon provides scripts to enhance workflow 2). Here is an example illustrating +the workflow using these scripts: + +.. code-block:: shell + + # start a local qemu instance + contrib/run_qemu.sh output/images/factory/[...]-x86-64.img + + # apply changes to the desired package + vi package/gluon-ebtables/files/etc/init.d/gluon-ebtables + + # rebuild and push the package to the qemu instance + contrib/push_pkg.sh package/gluon-ebtables/ + + # test your changes + ... + + # do more changes + ... + + # rebuild and push the package to the qemu instance + contrib/push_pkg.sh package/gluon-ebtables/ + + # test your changes + ... + + (and so on...) + + # see help of the script for more information + contrib/push_pkg.sh -h + ... + +Features of ``push_pkg.sh``: + +* Works with compiled and non-compiled packages. + + * This means it can be used in the development of C-code, Lua-Code and mostly any other code. + +* Works with native OpenWrt and Gluon packages. +* Pushes to remote machines or local qemu instances. +* Pushes multiple packages in in one call if desired. +* Performs site.conf checks. + +Implementation details of ``push_pkg.sh``: + +* First, the script builds an opkg package using the OpenWrt build system. +* This package is pushed to a *target machine* using scp: + + * By default the *target machine* is a locally running x86 qemu started using ``run_qemu.sh``. + * The *target machine* can also be remote machine. (See the cli switch ``-r``) + * Remote machines are not limited to a specific architecture. All architectures supported by gluon can be used as remote machines. + +* Finally opkg is used to install/update the packages in the target machine. + + * While doing this, it will not override ``/etc/config`` with package defaults by default. (See the cli switch ``-P``). + * While doing this, opkg calls the ``check_site.lua`` from the package as post_install script to validate the ``site.conf``. This means that the ``site.conf`` of the target machine is used for this validation. + +Note that: + +* ``push_pkg.sh`` does neither build nor push dependencies of the packages automatically. If you want to update dependencies, you must explicitly specify them to be pushed. +* If you add new packages, you must run ``make update config GLUON_TARGET=...``. +* You can change the gluon target of the target machine via ``make config GLUON_TARGET=...``. +* If you want to update the ``site.conf`` of the target machine, use ``push_pkg.sh package/gluon-site/``. +* Sometimes when things break, you can heal them by compiling a package with its dependencies: ``cd openwrt; make package/gluon-ebtables/clean; make package/gluon-ebtables/compile; cd ..``. +* You can exit qemu by pressing ``CTRL + a`` and ``c`` afterwards. Gluon package makefiles ======================= diff --git a/docs/index.rst b/docs/index.rst index 4d70c14b..d8e39465 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -78,6 +78,7 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre :caption: Releases :maxdepth: 1 + releases/v2021.1.1 releases/v2021.1 releases/v2020.2.3 releases/v2020.2.2 diff --git a/docs/releases/v2021.1.1.rst b/docs/releases/v2021.1.1.rst new file mode 100644 index 00000000..eeae6541 --- /dev/null +++ b/docs/releases/v2021.1.1.rst @@ -0,0 +1,63 @@ +Gluon 2021.1.1 +============== + +Important notes +--------------- + +Upgrades to v2021.1 and later releases are only supported from releases v2018.2 and later. This is due to migrations that have been removed to simplify maintenance. + + +Added hardware support +---------------------- + + +ath79-generic +~~~~~~~~~~~~~ + +* Joy-IT + + - JT-OR750i + + +ramips-mt76x8 +~~~~~~~~~~~~~ + +* Xiaomi + + - Mi Router 4A (100M Edition) + + +Bugfixes +-------- + +- Missing bandwith limit settings resulted in a respondd crash for v2021.1. + +- The Tunneldigger VPN provider was not registered with the Gluon VPN backend, resulting in broken Tunneldigger configurations. + +- Disabling Radio interfaces in v2021.1 could lead to nullpointer dereferences in the respondd airtime module, as the survey returns no data in this case. + + +Known issues +------------ + +* Upgrading EdgeRouter-X from versions before v2020.1.x may lead to a soft-bricked state due to bad blocks on the NAND flash which the NAND driver before this release does not handle well. + (`#1937 `_) + +* The integration of the BATMAN_V routing algorithm is incomplete. + + - Mesh neighbors don't appear on the status page. (`#1726 `_) + Many tools have the BATMAN_IV metric hardcoded, these need to be updated to account for the new throughput + metric. + - Throughput values are not correctly acquired for different interface types. + (`#1728 `_) + This affects virtual interface types like bridges and VXLAN. + +* 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. + +* In configurations without VXLAN, 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 promiscuous mode is disallowed). diff --git a/docs/requirements.txt b/docs/requirements.txt index 6c5d5d44..f85be1ff 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1 @@ -sphinx-rtd-theme +sphinx-rtd-theme==0.5.2 diff --git a/docs/site-example/site.mk b/docs/site-example/site.mk index 48e2d8a9..cff17523 100644 --- a/docs/site-example/site.mk +++ b/docs/site-example/site.mk @@ -17,6 +17,9 @@ GLUON_FEATURES := \ web-advanced \ web-wizard +GLUON_FEATURES_standard := \ + wireless-encryption-wpa3 + ## GLUON_SITE_PACKAGES # Specify additional Gluon/OpenWrt packages to include here; # A minus sign may be prepended to remove a packages from the diff --git a/docs/user/getting_started.rst b/docs/user/getting_started.rst index e22a11a5..7cf00834 100644 --- a/docs/user/getting_started.rst +++ b/docs/user/getting_started.rst @@ -29,7 +29,7 @@ freshly installed Debian Stretch system the following packages are required: * `git` (to get Gluon and other dependencies) * `subversion` -* `python` (Python 3 doesn't work) +* `python3` * `build-essential` * `gawk` * `unzip` diff --git a/docs/user/supported_devices.rst b/docs/user/supported_devices.rst index e605bd33..f243270e 100644 --- a/docs/user/supported_devices.rst +++ b/docs/user/supported_devices.rst @@ -13,14 +13,26 @@ ath79-generic - WiFi pro 1750i - WiFi pro 1750x +* Enterasys + + - WS-AP3705i + * GL.iNet - GL-AR300M-Lite +* Joy-IT + + - JT-OR750i + * OCEDO - Raccoon +* Onion + + - Omega [#modular_ethernet]_ + * Plasma Cloud - PA300 @@ -34,6 +46,12 @@ ath79-generic - Archer C6 (v2) - CPE220 (v3.0) + - CPE510 (v2.0) + - CPE510 (v3.0) + - EAP225-Outdoor (v1) + - TL-WDR3600 (v1) + - TL-WDR4300 (v1) + - WBS210 (v2.0) ath79-nand ---------- @@ -59,7 +77,11 @@ ipq40xx-generic * Aruba - AP-303 + - AP-303H + - AP-365 - Instant On AP11 + - Instant On AP11D + - Instant On AP17 * AVM @@ -206,12 +228,13 @@ ramips-mt7621 - EdgeRouter X - EdgeRouter X-SFP + - UniFi 6 Lite * ZBT - WG3526-16M - WG3526-32M - + * Xiaomi - Xiaomi Mi Router 4A (Gigabit Edition) @@ -226,16 +249,22 @@ ramips-mt76x8 * GL.iNet - GL-MT300N (v2) + - microuter-N300 - VIXMINI * NETGEAR - R6120 +* RAVPower + + - RP-WD009 + * TP-Link - Archer C50 (v3) - Archer C50 (v4) + - RE200 (v2) - TL-MR3020 (v3) - TL-MR3420 (v5) - TL-WA801ND (v5) @@ -251,13 +280,6 @@ ramips-mt76x8 - Xiaomi Mi Router 4A (100M Edition) - Xiaomi Mi Router 4C -ramips-rt305x [#deprecated]_ [#device-class-tiny]_ ---------------------------------------------------- - -* VoCore - - - VoCore (8M, 16M) - rockchip-armv8 -------------- @@ -300,10 +322,6 @@ See also: :doc:`x86` Footnotes --------- -.. [#deprecated] - The device or target is reaching its end of life soon. This means that support - in the next major release of Gluon is doubtful. - .. [#device-class-tiny] These devices only support a subset of Gluons capabilities due to flash or memory size constraints. Devices are classified as tiny in they provide less than 7M of usable @@ -319,3 +337,10 @@ Footnotes .. [#lan_as_wan] All LAN ports on this device are used as WAN. + +.. [#modular_ethernet] + These devices follow a modular principle, + which means even basic functionality like ethernet is provided by an expansion-board, + that may not be bundled with the device itself. + Such expansions are recommended for the config mode, but are not strictly necessary, + as exposed serial ports may grant sufficient access as well. diff --git a/modules b/modules index 07814d3f..97d8043f 100644 --- a/modules +++ b/modules @@ -2,15 +2,15 @@ GLUON_FEEDS='packages routing gluon' OPENWRT_REPO=https://github.com/openwrt/openwrt.git OPENWRT_BRANCH=openwrt-21.02 -OPENWRT_COMMIT=d666ebcaa327a1e03992a484d9601ea5f2e6b19a +OPENWRT_COMMIT=dec9e8395605d9ff3f1eb09f9dfb7d743939ee37 PACKAGES_PACKAGES_REPO=https://github.com/openwrt/packages.git PACKAGES_PACKAGES_BRANCH=openwrt-21.02 -PACKAGES_PACKAGES_COMMIT=5fa605a1fa76bc68e3f70122713e592a1b25f068 +PACKAGES_PACKAGES_COMMIT=f71a9c91cb44f4e50fbfb53ce5666fa0097d61a0 PACKAGES_ROUTING_REPO=https://github.com/openwrt/routing.git PACKAGES_ROUTING_BRANCH=openwrt-21.02 -PACKAGES_ROUTING_COMMIT=2baff33918c089fd3744c7192f8ae7a29c47a8d7 +PACKAGES_ROUTING_COMMIT=da7d7a0255efec87c1b0a511d6082e86754cba7e PACKAGES_GLUON_REPO=https://github.com/freifunk-gluon/packages.git -PACKAGES_GLUON_COMMIT=825aa0c093d6c0b4f81a95cd2320331a5b5adae6 +PACKAGES_GLUON_COMMIT=52d7ac4aea7dc17c639c96ad9e179137ca66e614 diff --git a/package/features b/package/features index 72887e3a..c6e94a1a 100644 --- a/package/features +++ b/package/features @@ -16,7 +16,7 @@ when(_'web-wizard' and _'autoupdater', { 'gluon-config-mode-autoupdater', }) -when(_'web-wizard' and (_'mesh-vpn-fastd' or _'mesh-vpn-tunneldigger'), { +when(_'web-wizard' and (_'mesh-vpn-fastd' or _'mesh-vpn-tunneldigger' or _'mesh-vpn-wireguard'), { 'gluon-config-mode-mesh-vpn', }) diff --git a/package/gluon-alfred/Makefile b/package/gluon-alfred/Makefile index 7c173a77..fd7e7120 100644 --- a/package/gluon-alfred/Makefile +++ b/package/gluon-alfred/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-alfred -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-authorized-keys/Makefile b/package/gluon-authorized-keys/Makefile index d5b3a907..3cbca241 100644 --- a/package/gluon-authorized-keys/Makefile +++ b/package/gluon-authorized-keys/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-authorized-keys -PKG_VERSION:=2 include ../gluon.mk diff --git a/package/gluon-autoupdater/Makefile b/package/gluon-autoupdater/Makefile index 368dce1b..61a8ba21 100644 --- a/package/gluon-autoupdater/Makefile +++ b/package/gluon-autoupdater/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-autoupdater -PKG_VERSION:=4 PKG_CONFIG_DEPENDS := CONFIG_GLUON_AUTOUPDATER_BRANCH CONFIG_GLUON_AUTOUPDATER_ENABLED diff --git a/package/gluon-client-bridge/Makefile b/package/gluon-client-bridge/Makefile index a2daf34b..d1005d86 100644 --- a/package/gluon-client-bridge/Makefile +++ b/package/gluon-client-bridge/Makefile @@ -1,13 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-client-bridge -PKG_VERSION:=1 include ../gluon.mk define Package/gluon-client-bridge TITLE:=Provides a bridge and a wireless interface for clients to connect to - DEPENDS:=+gluon-core +kmod-veth +@GLUON_SPECIALIZE_KERNEL:KERNEL_VETH + DEPENDS:=+gluon-core +kmod-veth endef $(eval $(call BuildPackageGluon,gluon-client-bridge)) diff --git a/package/gluon-config-mode-autoupdater/Makefile b/package/gluon-config-mode-autoupdater/Makefile index b94d3b45..d5a9d7f7 100644 --- a/package/gluon-config-mode-autoupdater/Makefile +++ b/package/gluon-config-mode-autoupdater/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-autoupdater -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-contact-info/Makefile b/package/gluon-config-mode-contact-info/Makefile index ad27ffa2..d7382b58 100644 --- a/package/gluon-config-mode-contact-info/Makefile +++ b/package/gluon-config-mode-contact-info/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-contact-info -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-core/Makefile b/package/gluon-config-mode-core/Makefile index b9c39487..0c3a0f42 100644 --- a/package/gluon-config-mode-core/Makefile +++ b/package/gluon-config-mode-core/Makefile @@ -4,7 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-core -PKG_VERSION:=2 include ../gluon.mk diff --git a/package/gluon-config-mode-domain-select/Makefile b/package/gluon-config-mode-domain-select/Makefile index b1ded939..98897752 100644 --- a/package/gluon-config-mode-domain-select/Makefile +++ b/package/gluon-config-mode-domain-select/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-domain-select -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-geo-location-osm/Makefile b/package/gluon-config-mode-geo-location-osm/Makefile index 4dbaf9d0..2e101223 100644 --- a/package/gluon-config-mode-geo-location-osm/Makefile +++ b/package/gluon-config-mode-geo-location-osm/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-geo-location-osm -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-geo-location/Makefile b/package/gluon-config-mode-geo-location/Makefile index a020feb9..7c7f8079 100644 --- a/package/gluon-config-mode-geo-location/Makefile +++ b/package/gluon-config-mode-geo-location/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-geo-location -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-geo-location/i18n/de.po b/package/gluon-config-mode-geo-location/i18n/de.po index 67769329..f3a7ba8a 100644 --- a/package/gluon-config-mode-geo-location/i18n/de.po +++ b/package/gluon-config-mode-geo-location/i18n/de.po @@ -32,9 +32,6 @@ msgstr "Längengrad" msgid "Set node position" msgstr "Knotenposition setzen" -msgid "Advertise node position" -msgstr "Knotenposition veröffentlichen" - msgid "" "Specifying the altitude is optional; it should only be filled in if an " "accurate value is known." diff --git a/package/gluon-config-mode-geo-location/i18n/fr.po b/package/gluon-config-mode-geo-location/i18n/fr.po index 34680a30..d6c0a00f 100644 --- a/package/gluon-config-mode-geo-location/i18n/fr.po +++ b/package/gluon-config-mode-geo-location/i18n/fr.po @@ -30,9 +30,6 @@ msgstr "Longitude" msgid "Set node position" msgstr "" -msgid "Advertise node position" -msgstr "" - msgid "" "Specifying the altitude is optional; it should only be filled in if an " "accurate value is known." diff --git a/package/gluon-config-mode-hostname/Makefile b/package/gluon-config-mode-hostname/Makefile index fdf3acd9..8285f5bb 100644 --- a/package/gluon-config-mode-hostname/Makefile +++ b/package/gluon-config-mode-hostname/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-hostname -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-mesh-vpn/Makefile b/package/gluon-config-mode-mesh-vpn/Makefile index 0c3a752d..b55d532a 100644 --- a/package/gluon-config-mode-mesh-vpn/Makefile +++ b/package/gluon-config-mode-mesh-vpn/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-mesh-vpn -PKG_VERSION:=2 include ../gluon.mk diff --git a/package/gluon-config-mode-outdoor/Makefile b/package/gluon-config-mode-outdoor/Makefile index 2f3acfcd..049cf52e 100644 --- a/package/gluon-config-mode-outdoor/Makefile +++ b/package/gluon-config-mode-outdoor/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-outdoor -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-config-mode-theme/Makefile b/package/gluon-config-mode-theme/Makefile index 38858f0c..7f20fbdb 100644 --- a/package/gluon-config-mode-theme/Makefile +++ b/package/gluon-config-mode-theme/Makefile @@ -4,7 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-config-mode-theme -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-core/Config.in b/package/gluon-core/Config.in deleted file mode 100644 index 6550ec7e..00000000 --- a/package/gluon-core/Config.in +++ /dev/null @@ -1,360 +0,0 @@ -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_ETH - bool - -config KERNEL_L2TP - bool - select KERNEL_L2TP_V3 - 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_ACT_POLICE - bool - select KERNEL_NET_CLS_ACT - -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_DNAT - 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 - -config KERNEL_BRIDGE_EBT_REDIRECT - 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 - -config KERNEL_IP_NF_RAW - bool - select KERNEL_IP_NF_IPTABLES - -config KERNEL_NETFILTER_XT_TARGET_CT - bool - select KERNEL_NETFILTER_XTABLES - select KERNEL_NF_CONNTRACK - select KERNEL_IP_NF_RAW - - -# 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_NETFILTER_XT_TARGET_CT - select KERNEL_IP_NF_NAT - select KERNEL_IP_NF_TARGET_MASQUERADE - select KERNEL_IP_NF_TARGET_REDIRECT - -config GLUON_MINIFY - bool "Minify Gluon scripts" - default y diff --git a/package/gluon-core/Makefile b/package/gluon-core/Makefile index 37aaa3f2..c56b78bb 100644 --- a/package/gluon-core/Makefile +++ b/package/gluon-core/Makefile @@ -2,10 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-core -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) +PKG_CONFIG_DEPENDS := CONFIG_GLUON_VERSION include ../gluon.mk include $(INCLUDE_DIR)/cmake.mk @@ -22,14 +19,26 @@ define Package/gluon-core/description endef define Package/gluon-core/config - source "$(SOURCE)/Config.in" +config GLUON_VERSION + string "Gluon version number" + depends on PACKAGE_gluon-core + default "" + +config GLUON_MINIFY + bool "Minify Gluon scripts" + default y +endef + +define Package/gluon-core/conffiles +/etc/config/gluon +/etc/config/gluon-core endef define Package/gluon-core/install $(Gluon/Build/Install) $(INSTALL_DIR) $(1)/lib/gluon - echo '$(GLUON_VERSION)' > $(1)/lib/gluon/gluon-version + echo '$(call qstrip,$(CONFIG_GLUON_VERSION))' > $(1)/lib/gluon/gluon-version endef $(eval $(call BuildPackageGluon,gluon-core)) diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua index 3966592d..4cb44d5b 100644 --- a/package/gluon-core/check_site.lua +++ b/package/gluon-core/check_site.lua @@ -26,7 +26,9 @@ need_string(in_site({'timezone'})) need_string_array({'ntp_servers'}, false) +need_string_match(in_domain({'prefix4'}), '^%d+.%d+.%d+.%d+/%d+$', false) need_string_match(in_domain({'prefix6'}), '^[%x:]+/64$') +need_string_array_match(in_domain({'extra_prefixes6'}), '^[%x:]+/%d+$', false) local supported_rates = {6000, 9000, 12000, 18000, 24000, 36000, 48000, 54000} for _, config in ipairs({'wifi24', 'wifi5'}) do diff --git a/scripts/check_site.lua b/package/gluon-core/luasrc/lib/gluon/check-site.lua similarity index 97% rename from scripts/check_site.lua rename to package/gluon-core/luasrc/lib/gluon/check-site.lua index 43765f80..6861d8cb 100644 --- a/scripts/check_site.lua +++ b/package/gluon-core/luasrc/lib/gluon/check-site.lua @@ -360,7 +360,7 @@ end function M.need_domain_name(path) M.need_string(path) M.need(path, function(domain_name) - local f = io.open(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/domains/' .. domain_name .. '.json') + local f = io.open((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/domains/' .. domain_name .. '.json') if not f then return false end f:close() return true @@ -383,7 +383,7 @@ end local check = setfenv(assert(loadfile()), M) -site = assert(json.load(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/site.json')) +site = assert(json.load((os.getenv('IPKG_INSTROOT') or '') .. '/lib/gluon/site.json')) local ok, err = pcall(function() if has_domains then diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces index f9ab73c5..d2814968 100755 --- a/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces +++ b/package/gluon-core/luasrc/lib/gluon/upgrade/020-interfaces @@ -78,11 +78,6 @@ end uci:delete('network', 'lan') uci:delete('network', 'wan') -uci:foreach('network', 'device', function(dev) - if dev['type'] ~= 'bridge' then return end - if dev['ifname'] ~= 'lan' and dev['ifname'] ~= 'wan' then return end - - uci:delete('network', dev['.name']) -end) +uci:delete_all('network', 'device') uci:save('network') diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua index 5bfe534e..9c4974ea 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/platform.lua @@ -30,10 +30,15 @@ function M.is_outdoor_device() 'plasmacloud,pa300', 'plasmacloud,pa300e', 'tplink,cpe220-v3', + 'tplink,cpe510-v2', + 'tplink,cpe510-v3', + 'tplink,eap225-outdoor-v1', + 'tplink,wbs210-v2', }) then return true elseif M.match('ipq40xx', 'generic', { + 'aruba,ap-365', 'engenius,ens620ext', 'plasmacloud,pa1200', }) then @@ -44,11 +49,6 @@ function M.is_outdoor_device() end function M.device_supports_wpa3() - -- rt2x00 crashes when enabling WPA3 personal / OWE VAP - if M.match('ramips', 'rt305x') then - return false - end - return unistd.access('/lib/gluon/features/wpa3') 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 index a5d13a5b..48b8340e 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/util.lua @@ -1,6 +1,8 @@ local bit = require 'bit' +local posix_fcntl = require 'posix.fcntl' local posix_glob = require 'posix.glob' local posix_syslog = require 'posix.syslog' +local posix_unistd = require 'posix.unistd' local hash = require 'hash' local sysconfig = require 'gluon.sysconfig' local site = require 'gluon.site' @@ -193,4 +195,76 @@ function M.log(message, verbose) posix_syslog.syslog(posix_syslog.LOG_INFO, message) end +local function close_fds(fds) + for _, fd in pairs(fds) do + posix_unistd.close(fd) + end +end + +M.subprocess = {} + +M.subprocess.DEVNULL = -1 +M.subprocess.PIPE = 1 + +-- Execute a program found using command PATH search, like the shell. +-- Return the pid, as well as the I/O streams as pipes or nil on error. +function M.subprocess.popen(path, argt, options) + argt = argt or {} + local childfds = {} + local parentfds = {} + local stdiostreams = {stdin = 0, stdout = 1, stderr = 2} + + for iostream in pairs(stdiostreams) do + if options[iostream] == M.subprocess.PIPE then + local piper, pipew = posix_unistd.pipe() + if iostream == "stdin" then + childfds[iostream] = piper + parentfds[iostream] = pipew + else + childfds[iostream] = pipew + parentfds[iostream] = piper + end + end + end + + -- childfds: r0, w1, w2 + -- parentfds: w0, r1, r2 + + local pid, errmsg, errnum = posix_unistd.fork() + + if pid == nil then + close_fds(parentfds) + close_fds(childfds) + return nil, errmsg, errnum + elseif pid == 0 then + local null = -1 + if M.contains(options, M.subprocess.DEVNULL) then + -- only open if there's anything to discard + null = posix_fcntl.open('/dev/null', posix_fcntl.O_RDWR) + end + + for iostream, fd in pairs(stdiostreams) do + local option = options[iostream] + if option == M.subprocess.DEVNULL then + posix_unistd.dup2(null, fd) + elseif option == M.subprocess.PIPE then + posix_unistd.dup2(childfds[iostream], fd) + end + end + close_fds(childfds) + close_fds(parentfds) + + -- close potential null + if null > 2 then + posix_unistd.close(null) + end + + posix_unistd.execp(path, argt) + posix_unistd._exit(127) + end + + close_fds(childfds) + + return pid, parentfds +end return M diff --git a/package/gluon-core/luasrc/usr/lib/lua/gluon/wireless.lua b/package/gluon-core/luasrc/usr/lib/lua/gluon/wireless.lua index 4f2cf088..0eb68023 100644 --- a/package/gluon-core/luasrc/usr/lib/lua/gluon/wireless.lua +++ b/package/gluon-core/luasrc/usr/lib/lua/gluon/wireless.lua @@ -2,16 +2,42 @@ local sysconfig = require 'gluon.sysconfig' local site = require 'gluon.site' local util = require 'gluon.util' +local unistd = require 'posix.unistd' +local dirent = require 'posix.dirent' + local M = {} local function find_phy_by_path(path) - local phy = util.glob('/sys/devices/' .. path .. '/ieee80211/phy*')[1] - or util.glob('/sys/devices/platform/' .. path .. '/ieee80211/phy*')[1] + local device_path, phy_offset = string.match(path, "^(.+)%+(%d+)$") - if phy then - return phy:match('([^/]+)$') + -- Special handling required for multi-phy devices + if device_path == nil then + device_path = path + phy_offset = '0' end + + -- Find the device path. Either it's located at /sys/devices or /sys/devices/platform + local path_prefix = '' + if not unistd.access('/sys/devices/' .. device_path .. '/ieee80211') then + path_prefix = 'platform/' + end + + -- Get all available PHYs of the device and dertermine the one with the lowest index + local phy_names = dirent.dir('/sys/devices/' .. path_prefix .. device_path .. '/ieee80211') + local device_phy_idxs = {} + for _, v in ipairs(phy_names) do + local phy_idx = v:match('^phy(%d+)$') + + if phy_idx ~= nil then + table.insert(device_phy_idxs, tonumber(phy_idx)) + end + end + + table.sort(device_phy_idxs) + + -- Index starts at 1 + return 'phy' .. device_phy_idxs[tonumber(phy_offset) + 1] end local function find_phy_by_macaddr(macaddr) diff --git a/package/gluon-ebtables-filter-multicast/Makefile b/package/gluon-ebtables-filter-multicast/Makefile index dc579a2a..92b2be2a 100644 --- a/package/gluon-ebtables-filter-multicast/Makefile +++ b/package/gluon-ebtables-filter-multicast/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-ebtables-filter-multicast -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-ebtables-filter-ra-dhcp/Makefile b/package/gluon-ebtables-filter-ra-dhcp/Makefile index c650bb89..bc52747a 100644 --- a/package/gluon-ebtables-filter-ra-dhcp/Makefile +++ b/package/gluon-ebtables-filter-ra-dhcp/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-ebtables-filter-ra-dhcp -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-ebtables-limit-arp/Makefile b/package/gluon-ebtables-limit-arp/Makefile index f7bdc48d..5f71b1c8 100644 --- a/package/gluon-ebtables-limit-arp/Makefile +++ b/package/gluon-ebtables-limit-arp/Makefile @@ -1,17 +1,12 @@ 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 + DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv endef define Package/gluon-ebtables-limit-arp/description diff --git a/package/gluon-ebtables-source-filter/Makefile b/package/gluon-ebtables-source-filter/Makefile index 2c14a793..17377e1f 100644 --- a/package/gluon-ebtables-source-filter/Makefile +++ b/package/gluon-ebtables-source-filter/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-ebtables-source-filter -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-ebtables-source-filter/check_site.lua b/package/gluon-ebtables-source-filter/check_site.lua deleted file mode 100644 index 56d229c0..00000000 --- a/package/gluon-ebtables-source-filter/check_site.lua +++ /dev/null @@ -1,2 +0,0 @@ -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/Makefile b/package/gluon-ebtables/Makefile index ca83fcf4..e69a83bf 100644 --- a/package/gluon-ebtables/Makefile +++ b/package/gluon-ebtables/Makefile @@ -1,24 +1,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-ebtables -PKG_VERSION:=1 -PKG_RELEASE:=1 - -PKG_CONFIG_DEPENDS := CONFIG_GLUON_SPECIALIZE_KERNEL include ../gluon.mk define Package/gluon-ebtables TITLE:=Ebtables support 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 + +kmod-ebtables +kmod-ebtables-ipv4 +kmod-ebtables-ipv6 endef define Package/gluon-ebtables/description diff --git a/package/gluon-hoodselector/Makefile b/package/gluon-hoodselector/Makefile index 394deeae..9706a605 100644 --- a/package/gluon-hoodselector/Makefile +++ b/package/gluon-hoodselector/Makefile @@ -2,9 +2,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-hoodselector -GLUON_VERSION:=3 -PKG_VERSION:=2 - include ../gluon.mk define Package/gluon-hoodselector diff --git a/package/gluon-iptables-clamp-mss-to-pmtu/Makefile b/package/gluon-iptables-clamp-mss-to-pmtu/Makefile index c3f84988..b8135c2f 100644 --- a/package/gluon-iptables-clamp-mss-to-pmtu/Makefile +++ b/package/gluon-iptables-clamp-mss-to-pmtu/Makefile @@ -2,9 +2,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-iptables-clamp-mss-to-pmtu -GLUON_VERSION = $(shell git describe --always --dirty=+ 2>/dev/null || echo unknown) -PKG_VERSION:=$(if $(DUMP),x,$(GLUON_VERSION)) - include ../gluon.mk define Package/$(PKG_NAME) diff --git a/package/gluon-l3roamd/Makefile b/package/gluon-l3roamd/Makefile index 0702749f..4259bb85 100644 --- a/package/gluon-l3roamd/Makefile +++ b/package/gluon-l3roamd/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-l3roamd -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-l3roamd/check_site.lua b/package/gluon-l3roamd/check_site.lua index f1e98a13..4e80ca2e 100644 --- a/package/gluon-l3roamd/check_site.lua +++ b/package/gluon-l3roamd/check_site.lua @@ -1,3 +1 @@ -need_string_match(in_domain({'prefix6'}), '^[%x:]+/64$', true) need_string_match(in_domain({'node_client_prefix6'}), '^[%x:]+/64$', false) -need_string_match(in_domain({'prefix4'}), '^%d+.%d+.%d+.%d+/%d+$', false) diff --git a/package/gluon-lock-password/Makefile b/package/gluon-lock-password/Makefile index 366fd7b8..2275d33e 100644 --- a/package/gluon-lock-password/Makefile +++ b/package/gluon-lock-password/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-lock-password -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-logging/Makefile b/package/gluon-logging/Makefile index 735a6f9e..dde7bcd2 100644 --- a/package/gluon-logging/Makefile +++ b/package/gluon-logging/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-logging -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-mesh-babel/Makefile b/package/gluon-mesh-babel/Makefile index bdc3d4bc..3abe66df 100644 --- a/package/gluon-mesh-babel/Makefile +++ b/package/gluon-mesh-babel/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mesh-babel -PKG_VERSION:=1 PKG_BUILD_DEPENDS := libbabelhelper PKG_BUILD_DEPENDS += libjson-c diff --git a/package/gluon-mesh-batman-adv/Makefile b/package/gluon-mesh-batman-adv/Makefile index eac84ac5..aac41f1b 100644 --- a/package/gluon-mesh-batman-adv/Makefile +++ b/package/gluon-mesh-batman-adv/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mesh-batman-adv -PKG_VERSION:=1 include ../gluon.mk @@ -19,10 +18,7 @@ define Package/gluon-mesh-batman-adv-15 +kmod-dummy \ +libnl-tiny \ +libbatadv \ - +batctl \ - +@GLUON_SPECIALIZE_KERNEL:KERNEL_DUMMY \ - +@GLUON_SPECIALIZE_KERNEL:KERNEL_CRC16 \ - +@GLUON_SPECIALIZE_KERNEL:KERNEL_LIBCRC32C + +batctl endef $(eval $(call BuildPackageGluon,gluon-mesh-batman-adv-15)) diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_default_gw4 b/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_default_gw4 new file mode 100755 index 00000000..96aa9bd4 --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_default_gw4 @@ -0,0 +1,2 @@ +#!/bin/sh +out=$(batctl gwl -H 2>/dev/null) && [ -n "$out" ] diff --git a/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_neighbours b/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_neighbours new file mode 100755 index 00000000..67d389ce --- /dev/null +++ b/package/gluon-mesh-batman-adv/files/lib/gluon/state/check.d/has_neighbours @@ -0,0 +1,2 @@ +#!/bin/sh +out=$(batctl n -H 2>/dev/null) && [ -n "$out" ] diff --git a/package/gluon-mesh-vpn-core/Makefile b/package/gluon-mesh-vpn-core/Makefile index 1acf17ca..3679e2bc 100644 --- a/package/gluon-mesh-vpn-core/Makefile +++ b/package/gluon-mesh-vpn-core/Makefile @@ -1,21 +1,12 @@ 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_ACT_POLICE \ - +@GLUON_SPECIALIZE_KERNEL:KERNEL_NET_SCH_TBF \ - +@GLUON_SPECIALIZE_KERNEL:KERNEL_NET_SCH_INGRESS + DEPENDS:=+gluon-core +gluon-wan-dnsmasq +iptables +iptables-mod-extra +simple-tc USERID:=:gluon-mesh-vpn=800 endef diff --git a/package/gluon-mesh-vpn-core/files/lib/netifd/proto/gluon_wireguard.sh b/package/gluon-mesh-vpn-core/files/lib/netifd/proto/gluon_wireguard.sh new file mode 100755 index 00000000..05eaad53 --- /dev/null +++ b/package/gluon-mesh-vpn-core/files/lib/netifd/proto/gluon_wireguard.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +PROTO_DEBUG=1 + +. /lib/functions.sh +. ../netifd-proto.sh +init_proto "$@" + +WG=/usr/bin/wg + +proto_gluon_wireguard_init_config() { + proto_config_add_int index + proto_config_add_int mtu +} + +interface_linklocal_from_wg_public_key() { + # We generate a predictable v6 address + local macaddr="$(printf "%s" "$1"|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/')" + local oldIFS="$IFS"; IFS=':'; + # shellcheck disable=SC2086 + set -- $macaddr; IFS="$oldIFS" + echo "fe80::$1$2:$3ff:fe$4:$5$6" +} + +proto_gluon_wireguard_setup() { + local config="$1" + local ifname="$2" + + local index mtu + json_get_vars index mtu + + local public_key="$(/lib/gluon/mesh-vpn/wireguard_pubkey.sh)" + + # The wireguard proto itself can not be moved here, as the proto does not + # allow add_dynamic. + + wireguard_ip=$(interface_linklocal_from_wg_public_key "$public_key") + + ## Add IP + + proto_add_host_dependency "$config" '' "$ifname" + proto_init_update "$ifname" 1 + proto_add_data + json_add_string zone 'wired_mesh' + proto_close_data + proto_add_ipv6_address "$wireguard_ip" "128" + proto_send_update "$ifname" + + ## wgpeerselector + + json_init + json_add_string name "${ifname}_peerselector" + json_add_string ifname "$ifname" + json_add_string proto 'wgpeerselector' + json_add_string unix_group 'gluon-mesh-vpn' + json_add_boolean transitive 1 + json_close_object + ubus call network add_dynamic "$(json_dump)" + + ## vxlan + + json_init + json_add_string name "mesh-vpn" + json_add_string proto 'vxlan6' + json_add_string tunlink "$ifname" + # ip6addr (the lower interface ip6) is used by the vxlan.sh proto + json_add_string ip6addr "$wireguard_ip" + json_add_string peer6addr "fe80::1" + json_add_int vid "$(lua -e 'print(tonumber(require("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)" + + proto_init_update "$ifname" 1 + proto_send_update "$config" +} + +proto_gluon_wireguard_teardown() { + local config="$1" + + proto_init_update "*" 0 + proto_send_update "$config" +} + +add_protocol gluon_wireguard 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 index 58bfa30e..a476afdb 100755 --- 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 @@ -54,6 +54,8 @@ if not uci:get('gluon', 'mesh_vpn') then else enabled = site.mesh_vpn.enabled(false) end + -- wireguard is not listed here, as it didn't exist before the uci section + -- gluon.mesh_vpn was introduced. Therefore no migration is necessary. local limit_enabled = tonumber((uci:get('simple-tc', 'mesh_vpn', 'enabled'))) diff --git a/package/gluon-mesh-vpn-fastd/Makefile b/package/gluon-mesh-vpn-fastd/Makefile index 087aff5f..cb6f6da4 100644 --- a/package/gluon-mesh-vpn-fastd/Makefile +++ b/package/gluon-mesh-vpn-fastd/Makefile @@ -1,13 +1,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mesh-vpn-fastd -PKG_VERSION:=3 include ../gluon.mk define Package/gluon-mesh-vpn-fastd TITLE:=Support for connecting meshes via fastd - DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +fastd +@GLUON_SPECIALIZE_KERNEL:KERNEL_TUN + DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +fastd endef $(eval $(call BuildPackageGluon,gluon-mesh-vpn-fastd)) diff --git a/package/gluon-mesh-vpn-tunneldigger/Makefile b/package/gluon-mesh-vpn-tunneldigger/Makefile index b7a5f18d..3a206e81 100644 --- a/package/gluon-mesh-vpn-tunneldigger/Makefile +++ b/package/gluon-mesh-vpn-tunneldigger/Makefile @@ -1,13 +1,12 @@ 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 + DEPENDS:=+gluon-core +gluon-mesh-vpn-core +tunneldigger endef $(eval $(call BuildPackageGluon,gluon-mesh-vpn-tunneldigger)) diff --git a/package/gluon-mesh-vpn-wireguard/Makefile b/package/gluon-mesh-vpn-wireguard/Makefile new file mode 100644 index 00000000..cae8781a --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/Makefile @@ -0,0 +1,12 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-mesh-vpn-wireguard + +include ../gluon.mk + +define Package/gluon-mesh-vpn-wireguard + TITLE:=Support for connecting meshes via wireguard + DEPENDS:=+gluon-core +libgluonutil +gluon-mesh-vpn-core +wireguard-tools +@GLUON_SPECIALIZE_KERNEL:KERNEL_TUN +wgpeerselector +libubus +endef + +$(eval $(call BuildPackageGluon,gluon-mesh-vpn-wireguard)) diff --git a/package/gluon-mesh-vpn-wireguard/check_site.lua b/package/gluon-mesh-vpn-wireguard/check_site.lua new file mode 100644 index 00000000..f5a0d94e --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/check_site.lua @@ -0,0 +1,9 @@ +local function check_peer(k) + need_alphanumeric_key(k) + + need_string_match(in_domain(extend(k, + {'public_key'})), "^" .. ("[%a%d+/]"):rep(42) .. "[AEIMQUYcgkosw480]=$") + need_string(in_domain(extend(k, {'endpoint'}))) +end + +need_table({'mesh_vpn', 'wireguard', 'peers'}, check_peer) diff --git a/package/gluon-mesh-vpn-wireguard/files/lib/gluon/mesh-vpn/provider/wireguard b/package/gluon-mesh-vpn-wireguard/files/lib/gluon/mesh-vpn/provider/wireguard new file mode 100644 index 00000000..e69de29b diff --git a/package/gluon-mesh-vpn-wireguard/files/lib/gluon/mesh-vpn/wireguard_pubkey.sh b/package/gluon-mesh-vpn-wireguard/files/lib/gluon/mesh-vpn/wireguard_pubkey.sh new file mode 100755 index 00000000..bbcba571 --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/files/lib/gluon/mesh-vpn/wireguard_pubkey.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +INCLUDE_ONLY=1 +. /lib/netifd/proto/wireguard.sh + +ensure_key_is_generated wg_mesh +uci get "network.wg_mesh.private_key" | /usr/bin/wg pubkey diff --git a/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard b/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard new file mode 100755 index 00000000..dfadc95b --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/luasrc/lib/gluon/upgrade/400-mesh-vpn-wireguard @@ -0,0 +1,39 @@ +#!/usr/bin/lua + +local uci = require('simple-uci').cursor() +local site = require 'gluon.site' + +local private_key = uci:get("network", 'wg_mesh', "private_key") + +if not private_key or not private_key:match("^" .. ("[%a%d+/]"):rep(42) .. "[AEIMQUYcgkosw480]=$") then + private_key = "generate" +end + +uci:section('network', 'interface', 'wg_mesh', { + proto = 'wireguard', + fwmark = 1, + private_key = private_key, +}) + +uci:section('network', 'interface', 'mesh_wg_mesh', { + ifname = 'wg_mesh', + proto = 'gluon_wireguard' +}) + +-- Clean up previous configuration +uci:delete_all('wgpeerselector', 'peer', function(peer) + return peer.preserve ~= '1' +end) + +for name, peer in pairs(site.mesh_vpn.wireguard.peers()) do + uci:section("wgpeerselector", "peer", name, { + enabled = true, + endpoint = peer.endpoint, + public_key = peer.public_key, + allowed_ips = { "fe80::1/128" }, + ifname = 'wg_mesh', + }) +end + +uci:save("wgpeerselector") +uci:save("network") diff --git a/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua b/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua new file mode 100644 index 00000000..5065e217 --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/luasrc/usr/lib/lua/gluon/mesh-vpn/provider/wireguard.lua @@ -0,0 +1,37 @@ +local uci = require('simple-uci').cursor() + +local site = require 'gluon.site' +local util = require 'gluon.util' +local vpn_core = require 'gluon.mesh-vpn' + +local M = {} + +function M.public_key() + return util.trim(util.exec("/lib/gluon/mesh-vpn/wireguard_pubkey.sh")) +end + +function M.enable(val) + uci:set('network', 'wg_mesh', 'disabled', not val) + uci:save('network') +end + +function M.active() + return site.mesh_vpn.wireguard() ~= nil +end + +function M.set_limit(ingress_limit, egress_limit) + -- TODO: Test that limiting this via simple-tc here is correct! + uci:delete('simple-tc', 'mesh_vpn') + if ingress_limit ~= nil and egress_limit ~= nil then + uci:section('simple-tc', 'interface', 'mesh_vpn', { + ifname = vpn_core.get_interface(), + enabled = true, + limit_egress = egress_limit, + limit_ingress = ingress_limit, + }) + end + + uci:save('simple-tc') +end + +return M diff --git a/package/gluon-mesh-vpn-wireguard/src/Makefile b/package/gluon-mesh-vpn-wireguard/src/Makefile new file mode 100644 index 00000000..0b027848 --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/src/Makefile @@ -0,0 +1,6 @@ +all: respondd.so + +CFLAGS += -Wall -Werror-implicit-function-declaration + +respondd.so: respondd.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -fPIC -D_GNU_SOURCE -o $@ $^ $(LDLIBS) -lgluonutil -lubus diff --git a/package/gluon-mesh-vpn-wireguard/src/respondd.c b/package/gluon-mesh-vpn-wireguard/src/respondd.c new file mode 100644 index 00000000..59f6511c --- /dev/null +++ b/package/gluon-mesh-vpn-wireguard/src/respondd.c @@ -0,0 +1,231 @@ +/* + Copyright (c) 2020, Leonardo Mörlein + 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 +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "libubus.h" + +static struct json_object * stdout_read(const char *cmd, const char *skip, bool oneword) { + FILE *f = popen(cmd, "r"); + if (!f) + return NULL; + + char *line = NULL; + size_t len = 0; + size_t skiplen = strlen(skip); + + ssize_t read_chars = getline(&line, &len, f); + + pclose(f); + + if (read_chars < 1) { + free(line); + return NULL; + } + + if (line[read_chars-1] == '\n') + line[read_chars-1] = '\0'; + + const char *content = line; + if (strncmp(content, skip, skiplen) == 0) + content += skiplen; + + if (oneword) { + for (int i = 0; i < len; i++) { + if (isspace(line[i])) { + line[i] = 0; + } + } + } + + struct json_object *ret = gluonutil_wrap_string(content); + free(line); + return ret; +} + +static struct json_object * get_wireguard_public_key(void) { + return stdout_read("exec /lib/gluon/mesh-vpn/wireguard_pubkey.sh", "", false); +} + +static struct json_object * get_wireguard_version(void) { + return stdout_read("exec wg -v", "wireguard-tools ", true); +} + +static bool wireguard_enabled(void) { + bool enabled = true; + + struct uci_context *ctx = uci_alloc_context(); + if (!ctx) + goto disabled_nofree; + ctx->flags &= ~UCI_FLAG_STRICT; + + struct uci_package *p; + if (uci_load(ctx, "network", &p)) + goto disabled; + + struct uci_section *s = uci_lookup_section(ctx, p, "wg_mesh"); + if (!s) + goto disabled; + + const char *disabled_str = uci_lookup_option_string(ctx, s, "disabled"); + if (!disabled_str || !strcmp(disabled_str, "1")) + enabled = false; + +disabled: + uci_free_context(ctx); + +disabled_nofree: + return enabled; +} + +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_wireguard(void) { + bool wg_enabled = wireguard_enabled(); + + struct json_object *ret = json_object_new_object(); + json_object_object_add(ret, "version", get_wireguard_version()); + json_object_object_add(ret, "enabled", json_object_new_boolean(wg_enabled)); + if (wg_enabled && !get_pubkey_privacy()) + json_object_object_add(ret, "public_key", get_wireguard_public_key()); + return ret; +} + +static struct json_object * respondd_provider_nodeinfo(void) { + struct json_object *ret = json_object_new_object(); + + struct json_object *software = json_object_new_object(); + json_object_object_add(software, "wireguard", get_wireguard()); + json_object_object_add(ret, "software", software); + + return ret; +} + +static json_object *blobmsg_attr2json(struct blob_attr *attr, int type) +{ + int len = blobmsg_data_len(attr); + struct blobmsg_data *data = blobmsg_data(attr); + struct blob_attr *inner_attr; + json_object *res = NULL; + switch(type) { + case BLOBMSG_TYPE_STRING: + return gluonutil_wrap_string(blobmsg_get_string(attr)); + case BLOBMSG_TYPE_BOOL: + return json_object_new_boolean(blobmsg_get_bool(attr)); + case BLOBMSG_TYPE_INT16: + return json_object_new_double(blobmsg_get_u16(attr)); + case BLOBMSG_TYPE_INT32: + return json_object_new_double(blobmsg_get_u32(attr)); + case BLOBMSG_TYPE_INT64: + return json_object_new_double(blobmsg_get_u64(attr)); + case BLOBMSG_TYPE_DOUBLE: + return json_object_new_double(blobmsg_get_double(attr)); + case BLOBMSG_TYPE_TABLE: + res = json_object_new_object(); + __blob_for_each_attr(inner_attr, data, len) { + json_object_object_add(res, blobmsg_name(inner_attr), blobmsg_attr2json(inner_attr, blobmsg_type(inner_attr))); + }; + break; + case BLOBMSG_TYPE_ARRAY: + res = json_object_new_array(); + __blob_for_each_attr(inner_attr, data, len) { + json_object_array_add(res, blobmsg_attr2json(inner_attr, blobmsg_type(inner_attr))); + } + break; + } + + return res; +} + +static void cb_wgpeerselector_vpn(struct ubus_request *req, int type, struct blob_attr *msg) +{ + json_object_object_add(req->priv, "mesh_vpn", blobmsg_attr2json(msg, type)); +} + +static struct json_object * respondd_provider_statistics(void) { + struct json_object *ret = json_object_new_object(); + struct ubus_context *ctx = ubus_connect(NULL); + uint32_t ubus_path_id; + + if (!ctx) { + fprintf(stderr, "Error in gluon-mesh-vpn-wireguard.so: Failed to connect to ubus.\n"); + goto err; + } + + if (ubus_lookup_id(ctx, "wgpeerselector.wg_mesh", &ubus_path_id)) { + goto err; + } + + ubus_invoke(ctx, ubus_path_id, "status", NULL, cb_wgpeerselector_vpn, ret, 1000); + +err: + if (ctx) + ubus_free(ctx); + return ret; +} + + +const struct respondd_provider_info respondd_providers[] = { + {"nodeinfo", respondd_provider_nodeinfo}, + {"statistics", respondd_provider_statistics}, + {} +}; diff --git a/package/gluon-mesh-wireless-sae/Makefile b/package/gluon-mesh-wireless-sae/Makefile index e17ee850..3fe755ab 100644 --- a/package/gluon-mesh-wireless-sae/Makefile +++ b/package/gluon-mesh-wireless-sae/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mesh-wireless-sae -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-mmfd/Makefile b/package/gluon-mmfd/Makefile index dc66bf4f..4e767db5 100644 --- a/package/gluon-mmfd/Makefile +++ b/package/gluon-mmfd/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-mmfd -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-neighbour-info/Makefile b/package/gluon-neighbour-info/Makefile index af58036c..903cb02c 100644 --- a/package/gluon-neighbour-info/Makefile +++ b/package/gluon-neighbour-info/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-neighbour-info -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-neighbour-info/src/gluon-neighbour-info.c b/package/gluon-neighbour-info/src/gluon-neighbour-info.c index 6470508c..a45a94c8 100644 --- a/package/gluon-neighbour-info/src/gluon-neighbour-info.c +++ b/package/gluon-neighbour-info/src/gluon-neighbour-info.c @@ -69,8 +69,23 @@ void tv_subtract (struct timeval *r, const struct timeval *a, const struct timev } } -ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) { +void resize_recvbuffer(char **recvbuffer, size_t *recvbuffer_len, size_t recvlen) +{ + free(*recvbuffer); + *recvbuffer = malloc(recvlen); + + if (!(*recvbuffer)) { + perror("Could not resize recvbuffer"); + exit(EXIT_FAILURE); + } + + *recvbuffer_len = recvlen; +} + +ssize_t recvtimeout(int socket, char **recvbuffer, size_t *recvbuffer_len, + const struct timeval *timeout) { struct timeval now, timeout_left; + ssize_t recvlen; getclock(&now); tv_subtract(&timeout_left, timeout, &now); @@ -79,18 +94,28 @@ ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const st return -1; setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left)); - return recv(socket, buffer, length, flags); + + recvlen = recv(socket, *recvbuffer, 0, MSG_PEEK | MSG_TRUNC); + if (recvlen < 0) + return recvlen; + + if (recvlen > *recvbuffer_len) + resize_recvbuffer(recvbuffer, recvbuffer_len, recvlen); + + return recv(socket, *recvbuffer, *recvbuffer_len, 0); } -int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) { +int request(const int sock, char **recvbuffer, size_t *recvbuffer_len, + const struct sockaddr_in6 *client_addr, const char *request, + const char *sse, double timeout, unsigned int max_count) { ssize_t ret; - char buffer[8192]; unsigned int count = 0; ret = sendto(sock, request, strlen(request), 0, (struct sockaddr *)client_addr, sizeof(struct sockaddr_in6)); if (ret < 0) { perror("Error in sendto()"); + free(*recvbuffer); exit(EXIT_FAILURE); } @@ -105,7 +130,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char * } do { - ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout); + ret = recvtimeout(sock, recvbuffer, recvbuffer_len, &tv_timeout); if (ret < 0) break; @@ -116,7 +141,7 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char * fputs("data: ", stdout); } - fwrite(buffer, sizeof(char), ret, stdout); + fwrite(*recvbuffer, sizeof(char), ret, stdout); if (sse) fputs("\n\n", stdout); @@ -137,6 +162,8 @@ int main(int argc, char **argv) { int sock; struct sockaddr_in6 client_addr = {}; char *request_string = NULL; + char *recvbuffer = NULL; + size_t recvbuffer_len = 0; sock = socket(PF_INET6, SOCK_DGRAM, 0); @@ -242,12 +269,16 @@ int main(int argc, char **argv) { fflush(stdout); } + resize_recvbuffer(&recvbuffer, &recvbuffer_len, 8192); + do { - ret = request(sock, &client_addr, request_string, sse, timeout, max_count); + ret = request(sock, &recvbuffer, &recvbuffer_len, &client_addr, + request_string, sse, timeout, max_count); } while(loop); if (sse) fputs("event: eot\ndata: null\n\n", stdout); + free(recvbuffer); return ret; } diff --git a/package/gluon-node-info/Makefile b/package/gluon-node-info/Makefile index 7718fa2b..20bae57b 100644 --- a/package/gluon-node-info/Makefile +++ b/package/gluon-node-info/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-node-info -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk @@ -11,4 +9,8 @@ define Package/gluon-node-info DEPENDS:=+gluon-core +libgluonutil endef +define Package/gluon-node-info/conffiles +/etc/config/gluon-node-info +endef + $(eval $(call BuildPackageGluon,gluon-node-info)) diff --git a/package/gluon-private-wifi/Makefile b/package/gluon-private-wifi/Makefile index 622334b5..0e0080ae 100644 --- a/package/gluon-private-wifi/Makefile +++ b/package/gluon-private-wifi/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-private-wifi -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-radv-filterd/Makefile b/package/gluon-radv-filterd/Makefile index 28d778c1..4cab8960 100644 --- a/package/gluon-radv-filterd/Makefile +++ b/package/gluon-radv-filterd/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-radv-filterd -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-radvd/Makefile b/package/gluon-radvd/Makefile index a3957530..430374e4 100644 --- a/package/gluon-radvd/Makefile +++ b/package/gluon-radvd/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-radvd -PKG_VERSION:=3 include ../gluon.mk diff --git a/package/gluon-respondd/Makefile b/package/gluon-respondd/Makefile index 52839a86..2fda9007 100644 --- a/package/gluon-respondd/Makefile +++ b/package/gluon-respondd/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-respondd -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-scheduled-domain-switch/Makefile b/package/gluon-scheduled-domain-switch/Makefile index b1d7f786..6d79c221 100644 --- a/package/gluon-scheduled-domain-switch/Makefile +++ b/package/gluon-scheduled-domain-switch/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-scheduled-domain-switch -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-setup-mode/Makefile b/package/gluon-setup-mode/Makefile index dfc1717a..5ee9117c 100644 --- a/package/gluon-setup-mode/Makefile +++ b/package/gluon-setup-mode/Makefile @@ -4,7 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-setup-mode -PKG_VERSION:=1 include ../gluon.mk @@ -17,6 +16,10 @@ define Package/gluon-setup-mode/description Offline mode to perform basic setup in a secure manner. endef +define Package/gluon-setup-mode/conffiles +/etc/config/gluon-setup-mode +endef + init_links := \ K89log \ K98boot \ diff --git a/package/gluon-site/Makefile b/package/gluon-site/Makefile index 9b01ec4d..4bad6ec1 100644 --- a/package/gluon-site/Makefile +++ b/package/gluon-site/Makefile @@ -3,15 +3,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-site 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_CONFIG_DEPENDS := CONFIG_GLUON_SITE_VERSION 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-jsonc/host gluon-web/host -PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) - include ../gluon.mk PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG) @@ -21,6 +17,11 @@ define Package/gluon-site endef define Package/gluon-site/config +config GLUON_SITE_VERSION + string "Gluon site version number" + depends on PACKAGE_gluon-site + default "" + config GLUON_RELEASE string "Gluon release number" depends on PACKAGE_gluon-site @@ -83,7 +84,7 @@ define Package/gluon-site/install $(CP) $(PKG_BUILD_DIR)/domains $(1)/lib/gluon/ endif - echo '$(GLUON_SITE_VERSION)' > $(1)/lib/gluon/site-version + echo '$(call qstrip,$(CONFIG_GLUON_SITE_VERSION))' > $(1)/lib/gluon/site-version echo '$(call qstrip,$(CONFIG_GLUON_RELEASE))' > $(1)/lib/gluon/release $(GluonInstallI18N) diff --git a/package/gluon-state-check/Makefile b/package/gluon-state-check/Makefile new file mode 100644 index 00000000..14028d88 --- /dev/null +++ b/package/gluon-state-check/Makefile @@ -0,0 +1,27 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=gluon-state-check + +include ../gluon.mk + +define Package/gluon-state-check + TITLE:=Provides info about the routers state + DEPENDS:=+gluon-core +micrond +endef + +define Package/gluon-state-check/description + gluon-state-check executes checks in `/lib/gluon/state/check.d/` and provides + a flag file for each check in `/var/gluon/state` depending on the return code + of the check. A flag file is created (or "touched") if the corresponding check + exits cleanly and gets removed otherwise. If the flags are "touched", they + are only accessed, but not modified. In this way, the atime of a flag file + reflects when the last check was performed and the mtime reflects when + when the state was last changed. + + This package provides the following checks: + - `has_default_gw6` - check whether the router has a default IPv6-route on br-client. + + The checks are executed once every minute (by micron.d). +endef + +$(eval $(call BuildPackageGluon,gluon-state-check)) diff --git a/package/gluon-state-check/files/lib/gluon/state/check.d/has_default_gw6 b/package/gluon-state-check/files/lib/gluon/state/check.d/has_default_gw6 new file mode 100755 index 00000000..d099a60d --- /dev/null +++ b/package/gluon-state-check/files/lib/gluon/state/check.d/has_default_gw6 @@ -0,0 +1,2 @@ +#!/bin/sh +out=$(ip -6 route show default dev br-client 2>/dev/null) && [ -n "$out" ] diff --git a/package/gluon-state-check/files/usr/lib/micron.d/gluon-state-check b/package/gluon-state-check/files/usr/lib/micron.d/gluon-state-check new file mode 100644 index 00000000..312dadfb --- /dev/null +++ b/package/gluon-state-check/files/usr/lib/micron.d/gluon-state-check @@ -0,0 +1 @@ +* * * * * /usr/sbin/gluon-state-check diff --git a/package/gluon-state-check/luasrc/usr/sbin/gluon-state-check b/package/gluon-state-check/luasrc/usr/sbin/gluon-state-check new file mode 100755 index 00000000..04348f9f --- /dev/null +++ b/package/gluon-state-check/luasrc/usr/sbin/gluon-state-check @@ -0,0 +1,41 @@ +#!/usr/bin/lua + +local util = require 'gluon.util' +local unistd = require 'posix.unistd' + +local state_dir = "/var/gluon/state/" +local check_dir = "/lib/gluon/state/check.d/" + + +local function set_flag(stateflag, state) + if state then + -- this does not modify atime + local flaghandle = io.open(stateflag, "w") + flaghandle:close() + else + os.remove(stateflag) + end +end + +local function exec_check(checkpath) + local checkname = string.sub(checkpath, #check_dir+1) + local ret = os.execute(checkpath) + local flagfile = state_dir..checkname + set_flag(flagfile, 0==ret) +end + +local function run_executable_checks() + for _, v in ipairs(util.glob(check_dir..'*')) do + if unistd.access(v, 'x') then + exec_check(v) + end + end +end + + +-- ensure state path exists +if not unistd.access(state_dir) then + os.execute("mkdir -p "..state_dir) +end + +run_executable_checks() diff --git a/package/gluon-status-page-mesh-batman-adv/Makefile b/package/gluon-status-page-mesh-batman-adv/Makefile index 4d2ed8f0..0fc8781f 100644 --- a/package/gluon-status-page-mesh-batman-adv/Makefile +++ b/package/gluon-status-page-mesh-batman-adv/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-status-page-mesh-batman-adv -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-status-page/Makefile b/package/gluon-status-page/Makefile index c30229e3..b4eea874 100644 --- a/package/gluon-status-page/Makefile +++ b/package/gluon-status-page/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-status-page -PKG_VERSION:=3 include ../gluon.mk 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 index 861c13a4..bdce64fb 100644 --- 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 @@ -29,17 +29,31 @@ local mesh = get_mesh() - local function get_interfaces() - local uconn = ubus.connect() - if not uconn then - error('failed to connect to ubus') - end + local function get_interfaces(uconn) local interfaces = util.get_mesh_devices(uconn) - ubus.close(uconn) table.sort(interfaces) return interfaces end + local function get_radios(uconn) + local radios = uconn:call("network.wireless", "status", {}) + local ret = {} + + for radio, info in pairs(radios) do + if info.up then + table.insert(ret, { + name = radio, + channel = info.config.channel, + }) + end + end + + table.sort(ret, function(a, b) + return a.name < b.name + end) + return ret + end + local function is_wireless(iface) while true do local pattern = '/sys/class/net/' .. iface .. '/lower_*' @@ -52,7 +66,15 @@ return unistd.access('/sys/class/net/' .. iface .. '/wireless') ~= nil end - local interfaces = get_interfaces() + local uconn = ubus.connect() + if not uconn then + error('failed to connect to ubus') + end + + local interfaces = get_interfaces(uconn) + local radios = get_radios(uconn) + + ubus.close(uconn) local function sorted(t) t = {unpack(t)} @@ -66,12 +88,17 @@ local function formatBits(bits) local units = {[0]='', 'k', 'M', 'G'} + local unit = 0 - local pow = math.floor(math.log(math.max(math.abs(bits), 1)) / math.log(1000)) - local known_pow = math.min(pow, #units) + for i = 1, #units do + if math.abs(bits) < 1000 then + break + end + unit = i + bits = bits / 1000 + end - local significand = bits/(1000^known_pow) - return string.format('%g %sbit', significand, units[known_pow]) + return string.format('%g %sbit', bits, units[unit]) end local function statistics(key, format) @@ -135,12 +162,12 @@ <% if nodeinfo.network.mesh_vpn.bandwidth_limit.enabled then -%>
<%:Bandwidth limit%>
- <% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%> - ▲ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%>
- <%- end %> <% if nodeinfo.network.mesh_vpn.bandwidth_limit.ingress then -%> ▼ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.ingress*1000) %>/s <%:downstream%> <%- end %> + <% if nodeinfo.network.mesh_vpn.bandwidth_limit.egress then -%> + ▲ <%| formatBits(nodeinfo.network.mesh_vpn.bandwidth_limit.egress*1000) %>/s <%:upstream%>
+ <%- end %>
<%- end %> <%- end %> @@ -190,11 +217,17 @@ <%:Wireless 2.4 GHz%><%= statistics('clients/wifi24') %> <%:Wireless 5 GHz%><%= statistics('clients/wifi5') %> - + <%- end %>

<%:Traffic%>

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 index 3fe35c37..21c3c692 100644 --- 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 @@ -1 +1 @@ -"use strict";!function(){var r=JSON.parse(document.body.getAttribute("data-translations"));function i(t,e){return t.toFixed(e).replace(/\./,r["."])}function o(t,e){e--;for(var n=t;10<=n&&0Channel "+(2484===(t=t.frequency)?14:2412<=t&&t<=2472?(t-2407)/5:5160<=t&&t<=5885?(t-5e3)/5:"unknown"),e.appendChild(n),i.appendChild(e)})}else e.style.display="none"}var n=document.querySelectorAll("[data-statistics]");d("/cgi-bin/dyn/statistics",function(o,a){var c=o.uptime-a.uptime;n.forEach(function(t){var e=t.getAttribute("data-statistics"),n=t.getAttribute("data-format"),i=l(a,e),e=l(o,e);try{var r=s[n](e,i,c);void 0!==r&&(t.textContent=r)}catch(t){console.error(t)}});try{t(o.mesh_vpn)}catch(t){console.error(t)}try{e(o.wireless)}catch(t){console.error(t)}});var c={};function A(n){var i=document.createElement("canvas"),r=i.getContext("2d"),o=null;return{canvas:i,highlight:!1,resize:function(t,e){try{r.getImageData(0,0,t,e)}catch(t){}i.width=t,i.height=e},draw:function(t,e){e=e(o);r.clearRect(t,0,5,i.height),e&&(t=t,e=e,r.beginPath(),r.fillStyle=n,r.arc(t,e,1.2,0,2*Math.PI,!1),r.closePath(),r.fill())},set:function(t){o=t}}}function h(){var c=-100,s=0,n=0,i=[],l=document.createElement("canvas");l.className="signalgraph",l.height=200;var u=l.getContext("2d");function t(){l.width=l.clientWidth,i.forEach(function(t){t.resize(l.width,l.height)})}function r(){var e;0!==l.clientWidth&&(l.width!==l.clientWidth&&t(),u.clearRect(0,0,l.width,l.height),e=!1,i.forEach(function(t){t.highlight&&(e=!0)}),u.save(),i.forEach(function(t){e&&(u.globalAlpha=.2),t.highlight&&(u.globalAlpha=1),t.draw(n,function(t){return e=t,n=c,i=s,t=l.height,(1-(e-n)/(i-n))*t;var e,n,i}),u.drawImage(t.canvas,0,0)}),u.restore(),u.save(),u.beginPath(),u.strokeStyle="rgba(255, 180, 0, 0.15)",u.lineWidth=5,u.moveTo(n+2.5,0),u.lineTo(n+2.5,l.height),u.stroke(),function(){var t=Math.floor(l.height/40);u.save(),u.lineWidth=.5,u.strokeStyle="rgba(0, 0, 0, 0.25)",u.fillStyle="rgba(0, 0, 0, 0.5)",u.textAlign="end",u.textBaseline="bottom",u.beginPath();for(var e,n,i,r=0;re[0]||t[1]e[1]?1:0});t=t[0][2];return t&&!/^fe80:/i.test(t)?t:void 0}}return t.wireless&&((g=a.insertCell()).textContent="-",g.setAttribute("data-label",o.children[Object.keys(l).length+1].textContent),(v=a.insertCell()).textContent="-",v.setAttribute("data-label",o.children[Object.keys(l).length+2].textContent),(m=a.insertCell()).textContent="-",m.setAttribute("data-label",o.children[Object.keys(l).length+3].textContent),p=A(n),t.signalgraph.addSignal(p)),a.onmouseenter=function(){a.classList.add("highlight"),p&&(p.highlight=!0)},a.onmouseleave=function(){a.classList.remove("highlight"),p&&(p.highlight=!1)},C(),{get_hostname:function(){return s.textContent},update_nodeinfo:function(t){var e,n,i,r,o=w(t.network.addresses);o&&("span"===s.nodeName.toLowerCase()&&(r=s,s=document.createElement("a"),r.parentNode.replaceChild(s,r)),s.href="http://["+o+"]/"),s.textContent=t.hostname,x&&t.location&&(e=x.latitude,n=x.longitude,i=t.location.latitude,r=t.location.longitude,o=Math.PI/180,t=(i*=o)-(e*=o),n=(r*=o)-(n*=o),i=Math.sin(t/2)*Math.sin(t/2)+Math.sin(n/2)*Math.sin(n/2)*Math.cos(e)*Math.cos(i),i=6372.8*(2*Math.asin(Math.sqrt(i))),v.textContent=Math.round(1e3*i)+" m"),C()},update_mesh:function(n){Object.keys(l).forEach(function(t){var e=l[t];e.td.textContent=n[t]+e.suffix}),C()},update_wifi:function(t){g.textContent=t.signal,m.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200e[0]||t[1]e[1]?1:0});t=t[0][2];return t&&!/^fe80:/i.test(t)?t:void 0}}return t.wireless&&((g=a.insertCell()).textContent="-",g.setAttribute("data-label",i.children[Object.keys(s).length+1].textContent),(v=a.insertCell()).textContent="-",v.setAttribute("data-label",i.children[Object.keys(s).length+2].textContent),(p=a.insertCell()).textContent="-",p.setAttribute("data-label",i.children[Object.keys(s).length+3].textContent),m=A(e),t.signalgraph.addSignal(m)),a.onmouseenter=function(){a.classList.add("highlight"),m&&(m.highlight=!0)},a.onmouseleave=function(){a.classList.remove("highlight"),m&&(m.highlight=!1)},y(),{get_hostname:function(){return u.textContent},get_addr:function(){return o},update_nodeinfo:function(t){var e,n,r,i,a;(o=E(t.network.addresses))&&("span"===u.nodeName.toLowerCase()&&(a=u,u=document.createElement("a"),a.parentNode.replaceChild(u,a)),u.href="http://["+o+"]/"),u.textContent=t.hostname,x&&t.location&&(e=x.latitude,n=x.longitude,r=t.location.latitude,i=t.location.longitude,a=Math.PI/180,t=(r*=a)-(e*=a),n=(i*=a)-(n*=a),r=Math.sin(t/2)*Math.sin(t/2)+Math.sin(n/2)*Math.sin(n/2)*Math.cos(e)*Math.cos(r),r=6372.8*(2*Math.asin(Math.sqrt(r))),v.textContent=Math.round(1e3*r)+" m"),y()},update_mesh:function(n){Object.keys(s).forEach(function(t){var e=s[t];e.td.textContent=n[t]+e.suffix}),y()},update_wifi:function(t){g.textContent=t.signal,p.textContent=Math.round(t.inactive/1e3)+" s",a.classList.toggle("inactive",200Channel " + channel(radio.frequency); - tr.appendChild(td); - - table.appendChild(tr); - }); - } - var statisticsElems = document.querySelectorAll('[data-statistics]'); add_event_source('/cgi-bin/dyn/statistics', function(data, dataPrev) { @@ -264,9 +228,16 @@ 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; + var format_result = formats[format](value, valuePrev, diff); + switch (typeof format_result) { + case "object": + if (elem.lastChild) + elem.removeChild(elem.lastChild); + elem.appendChild(format_result); + break; + default: + elem.textContent = format_result; + } } catch (e) { console.error(e); } @@ -277,11 +248,6 @@ } catch (e) { console.error(e); } - try { - update_radios(data.wireless); - } catch (e) { - console.error(e); - } }) function haversine(lat1, lon1, lat2, lon2) { @@ -319,7 +285,7 @@ 'resize': function(w, h) { var lastImage; try { - ctx.getImageData(0, 0, w, h); + lastImage = ctx.getImageData(0, 0, w, h); } catch (e) {} canvas.width = w; canvas.height = h; @@ -492,6 +458,7 @@ } var hostname = document.createElement("span"); + var addr; hostname.textContent = addr; tdHostname.appendChild(hostname); @@ -552,13 +519,13 @@ el.classList.add("highlight"); if (signal) signal.highlight = true; - } + }; el.onmouseleave = function () { - el.classList.remove("highlight") + el.classList.remove("highlight"); if (signal) signal.highlight = false; - } + }; var timeout; @@ -586,7 +553,8 @@ var n = parts.length; var groups = []; - parts.forEach(function(part, i) { + for (var i = 0; i < parts.length; i++) { + var part = parts[i]; if (part === '') { while (n++ <= 8) groups.push(0); @@ -596,7 +564,7 @@ groups.push(parseInt(part, 16)); } - }); + }; return groups; } @@ -664,8 +632,11 @@ 'get_hostname': function() { return hostname.textContent; }, + 'get_addr': function() { + return addr; + }, 'update_nodeinfo': function(nodeinfo) { - var addr = choose_address(nodeinfo.network.addresses); + addr = choose_address(nodeinfo.network.addresses); if (addr) { if (hostname.nodeName.toLowerCase() === 'span') { var oldHostname = hostname; 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 index ceb5d855..80c5e50a 100644 --- 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 @@ -61,7 +61,7 @@ local function match(a, b, n) 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 nodeinfo = json.parse(util.exec('exec gluon-neighbour-info -d ::1 -p 1001 -t 3 -c 1 -r nodeinfo')) local node_ip = parse_ip(http:getenv('SERVER_ADDR')) if node_ip and ( diff --git a/package/gluon-wan-dnsmasq/Makefile b/package/gluon-wan-dnsmasq/Makefile index adbe0f78..da42cf01 100644 --- a/package/gluon-wan-dnsmasq/Makefile +++ b/package/gluon-wan-dnsmasq/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-wan-dnsmasq -PKG_VERSION:=1 include ../gluon.mk @@ -14,4 +13,8 @@ define Package/gluon-wan-dnsmasq/description Gluon community wifi mesh firmware framework: Support for a secondary DNS server using the WAN interface endef +define Package/gluon-wan-dnsmasq/conffiles +/etc/config/gluon-wan-dnsmasq +endef + $(eval $(call BuildPackageGluon,gluon-wan-dnsmasq)) diff --git a/package/gluon-web-admin/Makefile b/package/gluon-web-admin/Makefile index d555be61..aa26e8cd 100644 --- a/package/gluon-web-admin/Makefile +++ b/package/gluon-web-admin/Makefile @@ -4,8 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-admin -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk 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 index da6a8a9c..5d614acf 100644 --- 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 @@ -12,8 +12,8 @@ You may obtain a copy of the License at local util = require 'gluon.util' local site = require 'gluon.site' +local sp = util.subprocess -local fcntl = require 'posix.fcntl' local unistd = require 'posix.unistd' local wait = require 'posix.sys.wait' @@ -76,29 +76,16 @@ function pw2.cfgvalue() end local function set_password(password) - local inr, inw = unistd.pipe() - local pid = unistd.fork() - - if pid < 0 then + local options = { + stdin = sp.PIPE, + stdout = sp.DEVNULL, + stderr = sp.DEVNULL, + } + local pid, pipe = sp.popen('passwd', {}, options) + if not pid then return false - elseif pid == 0 then - unistd.close(inw) - - local null = fcntl.open('/dev/null', fcntl.O_WRONLY) - unistd.dup2(null, unistd.STDOUT_FILENO) - unistd.dup2(null, unistd.STDERR_FILENO) - if null > 2 then - unistd.close(null) - end - - unistd.dup2(inr, unistd.STDIN_FILENO) - unistd.close(inr) - - unistd.execp('passwd', {[0] = 'passwd'}) - os.exit(127) end - - unistd.close(inr) + local inw = pipe.stdin unistd.write(inw, string.format('%s\n%s\n', password, password)) unistd.close(inw) diff --git a/package/gluon-web-autoupdater/Makefile b/package/gluon-web-autoupdater/Makefile index c50e731a..9b6a7d06 100644 --- a/package/gluon-web-autoupdater/Makefile +++ b/package/gluon-web-autoupdater/Makefile @@ -4,8 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-autoupdater -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-logging/Makefile b/package/gluon-web-logging/Makefile index 10d83740..9463e1c1 100644 --- a/package/gluon-web-logging/Makefile +++ b/package/gluon-web-logging/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-logging -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-mesh-vpn-fastd/Makefile b/package/gluon-web-mesh-vpn-fastd/Makefile index 46dfd181..c7fdb6e1 100644 --- a/package/gluon-web-mesh-vpn-fastd/Makefile +++ b/package/gluon-web-mesh-vpn-fastd/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-mesh-vpn-fastd -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-model/Makefile b/package/gluon-web-model/Makefile index d767f562..518a5b47 100644 --- a/package/gluon-web-model/Makefile +++ b/package/gluon-web-model/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-model -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-web-network/Makefile b/package/gluon-web-network/Makefile index 42620fe5..17a83b85 100644 --- a/package/gluon-web-network/Makefile +++ b/package/gluon-web-network/Makefile @@ -4,8 +4,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-network -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-node-role/Makefile b/package/gluon-web-node-role/Makefile index 81283761..516146bc 100644 --- a/package/gluon-web-node-role/Makefile +++ b/package/gluon-web-node-role/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-node-role -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-web-osm/Makefile b/package/gluon-web-osm/Makefile index a59f7f9f..3594da80 100644 --- a/package/gluon-web-osm/Makefile +++ b/package/gluon-web-osm/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-osm -PKG_VERSION:=1 include ../gluon.mk diff --git a/package/gluon-web-private-wifi/Makefile b/package/gluon-web-private-wifi/Makefile index f016abf4..971189cc 100644 --- a/package/gluon-web-private-wifi/Makefile +++ b/package/gluon-web-private-wifi/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-private-wifi -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-wifi-config/Makefile b/package/gluon-web-wifi-config/Makefile index 7827491e..e18febad 100644 --- a/package/gluon-web-wifi-config/Makefile +++ b/package/gluon-web-wifi-config/Makefile @@ -1,8 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web-wifi-config -PKG_VERSION:=1 -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon-web-wifi-config/i18n/de.po b/package/gluon-web-wifi-config/i18n/de.po index ee55ae30..d2ddeb8b 100644 --- a/package/gluon-web-wifi-config/i18n/de.po +++ b/package/gluon-web-wifi-config/i18n/de.po @@ -47,15 +47,6 @@ msgstr "Knoten wird im Außenbereich betrieben" msgid "Outdoor Installation" msgstr "Outdoor-Installation" -msgid "HT Mode" -msgstr "HT-Modus" - -msgid "Node will be installed outdoors" -msgstr "Knoten wird im Außenbereich betrieben" - -msgid "Outdoor Installation" -msgstr "Outdoor-Installation" - msgid "Transmission power" msgstr "Sendeleistung" diff --git a/package/gluon-web-wifi-config/i18n/fr.po b/package/gluon-web-wifi-config/i18n/fr.po index b922aa38..faf6d47d 100644 --- a/package/gluon-web-wifi-config/i18n/fr.po +++ b/package/gluon-web-wifi-config/i18n/fr.po @@ -42,15 +42,6 @@ msgstr "" msgid "Outdoor Installation" msgstr "Installation extérieure" -msgid "HT Mode" -msgstr "Mode HT" - -msgid "Node will be installed outdoors" -msgstr "" - -msgid "Outdoor Installation" -msgstr "Installation extérieure" - msgid "Transmission power" msgstr "Puissance d'émission" diff --git a/package/gluon-web/Makefile b/package/gluon-web/Makefile index decc9c84..54460a48 100644 --- a/package/gluon-web/Makefile +++ b/package/gluon-web/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-web -PKG_VERSION:=1 PKG_INSTALL:=1 diff --git a/package/gluon-wireless-encryption/Makefile b/package/gluon-wireless-encryption/Makefile index 35b61576..879054f8 100644 --- a/package/gluon-wireless-encryption/Makefile +++ b/package/gluon-wireless-encryption/Makefile @@ -1,7 +1,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=gluon-wireless-encryption -PKG_RELEASE:=1 include ../gluon.mk diff --git a/package/gluon.mk b/package/gluon.mk index 0139544e..40f9274f 100644 --- a/package/gluon.mk +++ b/package/gluon.mk @@ -1,10 +1,12 @@ GLUON_MK := $(abspath $(lastword $(MAKEFILE_LIST))) PKG_FILE_DEPENDS += $(GLUON_MK) +PKG_VERSION ?= 1 + PKG_BUILD_DEPENDS += luasrcdiet/host ifneq ($(wildcard ./luasrc/.),) - PKG_CONFIG_DEPENDS += CONFIG_GLUON_MINIFY + PKG_CONFIG_DEPENDS += CONFIG_GLUON_MINIFY endif ifneq ($(wildcard ./src/respondd.c),) @@ -21,7 +23,8 @@ 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' +[ -z "$$STAGING_DIR_HOSTPKG" ] || PATH="$$STAGING_DIR_HOSTPKG/bin:$$PATH" +lua "$$IPKG_INSTROOT/lib/gluon/check-site.lua" <<'END__GLUON__CHECK__SITE' $(call shell-verbatim,cat '$(1)') END__GLUON__CHECK__SITE endef diff --git a/patches/openwrt/0005-package-uci-backport-cli-add-option-for-changing-save-path.patch b/patches/openwrt/0005-package-uci-backport-cli-add-option-for-changing-save-path.patch new file mode 100644 index 00000000..a3f4f92a --- /dev/null +++ b/patches/openwrt/0005-package-uci-backport-cli-add-option-for-changing-save-path.patch @@ -0,0 +1,83 @@ +From: Leonardo Mörlein +Date: Sat, 16 Jan 2021 23:11:01 +0100 +Subject: package/uci: backport: "cli: add option for changing save path" + +This is a backport of + +https://git.openwrt.org/?p=project/uci.git;a=commit;h=4b3db1179747b6a6779029407984bacef851325c + +diff --git a/package/system/uci/Makefile b/package/system/uci/Makefile +index 75fc1bdfad0694aac99830b9b0cc87b42ea16e7d..924d5bb4824f567888e2ffd2954429af8f4fd504 100644 +--- a/package/system/uci/Makefile ++++ b/package/system/uci/Makefile +@@ -9,7 +9,7 @@ + include $(TOPDIR)/rules.mk + + PKG_NAME:=uci +-PKG_RELEASE:=5 ++PKG_RELEASE:=6 + + PKG_SOURCE_URL=$(PROJECT_GIT)/project/uci.git + PKG_SOURCE_PROTO:=git +diff --git a/package/system/uci/patches/0001-cli-add-option-for-changin-save-path.patch b/package/system/uci/patches/0001-cli-add-option-for-changin-save-path.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..377aec41fe6928aa26bccdde9fd77576d57ec4ed +--- /dev/null ++++ b/package/system/uci/patches/0001-cli-add-option-for-changin-save-path.patch +@@ -0,0 +1,56 @@ ++From: Rafał Miłecki ++Date: Mon, 12 Apr 2021 14:05:52 +0000 (+0200) ++Subject: cli: add option for changing save path ++X-Git-Url: http://git.openwrt.org/?p=project%2Fuci.git;a=commitdiff_plain;h=4b3db1179747b6a6779029407984bacef851325c;hp=52bbc99f69ea6f67b6fe264f424dac91bde5016c ++ ++cli: add option for changing save path ++ ++Save path is a directory where config change (delta) files are stored. ++Having a custom individual save dir can be used to prevent two (or more) ++"uci" cli callers (e.g. bash scripts) from commiting each other changes. ++ ++In the following example: ++ ++App0 App1 ++---- ---- ++uci set system.@system[0].timezone=UTC ++ uci set system.@system[0].hostname=OpenWrt ++ uci commit system ++ ++App1 would unintentionally commit changes made by App0. This can be ++avoided by at least 1 "uci" cli user specifying a custom -t option. ++ ++Signed-off-by: Rafał Miłecki ++--- ++ ++diff --git a/cli.c b/cli.c ++index 267437d..2fce39d 100644 ++--- a/cli.c +++++ b/cli.c ++@@ -167,6 +167,7 @@ static void uci_usage(void) ++ "\t-N don't name unnamed sections\n" ++ "\t-p add a search path for config change files\n" ++ "\t-P add a search path for config change files and use as default\n" +++ "\t-t set save path for config change files\n" ++ "\t-q quiet mode (don't print error messages)\n" ++ "\t-s force strict mode (stop on parser errors, default)\n" ++ "\t-S disable strict mode\n" ++@@ -706,7 +707,7 @@ int main(int argc, char **argv) ++ return 1; ++ } ++ ++- while((c = getopt(argc, argv, "c:d:f:LmnNp:P:sSqX")) != -1) { +++ while((c = getopt(argc, argv, "c:d:f:LmnNp:P:qsSt:X")) != -1) { ++ switch(c) { ++ case 'c': ++ uci_set_confdir(ctx, optarg); ++@@ -754,6 +755,9 @@ int main(int argc, char **argv) ++ case 'q': ++ flags |= CLI_FLAG_QUIET; ++ break; +++ case 't': +++ uci_set_savedir(ctx, optarg); +++ break; ++ case 'X': ++ flags &= ~CLI_FLAG_SHOW_EXT; ++ break; diff --git a/patches/openwrt/0006-wireguard-tools-allow-generating-private_key-v3.patch b/patches/openwrt/0006-wireguard-tools-allow-generating-private_key-v3.patch new file mode 100644 index 00000000..9d801d02 --- /dev/null +++ b/patches/openwrt/0006-wireguard-tools-allow-generating-private_key-v3.patch @@ -0,0 +1,53 @@ +From: lemoer +Date: Sat, 3 Jul 2021 22:50:29 +0200 +Subject: wireguard-tools: allow generating private_key (v3) + +When the uci configuration is created automatically during a very early +stage, where no entropy daemon is set up, generating the key directly is +not an option. Therefore we allow to set the private_key to "generate" +and generate the private key directly before the interface is taken up. + +v3: Somebody has implemented another uci cli flag '-t' upstream to handle + this, before my patch to implement the new uci flag '-x' syntax was + accepted. So I dropped my suggestion of '-x'. +v2: We now use a new uci cli flag to commit only the private_key and do + not commit uncommited user changes. This is not yet upstream as of + now. + +diff --git a/package/network/utils/wireguard-tools/files/wireguard.sh b/package/network/utils/wireguard-tools/files/wireguard.sh +index 63261aea71daa058bf37014ba7d670a5e74a2e04..845f9eb902bf3655b631d52aa3ee69231366f657 100644 +--- a/package/network/utils/wireguard-tools/files/wireguard.sh ++++ b/package/network/utils/wireguard-tools/files/wireguard.sh +@@ -95,6 +95,23 @@ proto_wireguard_setup_peer() { + fi + } + ++ensure_key_is_generated() { ++ local private_key ++ private_key="$(uci get network."$1".private_key)" ++ ++ if [ "$private_key" == "generate" ]; then ++ local ucitmp ++ oldmask="$(umask)" ++ umask 077 ++ ucitmp="$(mktemp -d)" ++ private_key="$("${WG}" genkey)" ++ uci -q -t "$ucitmp" set network."$1".private_key="$private_key" && \ ++ uci -q -t "$ucitmp" commit network ++ rm -rf "$ucitmp" ++ umask "$oldmask" ++ fi ++} ++ + proto_wireguard_setup() { + local config="$1" + local wg_dir="/tmp/wireguard" +@@ -104,6 +121,8 @@ proto_wireguard_setup() { + local listen_port + local mtu + ++ ensure_key_is_generated "${config}" ++ + config_load network + config_get private_key "${config}" "private_key" + config_get listen_port "${config}" "listen_port" diff --git a/scripts/copy_output.lua b/scripts/copy_output.lua index 9f14fba5..b5c6f1b2 100755 --- a/scripts/copy_output.lua +++ b/scripts/copy_output.lua @@ -83,7 +83,7 @@ lib.exec {'cp', kernel_debug_source, kernel_debug_dest} -- Copy opkg repo -if lib.opkg and (env.GLUON_DEVICES or '') == '' then +if (env.GLUON_DEVICES or '') == '' then local package_prefix = string.format('gluon-%s-%s', lib.site_code, env.GLUON_RELEASE) local function dest_dir(prefix) return env.GLUON_PACKAGEDIR..'/'..prefix..'/'..bindir diff --git a/scripts/getversion.sh b/scripts/getversion.sh new file mode 100755 index 00000000..8c437762 --- /dev/null +++ b/scripts/getversion.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +if [ $# -ne 1 ]; then + echo >&2 "Usage: getversion.sh " + exit 1 +fi + +cd "$1" || exit 1 + +cat .scmversion 2>/dev/null && exit 0 +git --git-dir=.git describe --always --abbrev=7 --dirty=+ 2>/dev/null && exit 0 + +echo unknown diff --git a/scripts/target_config_lib.lua b/scripts/target_config_lib.lua index 4b107e2b..c2237f72 100644 --- a/scripts/target_config_lib.lua +++ b/scripts/target_config_lib.lua @@ -151,13 +151,6 @@ lib.include(target) lib.check_devices() -if not lib.opkg then - lib.config('SIGNED_PACKAGES', false) - lib.config('CLEAN_IPKG', true) - lib.config('ALL_NONSHARED', false) - lib.packages {'-opkg'} -end - if #lib.devices > 0 then handle_target_pkgs(lib.target_packages) diff --git a/scripts/target_lib.lua b/scripts/target_lib.lua index babec324..36a6ee91 100644 --- a/scripts/target_lib.lua +++ b/scripts/target_lib.lua @@ -28,7 +28,6 @@ M.target_packages = {} M.configs = {} M.devices = {} M.images = {} -M.opkg = true local default_options = { @@ -309,10 +308,6 @@ function F.sysupgrade_image(image, name, ext, options) } end -function F.no_opkg() - M.opkg = false -end - function F.defaults(options) default_options = merge(default_options, options) end diff --git a/scripts/update-ci.sh b/scripts/update-ci.sh new file mode 100755 index 00000000..cebc92dc --- /dev/null +++ b/scripts/update-ci.sh @@ -0,0 +1,3 @@ +#!/bin/sh -e + +make --no-print-directory list-targets BROKEN=1 | ./contrib/actions/generate-target-filters.py > .github/filters.yml diff --git a/scripts/update-modules.sh b/scripts/update-modules.sh new file mode 100755 index 00000000..49f87a50 --- /dev/null +++ b/scripts/update-modules.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +set -eo pipefail + +# move to basedir, in case the script is not executed via `make update-modules` +cd "$(dirname "$0")/.." || exit 1 + +# shellcheck source=./modules +source ./modules + +git diff --quiet ./modules || { + 1>&2 echo "Your modules file is dirty, aborting." + exit 1 +} + +LOCAL_BRANCH=$(git branch --show-current) +[[ $LOCAL_BRANCH != *-updates ]] && LOCAL_BRANCH+=-updates + +for MODULE in "OPENWRT" "PACKAGES_PACKAGES" "PACKAGES_ROUTING" "PACKAGES_GLUON"; do + _REMOTE_URL=${MODULE}_REPO + _REMOTE_BRANCH=${MODULE}_BRANCH + _LOCAL_HEAD=${MODULE}_COMMIT + + REMOTE_URL="${!_REMOTE_URL}" + REMOTE_BRANCH="${!_REMOTE_BRANCH}" + LOCAL_HEAD="${!_LOCAL_HEAD}" + + # get default branch name if none is set + [ -z "${REMOTE_BRANCH}" ] && { + REMOTE_BRANCH=$(git ls-remote --symref "${REMOTE_URL}" HEAD | awk '/^ref:/ { sub(/refs\/heads\//, "", $2); print $2 }') + } + + # fetch the commit id for the HEAD of the module + REMOTE_HEAD=$(git ls-remote "${REMOTE_URL}" "${REMOTE_BRANCH}" | awk '{ print $1 }') + + # skip ahead if the commit id did not change + [ "$LOCAL_HEAD" == "$REMOTE_HEAD" ] && continue 1 + + # switch to local working branch, if we found changes + [ "$(git branch --show-current)" != "${LOCAL_BRANCH}" ] && { + git switch -c "${LOCAL_BRANCH}" || git switch "${LOCAL_BRANCH}" + } + + CHECKOUT=$(mktemp -d) + + # clone the target branch + git clone --bare "${REMOTE_URL}" --branch="${REMOTE_BRANCH}" "${CHECKOUT}" + + # prepare the commit message + # shellcheck disable=SC2001 + MODULE=$(echo ${MODULE,,} | sed 's/packages_//') + TITLE="modules: update ${MODULE}" + MESSAGE="$(mktemp)" + { + echo "${TITLE}" + printf '\n\n' + git -C "${CHECKOUT}" log --oneline --no-decorate --no-merges "${LOCAL_HEAD}..${REMOTE_HEAD}" | cat + } > "$MESSAGE" + + # modify modules file + sed -i "s/${LOCAL_HEAD}/${REMOTE_HEAD}/" ./modules + git add ./modules + + git commit -F "${MESSAGE}" + + # remove the checkout + rm -fr "${CHECKOUT}" +done + diff --git a/targets/ath79-generic b/targets/ath79-generic index 5e66617d..680c9f81 100644 --- a/targets/ath79-generic +++ b/targets/ath79-generic @@ -54,18 +54,40 @@ device('devolo-wifi-pro-1750x', 'devolo_dvl1750x', { factory = false, }) + +-- Enterasys + +device('enterasys-ws-ap3705', 'enterasys_ws-ap3705i', { + factory = false, +}) + + -- GL.iNet device('gl.inet-gl-ar300m-lite', 'glinet_gl-ar300m-lite', { factory = false, }) +-- JOY-IT + +device('joy-it-jt-or750i', 'joyit_jt-or750i', { + packages = ATH10K_PACKAGES_QCA9887, + factory = false, +}) + + -- OCEDO device('ocedo-raccoon', 'ocedo_raccoon', { factory = false, }) +-- Onion + +-- modular/optional "ethernet expansion board" recommended for config mode +-- setup via integrated (USB-)tty is possible as well +device('onion-omega', 'onion_omega') + -- Plasma Cloud device('plasma-cloud-pa300', 'plasmacloud_pa300') @@ -85,17 +107,27 @@ device('tp-link-archer-c2-v3', 'tplink_archer-c2-v3', { packages = ATH10K_PACKAGES_QCA9887, class = 'tiny', broken = true, -- 64M ath9k + ath10k - }) device('tp-link-archer-c6-v2', 'tplink_archer-c6-v2', { packages = ATH10K_PACKAGES_QCA9888, }) -device('tp-link-cpe220-v3', 'tplink_cpe220-v3') - device('tp-link-archer-d50-v1', 'tplink_archer-d50-v1', { packages = ATH10K_PACKAGES_QCA9880, factory = false, broken = true, -- 64M ath9k + ath10k & power LED not working }) + +device('tp-link-cpe220-v3', 'tplink_cpe220-v3') +device('tp-link-cpe510-v2', 'tplink_cpe510-v2') +device('tp-link-cpe510-v3', 'tplink_cpe510-v3') + +device('tp-link-eap225-outdoor-v1', 'tplink_eap225-outdoor-v1', { + packages = ATH10K_PACKAGES_QCA9888, +}) + +device('tp-link-tl-wdr3600-v1', 'tplink_tl-wdr3600-v1') +device('tp-link-tl-wdr4300-v1', 'tplink_tl-wdr4300-v1') + +device('tp-link-wbs210-v2', 'tplink_wbs210-v2') diff --git a/targets/generic b/targets/generic index cd72112f..b0943d9b 100644 --- a/targets/generic +++ b/targets/generic @@ -2,6 +2,8 @@ assert(env.GLUON_LANGS) config('GLUON_SITEDIR', env.GLUON_SITEDIR) +config('GLUON_VERSION', env.GLUON_VERSION) +config('GLUON_SITE_VERSION', env.GLUON_SITE_VERSION) config('GLUON_RELEASE', env.GLUON_RELEASE) try_config('GLUON_AUTOUPDATER_BRANCH', env.GLUON_AUTOUPDATER_BRANCH) diff --git a/targets/ipq40xx-generic b/targets/ipq40xx-generic index f2b3686c..e3fc746b 100644 --- a/targets/ipq40xx-generic +++ b/targets/ipq40xx-generic @@ -28,6 +28,16 @@ device('aruba-ap-303', 'aruba_ap-303', { aliases = {'aruba-instant-on-ap11'}, }) +device('aruba-ap-303h', 'aruba_ap-303h', { + factory = false, + aliases = {'aruba-instant-on-ap11d'}, +}) + +device('aruba-ap-365', 'aruba_ap-365', { + factory = false, + aliases = {'aruba-instant-on-ap17'}, +}) + -- AVM diff --git a/targets/ramips-mt7621 b/targets/ramips-mt7621 index c8a42d0e..531a81ae 100644 --- a/targets/ramips-mt7621 +++ b/targets/ramips-mt7621 @@ -29,6 +29,13 @@ device('netgear-wndr3700-v5', 'netgear_wndr3700-v5', { }) +-- Ubiquiti + +device('ubiquiti-unifi-6-lite', 'ubnt_unifi-6-lite', { + factory = false, +}) + + -- Xiaomi device('xiaomi-mi-router-4a-gigabit-edition', 'xiaomi_mi-router-4a-gigabit', { diff --git a/targets/ramips-mt76x8 b/targets/ramips-mt76x8 index 0adcfaa4..a22f996b 100644 --- a/targets/ramips-mt76x8 +++ b/targets/ramips-mt76x8 @@ -9,6 +9,10 @@ device('gl-mt300n-v2', 'glinet_gl-mt300n-v2', { factory = false, }) +device('gl.inet-microuter-n300', 'glinet_microuter-n300', { + factory = false, +}) + device('gl.inet-vixmini', 'glinet_vixmini', { factory = false, }) @@ -21,6 +25,11 @@ device('netgear-r6120', 'netgear_r6120', { }) +-- RAVPower + +device('ravpower-rp-wd009', 'ravpower_rp-wd009') + + -- TP-Link device('tp-link-archer-c50-v3', 'tplink_archer-c50-v3', { @@ -34,6 +43,8 @@ device('tp-link-archer-c50-v4', 'tplink_archer-c50-v4', { factory = false, }) +device('tp-link-re200-v2', 'tplink_re200-v2') + device('tp-link-tl-mr3020-v3', 'tplink_tl-mr3020-v3', { factory = false, extra_images = { diff --git a/targets/ramips-rt305x b/targets/ramips-rt305x deleted file mode 100644 index f8be18c7..00000000 --- a/targets/ramips-rt305x +++ /dev/null @@ -1,18 +0,0 @@ -config('KERNEL_KALLSYMS', false) -config('GLUON_SPECIALIZE_KERNEL', true) - -no_opkg() - -defaults { - class = 'tiny', -- 32M RAM -} - --- VoCore - -device('vocore-8M', 'vocore_vocore-8m', { - factory = false, -}) - -device('vocore-16M', 'vocore_vocore-16m', { - factory = false, -}) diff --git a/targets/targets.mk b/targets/targets.mk index 67e87fa2..92b58ab8 100644 --- a/targets/targets.mk +++ b/targets/targets.mk @@ -12,7 +12,6 @@ $(eval $(call GluonTarget,mpc85xx,p1020)) $(eval $(call GluonTarget,ramips,mt7620)) $(eval $(call GluonTarget,ramips,mt7621)) $(eval $(call GluonTarget,ramips,mt76x8)) -$(eval $(call GluonTarget,ramips,rt305x)) $(eval $(call GluonTarget,rockchip,armv8)) $(eval $(call GluonTarget,sunxi,cortexa7)) $(eval $(call GluonTarget,x86,generic)) diff --git a/targets/x86.inc b/targets/x86.inc index ebefcbfa..f090a9e8 100644 --- a/targets/x86.inc +++ b/targets/x86.inc @@ -40,6 +40,9 @@ packages { 'kmod-mt7615e', } +-- We do not use the ext4 images, so we do not want to build them. +config('TARGET_ROOTFS_EXT4FS', false) + defaults { factory = '-squashfs-combined', factory_ext = {'.img.gz', '.vmdk', '.vdi'},