Merge branch 'freifunk-gluon:master' into add-fritzbox-7430

This commit is contained in:
Felix 2021-12-10 20:37:19 +01:00 committed by GitHub
commit c24f7c1b87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
139 changed files with 1748 additions and 1073 deletions

186
.github/filters.yml vendored Normal file
View File

@ -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"
]
}

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

1
.gitignore vendored
View File

@ -7,3 +7,4 @@
.bash_history
.subversion
.wget-hsts
/.scmversion

16
.readthedocs.yml Normal file
View File

@ -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

View File

@ -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 :=

View File

@ -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)

View File

@ -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))

View File

@ -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/*

View File

@ -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
*/

View File

@ -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" ]

View File

@ -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.

View File

@ -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.')

View File

@ -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!

149
contrib/push_pkg.sh Executable file
View File

@ -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

15
contrib/run_qemu.sh Executable file
View File

@ -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 \
"$@"

View File

@ -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;
}

View File

@ -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``.

View File

@ -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
=======================

View File

@ -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

View File

@ -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 <https://github.com/freifunk-gluon/gluon/issues/1937>`_)
* The integration of the BATMAN_V routing algorithm is incomplete.
- Mesh neighbors don't appear on the status page. (`#1726 <https://github.com/freifunk-gluon/gluon/issues/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 <https://github.com/freifunk-gluon/gluon/issues/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 <https://github.com/freifunk-gluon/gluon/issues/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 <https://github.com/freifunk-gluon/gluon/issues/496>`_)
This may lead to issues in environments where a fixed MAC address is expected (like VMware when promiscuous mode is disallowed).

View File

@ -1 +1 @@
sphinx-rtd-theme
sphinx-rtd-theme==0.5.2

View File

@ -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

View File

@ -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`

View File

@ -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.

View File

@ -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

View File

@ -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',
})

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-alfred
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-authorized-keys
PKG_VERSION:=2
include ../gluon.mk

View File

@ -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

View File

@ -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))

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-autoupdater
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-contact-info
PKG_VERSION:=1
include ../gluon.mk

View File

@ -4,7 +4,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-core
PKG_VERSION:=2
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-domain-select
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-geo-location-osm
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-geo-location
PKG_VERSION:=1
include ../gluon.mk

View File

@ -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."

View File

@ -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."

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-hostname
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-mesh-vpn
PKG_VERSION:=2
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-outdoor
PKG_VERSION:=1
include ../gluon.mk

View File

@ -4,7 +4,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-config-mode-theme
PKG_VERSION:=1
include ../gluon.mk

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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

View File

@ -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')

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-filter-multicast
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-filter-ra-dhcp
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -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

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-source-filter
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-l3roamd
PKG_VERSION:=1
include ../gluon.mk

View File

@ -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)

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-lock-password
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-logging
PKG_VERSION:=1
include ../gluon.mk

View File

@ -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

View File

@ -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))

View File

@ -0,0 +1,2 @@
#!/bin/sh
out=$(batctl gwl -H 2>/dev/null) && [ -n "$out" ]

View File

@ -0,0 +1,2 @@
#!/bin/sh
out=$(batctl n -H 2>/dev/null) && [ -n "$out" ]

View File

@ -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

View File

@ -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

View File

@ -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')))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,231 @@
/*
Copyright (c) 2020, Leonardo Mörlein <me@irrelefant.net>
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
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 <respondd.h>
#include <json-c/json.h>
#include <libgluonutil.h>
#include <uci.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#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},
{}
};

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mesh-wireless-sae
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-mmfd
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-neighbour-info
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -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;
}

View File

@ -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))

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-private-wifi
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,8 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-radv-filterd
PKG_VERSION:=1
PKG_RELEASE:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-radvd
PKG_VERSION:=3
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-respondd
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-scheduled-domain-switch
PKG_VERSION:=1
include ../gluon.mk

View File

@ -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 \

View File

@ -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)

View File

@ -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))

View File

@ -0,0 +1,2 @@
#!/bin/sh
out=$(ip -6 route show default dev br-client 2>/dev/null) && [ -n "$out" ]

View File

@ -0,0 +1 @@
* * * * * /usr/sbin/gluon-state-check

View File

@ -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()

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-status-page-mesh-batman-adv
PKG_VERSION:=1
include ../gluon.mk

View File

@ -1,7 +1,6 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-status-page
PKG_VERSION:=3
include ../gluon.mk

Some files were not shown because too many files have changed in this diff Show More