aredn/files/usr/local/bin/node-setup

1215 lines
45 KiB
Plaintext
Raw Normal View History

#! /usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2021-2023 Tim Wilkinson
Orignal Perl Copyright (C) 2015 Conrad Lara
See Contributors file for additional contributors
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 3 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Additional Terms:
Additional use restrictions exist on the AREDN(TM) trademark and logo.
See AREDNLicense.txt for more info.
Attributions to the AREDN Project must be retained in the source code.
If importing this code into a new or existing project attribution
to the AREDN project must be added to the source code.
You must not misrepresent the origin of the material contained within.
Modified versions must be modified to attribute to the original source
and be marked in reasonable ways as differentiate it from the original
version
--]]
require("nixio")
require("aredn.utils")
require('aredn.info')
require("aredn.hardware")
require("iwinfo")
require("aredn.services")
-- helpers start
function is_null(v)
2022-02-27 16:57:51 -07:00
if not v or v == "" or v == 0 or v == "0" then
return true
else
return false
end
end
local function h2s(hex)
local s = ""
if hex then
for i = 1,#hex,2
do
local p = hex:sub(i, i+1)
if p:match("[0-9a-f][0-9a-f]") then
s = s .. string.char(tonumber(p, 16))
else
s = s .. p
end
end
end
return s
end
-- helpers end
local c = uci.cursor()
local cm = uci.cursor("/etc/config.mesh")
local ieee80211 = "/sys/class/ieee80211/"
Update AREDN to OpenWRT 22.3.2 (Major Upgrade) (#574) * Update to Openwrt 21.02 and add support for the CPE710 v1 Update scripts to change references to ifname to device due to a change in Openwrt naming reverse-wpad-basic-wolfssl and disable SSL on Curl NOTE: The compile host must have python3-distutils installed for gpsd to build * aredn: initial working upgrade to openwrt 21.02.1 * aredn: update 1 to working upgrade to openwrt 21.02.1 * aredn: add cpe710v1 to build config * Andrew's patches * Remove duplicates + display perl * Temp disable wifi extension patch * ifname/ports support * Add spectrum patch back in * Generic function to extra interfaces * New api to get wifi ifname * Disables jails * Style link * aredn: partial upgrade to openwrt 22.0.3.0 added AC device images and partial migration to 22.0.3.0 firewall upgrade pending * aredn: update mesh-release and revert config.mk * Unused * NFT firewall rewrite * Common-isze configs * Fix network layout for hap2 * Use local packages dev (new firewall rules) * Add HAP2 * Add pause after network restart to let bridge reinitialize * Various lua fixes for new lua version * Tweak config * Re-fix networking (lost patch change) * Add new radio names * Tolerate missing wifi * Fix hap-lite switch setup * More devices * New radio id * Build Rocket 5AC lite * Remove need for luci.sys * Remove need for luci.sys * Explicitly name wlan interfaces * Handle different compatibility verisoning * Update networking for switches * ipref version bump * Extra flag for curl * Better compat_version fix * Remove wolfssl * Fix dns server * Fix device name * Unused * Remove things we dont need * Remove unused packages * Generic macaddr overrides * Fix uci commit * Fix luci.template.parser to avoid luci.http loading the real thing * Rocket-M build * Add search-domain dhcp option * Turn of ipv6 * No IPV6 in dnsmasq * Override mac addresses if devices all the same * Working from master (for now) * Put back hostap * Disable old ethmac fixup * Tweak configs * Move back to v22.03.2 Leave ipq4019 builds to master * Need IPV6 to compile nft firewall * Rocket-M fixes * Before we start * WIP * Working snapshot * Cleaned patches * Merged patch * Single patch to support HAP2 * Fix typo * Add nanostation-m * 5/10Mhz patch * 5+10MHz patch for ath10k-ct driver * Extend 2Ghz channel check to include -4 to -1 * Add chanbw setup for ath10k (like ath9k) * Added TP-Link CPE710 v1 * Override firmwares * Missing patch * Dropbear config like 3.22.8.0 * Add Ubiquiti Rocket 5AC Lite * Fix c6 * Update * Need more scan channels * Remove IPV6 * Improve mac fixups * Put back missing nft app * IPv6 removed so dont have to disable it * Fix rocket-m flash bug * Fix nanostation-m * Nanobridge is tiny * Fix wifi order for ar750 * Rocket M5 XW support * New rates * Fix firewall4 so we don't need IPv6 * Allow channel width to be restricted * Move channel list into library * Fix naming * Mechanism to block specific channels on specific radios * Refresh buttons * routerboard-sxt-5nd * CPE605 v1.0 * Improve rocket m xw * tpink * Update patch * Update to remove disable * Remove BW restrictions on cpe710 * Restrict to what has been tested * Remove test BW restrictions * sxtsq-5-ac * Update * Update * powerbeam-m5-300 support * Fix * Fix hap2 * Tidy unused patches * Remove limit * Add ubnt_bullet-m-ar7241 * Added ubnt_nanobeam-ac-gen2 * Fix typo * Tolerate missing dtd ip * Explicitly gix hap2 mac addresses * Fix some broken patches * Hap2 wont work at 5MHz * Ubiquiti LiteBeam 5AC Gen2 * Fix compat_version for sxt 5ac * Update patch * Unused * Fix lan configuration for some devices * Rolling average of noise level * Unused * Split out the ath10k rssi monitor (its very simple at the moment) * Ignore .DS_Store * Reboot if ethernet doesnt come up (but only once!) * reboot returns - add exit * Add some logging info * Fix ] * Check all possibly ethernet bridges * Improve mac fixing * Remove HostAP on small memory devices * Reduce dropbear footprint * Add setsid * Kill hostap when upgrading to save memory * Different way to detect hostapd unavailable * New build steps * Improve manager logging * Fix name conflict for the two monitors * Try to improve test mesh name resolve problem * Migrate tiny to generic (tiny doesnt work properly) * Typo * Another attempt to fix macs for Mikrotik * Protect against missing trackers * Fix wpad for ipq40xx * Remove old tunnel check code * Enable ZRAM swap to aid low memory devices * ath10k noise can something be out of range - protect against that * Updated with current devices and status * Update firmware which has been tested * Updated with more builds * More binary/README * Fix css error * Start noise at sensible base level * Unfix the css so it looks how it use to. * Save as much memory as we can on lowmem nodes * Hide some options on low memory devices * Add "eol" to 32MB devices * Restart network rather than reboot node if it seems to be broken * Fixes * Revert network reset * Fix ar750 networking * Continue to trim tiny configs * More devices * Dump IW output messages * Fix Rocket 5AC intermittent ethernet issue * Ethernet fix for PowerBeam 5AC 500 * More tiny size reduction * More support data * Fixed POE and USB power features * Add Ubiquiti NanoBeam AC (gen1) * NanoStation (not NanoBeam) * Add mii-tool package * Device updates * Bump update time to 5 minutes * Fix ethernet negotiation for rocker-5ac and nanobeam * Fix iplookup * Config changes based on call feedback * Radio listing fixes * Update with more untested builds * Fallback TxMbps extracted from iw station dump * Fix tunnel detection for low memory nodes * Remove unused feed packages * snapshot build * Update stability info * Add powerbeam-5ac-500 * Typo * Add missing 3.22.1.0 * Add MikroTik LHG 5 AC * Fix permissions * Fix permissions * AirGrid's take Bullet builds * Mikrotik AC3 * Improve supportdata structure a little to make it easier to find things * Restore WAN VLAN overrides * Fix vlan regex for hap2 and hap3 * Support old and new style poe controls * hap-ac3 is version 1.1 * Handle typo in some openwrt config files * Fix HAP AC3 install * Update hap ac3 status * Support user overrides for network ports (non-swconfig devices) * LHG 5AC support * Remove -nand * Remove non-working platform.sh change * tunnel weight override * Omit LinkQualityMult when value is 1 * Add mANTBox 19s and 15s * Support ath79 mikrotik devices which require ath10k in the initramfs Co-authored-by: apcameron <apcameron@softhome.net> Co-authored-by: Joe AE6XE <ae6xe@arrl.net> Co-authored-by: Joe Ayers <joe@arrl.net>
2022-12-22 13:22:49 -07:00
local lanintf = aredn.hardware.get_board_network_ifname("lan")
local node = aredn.info.get_nvram("node")
local tactical = aredn.info.get_nvram("tactical")
local mac2 = aredn.info.get_nvram("mac2")
local dtdmac = aredn.info.get_nvram("dtdmac")
local wifi_mon_enable = false
local deleteme = {}
local cfg = {
lan_intf = lanintf,
Update AREDN to OpenWRT 22.3.2 (Major Upgrade) (#574) * Update to Openwrt 21.02 and add support for the CPE710 v1 Update scripts to change references to ifname to device due to a change in Openwrt naming reverse-wpad-basic-wolfssl and disable SSL on Curl NOTE: The compile host must have python3-distutils installed for gpsd to build * aredn: initial working upgrade to openwrt 21.02.1 * aredn: update 1 to working upgrade to openwrt 21.02.1 * aredn: add cpe710v1 to build config * Andrew's patches * Remove duplicates + display perl * Temp disable wifi extension patch * ifname/ports support * Add spectrum patch back in * Generic function to extra interfaces * New api to get wifi ifname * Disables jails * Style link * aredn: partial upgrade to openwrt 22.0.3.0 added AC device images and partial migration to 22.0.3.0 firewall upgrade pending * aredn: update mesh-release and revert config.mk * Unused * NFT firewall rewrite * Common-isze configs * Fix network layout for hap2 * Use local packages dev (new firewall rules) * Add HAP2 * Add pause after network restart to let bridge reinitialize * Various lua fixes for new lua version * Tweak config * Re-fix networking (lost patch change) * Add new radio names * Tolerate missing wifi * Fix hap-lite switch setup * More devices * New radio id * Build Rocket 5AC lite * Remove need for luci.sys * Remove need for luci.sys * Explicitly name wlan interfaces * Handle different compatibility verisoning * Update networking for switches * ipref version bump * Extra flag for curl * Better compat_version fix * Remove wolfssl * Fix dns server * Fix device name * Unused * Remove things we dont need * Remove unused packages * Generic macaddr overrides * Fix uci commit * Fix luci.template.parser to avoid luci.http loading the real thing * Rocket-M build * Add search-domain dhcp option * Turn of ipv6 * No IPV6 in dnsmasq * Override mac addresses if devices all the same * Working from master (for now) * Put back hostap * Disable old ethmac fixup * Tweak configs * Move back to v22.03.2 Leave ipq4019 builds to master * Need IPV6 to compile nft firewall * Rocket-M fixes * Before we start * WIP * Working snapshot * Cleaned patches * Merged patch * Single patch to support HAP2 * Fix typo * Add nanostation-m * 5/10Mhz patch * 5+10MHz patch for ath10k-ct driver * Extend 2Ghz channel check to include -4 to -1 * Add chanbw setup for ath10k (like ath9k) * Added TP-Link CPE710 v1 * Override firmwares * Missing patch * Dropbear config like 3.22.8.0 * Add Ubiquiti Rocket 5AC Lite * Fix c6 * Update * Need more scan channels * Remove IPV6 * Improve mac fixups * Put back missing nft app * IPv6 removed so dont have to disable it * Fix rocket-m flash bug * Fix nanostation-m * Nanobridge is tiny * Fix wifi order for ar750 * Rocket M5 XW support * New rates * Fix firewall4 so we don't need IPv6 * Allow channel width to be restricted * Move channel list into library * Fix naming * Mechanism to block specific channels on specific radios * Refresh buttons * routerboard-sxt-5nd * CPE605 v1.0 * Improve rocket m xw * tpink * Update patch * Update to remove disable * Remove BW restrictions on cpe710 * Restrict to what has been tested * Remove test BW restrictions * sxtsq-5-ac * Update * Update * powerbeam-m5-300 support * Fix * Fix hap2 * Tidy unused patches * Remove limit * Add ubnt_bullet-m-ar7241 * Added ubnt_nanobeam-ac-gen2 * Fix typo * Tolerate missing dtd ip * Explicitly gix hap2 mac addresses * Fix some broken patches * Hap2 wont work at 5MHz * Ubiquiti LiteBeam 5AC Gen2 * Fix compat_version for sxt 5ac * Update patch * Unused * Fix lan configuration for some devices * Rolling average of noise level * Unused * Split out the ath10k rssi monitor (its very simple at the moment) * Ignore .DS_Store * Reboot if ethernet doesnt come up (but only once!) * reboot returns - add exit * Add some logging info * Fix ] * Check all possibly ethernet bridges * Improve mac fixing * Remove HostAP on small memory devices * Reduce dropbear footprint * Add setsid * Kill hostap when upgrading to save memory * Different way to detect hostapd unavailable * New build steps * Improve manager logging * Fix name conflict for the two monitors * Try to improve test mesh name resolve problem * Migrate tiny to generic (tiny doesnt work properly) * Typo * Another attempt to fix macs for Mikrotik * Protect against missing trackers * Fix wpad for ipq40xx * Remove old tunnel check code * Enable ZRAM swap to aid low memory devices * ath10k noise can something be out of range - protect against that * Updated with current devices and status * Update firmware which has been tested * Updated with more builds * More binary/README * Fix css error * Start noise at sensible base level * Unfix the css so it looks how it use to. * Save as much memory as we can on lowmem nodes * Hide some options on low memory devices * Add "eol" to 32MB devices * Restart network rather than reboot node if it seems to be broken * Fixes * Revert network reset * Fix ar750 networking * Continue to trim tiny configs * More devices * Dump IW output messages * Fix Rocket 5AC intermittent ethernet issue * Ethernet fix for PowerBeam 5AC 500 * More tiny size reduction * More support data * Fixed POE and USB power features * Add Ubiquiti NanoBeam AC (gen1) * NanoStation (not NanoBeam) * Add mii-tool package * Device updates * Bump update time to 5 minutes * Fix ethernet negotiation for rocker-5ac and nanobeam * Fix iplookup * Config changes based on call feedback * Radio listing fixes * Update with more untested builds * Fallback TxMbps extracted from iw station dump * Fix tunnel detection for low memory nodes * Remove unused feed packages * snapshot build * Update stability info * Add powerbeam-5ac-500 * Typo * Add missing 3.22.1.0 * Add MikroTik LHG 5 AC * Fix permissions * Fix permissions * AirGrid's take Bullet builds * Mikrotik AC3 * Improve supportdata structure a little to make it easier to find things * Restore WAN VLAN overrides * Fix vlan regex for hap2 and hap3 * Support old and new style poe controls * hap-ac3 is version 1.1 * Handle typo in some openwrt config files * Fix HAP AC3 install * Update hap ac3 status * Support user overrides for network ports (non-swconfig devices) * LHG 5AC support * Remove -nand * Remove non-working platform.sh change * tunnel weight override * Omit LinkQualityMult when value is 1 * Add mANTBox 19s and 15s * Support ath79 mikrotik devices which require ath10k in the initramfs Co-authored-by: apcameron <apcameron@softhome.net> Co-authored-by: Joe AE6XE <ae6xe@arrl.net> Co-authored-by: Joe Ayers <joe@arrl.net>
2022-12-22 13:22:49 -07:00
wan_intf = aredn.hardware.get_board_network_ifname("wan"),
bridge_network_config = "",
lan_network_config = "",
wan_network_config = "",
dtdlink_network_config = "",
wifi_network_config = "",
olsrd_dtd_interface_mode = "ether",
tun_network_config = "",
wireguard_network_config = "",
olsrd_pollrate = "0.05",
tun_devices_config = ""
}
-- Track the changes so we can make better decissions about what to restart/reboot
local changes = {
reboot = false,
system = false,
manager = false,
network = false,
olsr = false,
dnsmasq = false,
firewall = false,
tunnels = false,
wireless = false,
localservices = false
}
function valid_config(config)
remove_all("/tmp/uci_validate")
nixio.fs.mkdir("/tmp/uci_validate")
write_all("/tmp/uci_validate/config", config)
local r = os.execute("/sbin/uci -c /tmp/uci_validate import dummy < /tmp/uci_validate/config")
remove_all("/tmp/uci_validate")
return r == 0 and true or false
end
function expand_vars(lines)
local nlines = {}
for line in lines:gmatch("([^\n]*\n?)")
do
local inc = line:match("^include%s+(%S+)%s*")
if inc then
if nixio.fs.stat(inc) then
line = expand_vars(read_all(inc))
if not valid_config(line) then
print("Invalid config fragment: " .. inc)
os.exit(1)
end
else
line = nil
end
elseif line:match("^[^#]") then
for parm in line:gmatch("<([^%s]*)>")
do
if deleteme[parm] then
line = nil
elseif parm == "NODE" then
line = line:gsub("<NODE>", node)
elseif parm == "MAC2" then
line = line:gsub("<MAC2>", mac2)
elseif parm == "DTDMAC" then
line = line:gsub("<DTDMAC>", dtdmac)
elseif cfg[parm] then
line = line:gsub("<" .. parm .. ">", cfg[parm])
else
line = nil
end
end
end
if line then
nlines[#nlines + 1] = line
end
end
return table.concat(nlines, "")
end
-- load the verify the selected configuration
for line in io.lines("/etc/config.mesh/_setup")
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
line = line:gsub("<NODE>", node):gsub("<MAC2>", mac2):gsub("<DTDMAC>", dtdmac)
local k, v = line:match("^([^%s]*)%s*=%s*(.*)%s*$")
cfg[k] = v
end
end
if cfg.wifi_enable == "1" then
if not cfg.wifi_intf or cfg.wifi_intf == "" then
cfg.wifi_intf = aredn.hardware.get_board_network_ifname("wifi"):match("^(%S+)")
end
local mtu = c:get("aredn", "@lqm[0]", "mtu")
mtu = tonumber(mtu)
if mtu and mtu >= 256 and mtu <= 1500 then
cfg.wifi_mtu = mtu
end
else
cfg.wifi_intf = "br-nomesh"
end
-- Supernode options
local is_supernode = (cm:get("aredn", "@supernode[0]", "enable") == "1")
if is_supernode then
cfg.olsrd_dtd_interface_mode = "isolated"
cfg.olsrd_pollrate = "0.01"
end
-- delete some config lines if necessary
if cfg.wan_proto == "dhcp" then
deleteme.wan_ip = true
deleteme.wan_gw = true
deleteme.wan_mask = true
end
2022-02-27 16:57:51 -07:00
if not is_null(cfg.dmz_mode) or cfg.wan_proto ~= "disabled" then
deleteme.lan_gw = true
end
-- lan_dhcp sense is inverted in the dhcp config file
-- and it is a checkbox so it may not be defined - this fixes that
if cfg.lan_dhcp == "1" then
cfg.lan_dhcp = 0
else
cfg.lan_dhcp = 1
end
2023-12-06 13:19:18 -07:00
-- handle possible remote syslog
2024-01-11 21:51:25 -07:00
local remote_log = cm:get("aredn", "@remotelog[0]", "url") or ""
2023-12-06 13:19:18 -07:00
local proto, ip, port = remote_log:match("^(.+)://(%d+%.%d+%.%d+%.%d+):(%d+)$")
port = tonumber(port)
if proto and (proto == "tcp" or proto == "udp") and (port > 0 and port < 65536) and validate_ip(ip) then
cfg.remote_log_ip = ip
cfg.remote_log_port = port
cfg.remote_log_proto = proto
else
deleteme.remote_log_ip = true
deleteme.remote_log_port = true
deleteme.remote_log_proto = true
end
-- verify that we have all the variables we need
for file in nixio.fs.glob("/etc/config.mesh/*")
do
for line in io.lines(file)
do
if line:match("^[^#]") then
for parm in line:gmatch("<([^%s]*)>")
do
if parm:upper() == parm then
-- nvram variable
if aredn.info.get_nvram(parm:lower()) == "" then
print ("nv parameter '" .. parm .. "' in file '" .. file .. "' does not exist")
return -1
end
else
if not cfg[parm] and not deleteme[parm] then
print ("parameter '" .. parm .. "' in file '" .. file .. "' does not exist")
return -1
end
end
end
end
end
end
-- sensible dmz_mode default
if is_null(cfg.dmz_mode) then
2022-02-27 16:57:51 -07:00
cfg.dmz_mode = "0"
end
-- switch to dmz values if needed
if not is_null(cfg.dmz_mode) then
cfg.lan_ip = cfg.dmz_lan_ip
cfg.lan_mask = cfg.dmz_lan_mask
cfg.dhcp_start = cfg.dmz_dhcp_start
cfg.dhcp_end = cfg.dmz_dhcp_end
cfg.dhcp_limit = cfg.dmz_dhcp_limit
end
-- select ports and dhcp files based on mode
local portfile = "/etc/config.mesh/_setup.ports"
local dhcpfile = "/etc/config.mesh/_setup.dhcp"
First draft of advanced DHCP option specification on Ports tab. (#1073) * First draft of advanced DHCP option specification on Ports tab. Allows the node administrator to specify additional DHCP options that will be supplied to LAN clients in specific circumstances. This change adds two tables to the Ports configuration tab. The "Tags for Advanced DHCP Options" table allows the administrator to specify DHCP tags that will be assigned to clients that identify themselves with specific values for properties such as Vendor Class or MAC address. The "Advanced DHCP Options" table allows the administrator to specify arbitrary DHCP options to send to any client, or only to clients with a specific tag. Option numbers can be entered directly or chosen from a list of well-known options. Option values are manually entered by the administrator. In-browser validation is implemented for all input fields with easily recognizable content such as host names, MAC addresses, and port and option numbers. Placeholders are also supplied for input fields, such as MAC addresses with wildcard matching, that might otherwise be difficult to describe. Issues with the current version: - Sending DHCP options not requested by the client is implemented using the dhcp_option_force UCI configuration option, but does not currently work. - Tagging by client host name is supported by dnsmasq, but not yet by UCI. - DHCP option values must be entered manually by the administrator, but are not currently validated. * Better validation, placeholders, and hints for existing input fields. * Remove junk accidentally inserted in comment. * Preserve Advanced DHCP options across updates.
2024-01-21 18:25:16 -07:00
local dhcptagsfile = "/etc/config.mesh/_setup.dhcptags"
local dhcpoptionsfile = "/etc/config.mesh/_setup.dhcpoptions"
local aliasfile = "/etc/config.mesh/aliases"
local servfile = "/etc/config.mesh/_setup.services"
2022-02-27 16:57:51 -07:00
if is_null(cfg.dmz_mode) then
portfile = portfile .. ".nat"
dhcpfile = dhcpfile .. ".nat"
First draft of advanced DHCP option specification on Ports tab. (#1073) * First draft of advanced DHCP option specification on Ports tab. Allows the node administrator to specify additional DHCP options that will be supplied to LAN clients in specific circumstances. This change adds two tables to the Ports configuration tab. The "Tags for Advanced DHCP Options" table allows the administrator to specify DHCP tags that will be assigned to clients that identify themselves with specific values for properties such as Vendor Class or MAC address. The "Advanced DHCP Options" table allows the administrator to specify arbitrary DHCP options to send to any client, or only to clients with a specific tag. Option numbers can be entered directly or chosen from a list of well-known options. Option values are manually entered by the administrator. In-browser validation is implemented for all input fields with easily recognizable content such as host names, MAC addresses, and port and option numbers. Placeholders are also supplied for input fields, such as MAC addresses with wildcard matching, that might otherwise be difficult to describe. Issues with the current version: - Sending DHCP options not requested by the client is implemented using the dhcp_option_force UCI configuration option, but does not currently work. - Tagging by client host name is supported by dnsmasq, but not yet by UCI. - DHCP option values must be entered manually by the administrator, but are not currently validated. * Better validation, placeholders, and hints for existing input fields. * Remove junk accidentally inserted in comment. * Preserve Advanced DHCP options across updates.
2024-01-21 18:25:16 -07:00
dhcptagsfile = dhcptagsfile .. ".nat"
dhcpoptionsfile = dhcpoptionsfile .. ".nat"
aliasfile = aliasfile .. ".nat"
servfile = servfile .. ".nat"
else
portfile = portfile .. ".dmz"
dhcpfile = dhcpfile .. ".dmz"
First draft of advanced DHCP option specification on Ports tab. (#1073) * First draft of advanced DHCP option specification on Ports tab. Allows the node administrator to specify additional DHCP options that will be supplied to LAN clients in specific circumstances. This change adds two tables to the Ports configuration tab. The "Tags for Advanced DHCP Options" table allows the administrator to specify DHCP tags that will be assigned to clients that identify themselves with specific values for properties such as Vendor Class or MAC address. The "Advanced DHCP Options" table allows the administrator to specify arbitrary DHCP options to send to any client, or only to clients with a specific tag. Option numbers can be entered directly or chosen from a list of well-known options. Option values are manually entered by the administrator. In-browser validation is implemented for all input fields with easily recognizable content such as host names, MAC addresses, and port and option numbers. Placeholders are also supplied for input fields, such as MAC addresses with wildcard matching, that might otherwise be difficult to describe. Issues with the current version: - Sending DHCP options not requested by the client is implemented using the dhcp_option_force UCI configuration option, but does not currently work. - Tagging by client host name is supported by dnsmasq, but not yet by UCI. - DHCP option values must be entered manually by the administrator, but are not currently validated. * Better validation, placeholders, and hints for existing input fields. * Remove junk accidentally inserted in comment. * Preserve Advanced DHCP options across updates.
2024-01-21 18:25:16 -07:00
dhcptagsfile = dhcptagsfile .. ".dmz"
dhcpoptionsfile = dhcpoptionsfile .. ".dmz"
aliasfile = aliasfile .. ".dmz"
servfile = servfile .. ".dmz"
end
-- check for old aliases file, copy it to .dmz and create symlink
-- just in case anyone is already using the file for some script or something
if not nixio.fs.readlink("/etc/config.mesh/aliases") then
if nixio.fs.stat("/etc/config.mesh/aliases") then
filecopy("/etc/config.mesh/aliases", "/etc/config.mesh/aliases.dmz")
os.remove("/etc/config.mesh/aliases")
else
io.open("/etc/config.mesh/aliases.dmz", "a"):close()
end
nixio.fs.symlink("aliases.dmz", "/etc/config.mesh/aliases")
end
-- generate the new school bridge configuration
if nixio.fs.stat("/etc/aredn_include/bridge.network.user") then
cfg.bridge_network_config = expand_vars(read_all("/etc/aredn_include/bridge.network.user"))
if not valid_config(cfg.bridge_network_config) then
print("Invalid config fragment: /etc/aredn_include/bridge.network.user")
os.exit(1)
end
else
local list = {}
for _, net in ipairs({ "lan", "wan", "dtdlink" })
do
local ports = aredn.hardware.get_board_network_ifname(net):split(" ")
for _, port in ipairs(ports)
do
list[port:gsub("%..*$", "")] = true
end
end
local config = "config device\n option name 'br0'\n option type 'bridge'\n option vlan_filtering '1'\n"
for port, _ in pairs(list)
do
config = config .. " list ports '" .. port .. "'\n"
end
cfg.bridge_network_config = config
end
-- generate the network configurations
for _, net in ipairs({ "lan", "wan", "dtdlink", "wifi" })
do
local wireless = false
local config = ""
-- user override
if nixio.fs.stat("/etc/aredn_include/" .. net .. ".network.user") then
if nixio.fs.stat("/etc/aredn_include/fixedmac." .. net) then
for line in io.lines("/etc/aredn_include/fixedmac." .. net)
do
local m = line:match("option%s+macaddr%s+(%S+)")
if m then
cfg[net .. "_mac"] = m
end
end
end
config = expand_vars(read_all("/etc/aredn_include/" .. net .. ".network.user"))
if not valid_config(config) then
print("Invalid config fragment: /etc/aredn_include/" .. net .. ".network.user")
os.exit(1)
end
else
-- generate a complete config
local vlan = nil
local ports = aredn.hardware.get_board_network_ifname(net):split(" ")
if net == "lan" then
-- If the LAN has be given a vlan to use (usually by a switch) we use that here,
-- otherwise we just use '3'
local lvlan = ports[1]:match("%.(%d+)$")
if lvlan then
vlan = lvlan .. ":t"
else
vlan = "3:u"
end
elseif net == "wan" then
-- wifi can be used for the WAN (we become a wifi client)
if cfg.wifi3_enable == "1" then
-- WAN uses wifi
wireless = true
ports = { "wlan0" }
for devname in nixio.fs.dir(ieee80211)
do
local hwmode = "11g"
if iwinfo.nl80211.freqlist(devname)[1].mhz > 5000 then
hwmode="11a"
end
if hwmode == cfg.wifi3_hwmode then
ports = { "wlan" .. devname:match("^phy(%d+)$") }
break
end
end
else
-- If the WAN has been given a vlan to use (usually 1) we use that here.
local wvlan = ports[1]:match("%.(%d+)$")
if wvlan then
vlan = wvlan .. ":t"
else
vlan = "4:u"
end
-- handle wan vlan override
for line in io.lines("/etc/config.mesh/_setup")
do
local wport, wvlan = line:match("^wan_intf = (%w+%.)(%d+)")
if wvlan then
vlan = wvlan .. ":t"
ports = { wport .. wvlan }
break
end
end
end
elseif net == "dtdlink" then
-- Always vlan 2
vlan = "2:t"
cfg.dtdlink_proto = "static"
cfg.dtdlink_mask = "255.0.0.0"
elseif net == "wifi" then
wireless = true
ports = { cfg.wifi_intf }
end
if vlan then
-- new school vlan configuration
local v, t = vlan:match("(.*):(.*)")
config = config .. "\nconfig bridge-vlan\n option device 'br0'\n option vlan '" .. v .. "'\n"
for _, port in ipairs(ports)
do
config = config .. " list ports '" .. port:gsub("%..*$", "") .. ":" .. t .. "'\n"
end
config = config .. "\n"
ports = { "br0." .. v }
end
local proto = cfg[net .. "_proto"] or ""
local ipaddr = cfg[net .. "_ip"] or ""
local netmask = cfg[net .. "_mask"] or ""
local mtu = cfg[net .. "_mtu"] or ""
local dns1 = ""
local dns2 = ""
if net == "lan" then
dns1 = cfg.wan_dns1 or ""
dns2 = cfg.wan_dns2 or ""
end
local gateway = cfg[net .. "_gw"] or ""
config = config .. "config device\n"
if not wireless then
config = config .. " option name 'br-" .. net .. "'\n option type 'bridge'\n"
elseif cfg.wifi_enable ~= "1" then
netmask = "255.255.255.255"
end
if nixio.fs.stat("/etc/aredn_include/fixedmac." .. net) then
config = config .. read_all("/etc/aredn_include/fixedmac." .. net)
end
if not wireless then
if #ports == 0 then
config = config .. " option bridge_empty '1'\n"
else
for _, port in ipairs(ports)
do
config = config .. " list ports '" .. port .. "'\n"
end
end
else
config = config .. " option name '" .. ports[1] .. "'\n"
if not ports[1]:match("^wlan") then
config = config .. " option type 'bridge'\n option bridge_empty '1'\n"
end
Update AREDN to OpenWRT 22.3.2 (Major Upgrade) (#574) * Update to Openwrt 21.02 and add support for the CPE710 v1 Update scripts to change references to ifname to device due to a change in Openwrt naming reverse-wpad-basic-wolfssl and disable SSL on Curl NOTE: The compile host must have python3-distutils installed for gpsd to build * aredn: initial working upgrade to openwrt 21.02.1 * aredn: update 1 to working upgrade to openwrt 21.02.1 * aredn: add cpe710v1 to build config * Andrew's patches * Remove duplicates + display perl * Temp disable wifi extension patch * ifname/ports support * Add spectrum patch back in * Generic function to extra interfaces * New api to get wifi ifname * Disables jails * Style link * aredn: partial upgrade to openwrt 22.0.3.0 added AC device images and partial migration to 22.0.3.0 firewall upgrade pending * aredn: update mesh-release and revert config.mk * Unused * NFT firewall rewrite * Common-isze configs * Fix network layout for hap2 * Use local packages dev (new firewall rules) * Add HAP2 * Add pause after network restart to let bridge reinitialize * Various lua fixes for new lua version * Tweak config * Re-fix networking (lost patch change) * Add new radio names * Tolerate missing wifi * Fix hap-lite switch setup * More devices * New radio id * Build Rocket 5AC lite * Remove need for luci.sys * Remove need for luci.sys * Explicitly name wlan interfaces * Handle different compatibility verisoning * Update networking for switches * ipref version bump * Extra flag for curl * Better compat_version fix * Remove wolfssl * Fix dns server * Fix device name * Unused * Remove things we dont need * Remove unused packages * Generic macaddr overrides * Fix uci commit * Fix luci.template.parser to avoid luci.http loading the real thing * Rocket-M build * Add search-domain dhcp option * Turn of ipv6 * No IPV6 in dnsmasq * Override mac addresses if devices all the same * Working from master (for now) * Put back hostap * Disable old ethmac fixup * Tweak configs * Move back to v22.03.2 Leave ipq4019 builds to master * Need IPV6 to compile nft firewall * Rocket-M fixes * Before we start * WIP * Working snapshot * Cleaned patches * Merged patch * Single patch to support HAP2 * Fix typo * Add nanostation-m * 5/10Mhz patch * 5+10MHz patch for ath10k-ct driver * Extend 2Ghz channel check to include -4 to -1 * Add chanbw setup for ath10k (like ath9k) * Added TP-Link CPE710 v1 * Override firmwares * Missing patch * Dropbear config like 3.22.8.0 * Add Ubiquiti Rocket 5AC Lite * Fix c6 * Update * Need more scan channels * Remove IPV6 * Improve mac fixups * Put back missing nft app * IPv6 removed so dont have to disable it * Fix rocket-m flash bug * Fix nanostation-m * Nanobridge is tiny * Fix wifi order for ar750 * Rocket M5 XW support * New rates * Fix firewall4 so we don't need IPv6 * Allow channel width to be restricted * Move channel list into library * Fix naming * Mechanism to block specific channels on specific radios * Refresh buttons * routerboard-sxt-5nd * CPE605 v1.0 * Improve rocket m xw * tpink * Update patch * Update to remove disable * Remove BW restrictions on cpe710 * Restrict to what has been tested * Remove test BW restrictions * sxtsq-5-ac * Update * Update * powerbeam-m5-300 support * Fix * Fix hap2 * Tidy unused patches * Remove limit * Add ubnt_bullet-m-ar7241 * Added ubnt_nanobeam-ac-gen2 * Fix typo * Tolerate missing dtd ip * Explicitly gix hap2 mac addresses * Fix some broken patches * Hap2 wont work at 5MHz * Ubiquiti LiteBeam 5AC Gen2 * Fix compat_version for sxt 5ac * Update patch * Unused * Fix lan configuration for some devices * Rolling average of noise level * Unused * Split out the ath10k rssi monitor (its very simple at the moment) * Ignore .DS_Store * Reboot if ethernet doesnt come up (but only once!) * reboot returns - add exit * Add some logging info * Fix ] * Check all possibly ethernet bridges * Improve mac fixing * Remove HostAP on small memory devices * Reduce dropbear footprint * Add setsid * Kill hostap when upgrading to save memory * Different way to detect hostapd unavailable * New build steps * Improve manager logging * Fix name conflict for the two monitors * Try to improve test mesh name resolve problem * Migrate tiny to generic (tiny doesnt work properly) * Typo * Another attempt to fix macs for Mikrotik * Protect against missing trackers * Fix wpad for ipq40xx * Remove old tunnel check code * Enable ZRAM swap to aid low memory devices * ath10k noise can something be out of range - protect against that * Updated with current devices and status * Update firmware which has been tested * Updated with more builds * More binary/README * Fix css error * Start noise at sensible base level * Unfix the css so it looks how it use to. * Save as much memory as we can on lowmem nodes * Hide some options on low memory devices * Add "eol" to 32MB devices * Restart network rather than reboot node if it seems to be broken * Fixes * Revert network reset * Fix ar750 networking * Continue to trim tiny configs * More devices * Dump IW output messages * Fix Rocket 5AC intermittent ethernet issue * Ethernet fix for PowerBeam 5AC 500 * More tiny size reduction * More support data * Fixed POE and USB power features * Add Ubiquiti NanoBeam AC (gen1) * NanoStation (not NanoBeam) * Add mii-tool package * Device updates * Bump update time to 5 minutes * Fix ethernet negotiation for rocker-5ac and nanobeam * Fix iplookup * Config changes based on call feedback * Radio listing fixes * Update with more untested builds * Fallback TxMbps extracted from iw station dump * Fix tunnel detection for low memory nodes * Remove unused feed packages * snapshot build * Update stability info * Add powerbeam-5ac-500 * Typo * Add missing 3.22.1.0 * Add MikroTik LHG 5 AC * Fix permissions * Fix permissions * AirGrid's take Bullet builds * Mikrotik AC3 * Improve supportdata structure a little to make it easier to find things * Restore WAN VLAN overrides * Fix vlan regex for hap2 and hap3 * Support old and new style poe controls * hap-ac3 is version 1.1 * Handle typo in some openwrt config files * Fix HAP AC3 install * Update hap ac3 status * Support user overrides for network ports (non-swconfig devices) * LHG 5AC support * Remove -nand * Remove non-working platform.sh change * tunnel weight override * Omit LinkQualityMult when value is 1 * Add mANTBox 19s and 15s * Support ath79 mikrotik devices which require ath10k in the initramfs Co-authored-by: apcameron <apcameron@softhome.net> Co-authored-by: Joe AE6XE <ae6xe@arrl.net> Co-authored-by: Joe Ayers <joe@arrl.net>
2022-12-22 13:22:49 -07:00
end
config = config .. "\nconfig interface " .. net .. "\n"
if wireless then
config = config .. " option device '" .. ports[1] .. "'\n"
else
config = config .. " option device 'br-" .. net .. "'\n"
end
if proto ~= "" then
config = config .. " option proto '" .. proto .. "'\n"
end
if mtu ~= "" then
config = config .. " option mtu '" .. mtu .. "'\n"
end
if ipaddr ~= "" then
config = config .. " option ipaddr '" .. ipaddr .. "'\n"
end
if netmask ~= "" then
config = config .. " option netmask '" .. netmask .. "'\n"
end
if dns1 ~= "" or dns2 ~= "" then
config = config .. " option dns '" .. (dns1 or "") .. (dns1 and dns2 and " " or "") .. (dns2 or "") .. "'\n"
end
if gateway ~= "" then
config = config .. " option gateway '" .. gateway .. "'\n"
end
end
cfg[net .. "_network_config"] = config
end
-- Generate the tunnel configurations
local tun_port = cm:get("vtun", "@options[0]", "port")
if tun_port then
cfg.tun_network_config = cfg.tun_network_config .. "config options\n\toption port '" .. tun_port .. "'\n\n"
end
local tun_start = cm:get("vtun", "@network[0]", "start")
local tun_dns = cm:get("vtun", "@network[0]", "dns")
if tun_start or tun_dns then
cfg.tun_network_config = cfg.tun_network_config .. "config network\n"
if tun_start then
cfg.tun_network_config = cfg.tun_network_config .. "\toption start '" .. tun_start .. "'\n"
end
if tun_dns then
cfg.tun_network_config = cfg.tun_network_config .. "\toption dns '" .. tun_dns .. "'\n"
end
cfg.tun_network_config = cfg.tun_network_config .. "\n"
end
local vtunclients = 0
cm:foreach("vtun", "client",
function(s)
if s.enabled == "1" then
cfg.tun_network_config = cfg.tun_network_config .. string.format("config client\n\toption enabled '1'\n\toption node '%s'\n\toption passwd '%s'\n\toption clientip '%s'\n\toption serverip '%s'\n\toption netip '%s'\n\n",
s.node:upper(), s.passwd, s.clientip, s.serverip, s.netip)
vtunclients = vtunclients + 1
end
end
)
local wgclients = 0
cm:foreach("wireguard", "client",
function(s)
if s.enabled == "1" then
2024-01-07 17:17:52 -07:00
local server_priv, _, _, client_pub = s.key:match("^(.+=)(.+=)(.+=)(.+=)$")
local addr, port = s.clientip:match("^(%d+%.%d+%.%d+%.%d+):(%d+)$")
cfg.wireguard_network_config = cfg.wireguard_network_config ..
2024-01-07 17:17:52 -07:00
string.format("config interface 'wgc%d'\n\toption proto 'wireguard'\n\toption private_key '%s'\n\toption nohostroute '1'\n\toption listen_port '%s'\n\tlist addresses '%s'\n\n",
wgclients, server_priv, port, addr)
2024-01-07 17:17:52 -07:00
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config wireguard_wgc%d\n\toption public_key '%s'\n\toption persistent_keepalive '25'\n\tlist allowed_ips '0.0.0.0/0'\n\n",
wgclients, client_pub)
wgclients = wgclients + 1
end
end
)
local vtunservers = 0
local wgservers = 0
cm:foreach("vtun", "server",
function(s)
if s.enabled == "1" then
2024-01-07 17:17:52 -07:00
if s.netip:match(":") then
local server_pub, client_priv, client_pub = s.passwd:match("^(.+=)(.+=)(.+=)$")
2024-01-07 17:17:52 -07:00
local abc, d, p = s.netip:match("^(%d+%.%d+%.%d+)%.(%d+):(%d+)")
d = tonumber(d) + 1
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config interface 'wgs%d'\n\toption proto 'wireguard'\n\toption private_key '%s'\n\toption nohostroute '1'\n\tlist addresses '%s'\n\n",
wgservers, client_priv, (abc .. "." .. d))
cfg.wireguard_network_config = cfg.wireguard_network_config ..
string.format("config wireguard_wgs%d\n\toption public_key '%s'\n\toption endpoint_host '%s'\n\toption endpoint_port '%s'\n\toption persistent_keepalive '25'\n\tlist allowed_ips '0.0.0.0/0'\n\n",
2024-01-07 17:17:52 -07:00
wgservers, server_pub, s.host, p)
wgservers = wgservers + 1
else
cfg.tun_network_config = cfg.tun_network_config ..
string.format("config server\n\toption enabled '1'\n\toption host '%s'\n\toption node '%s'\n\toption passwd '%s'\n\toption clientip '%s'\n\toption serverip '%s'\n\toption netip '%s'\n\n",
s.host, s.node:upper(), s.passwd, s.clientip, s.serverip, s.netip)
vtunservers = vtunservers + 1
end
end
end
)
-- Create the tunnel devices we need
local maxclients = 0
local maxservers = 0
-- No tunnel devices without the vtund app
if nixio.fs.stat("/usr/sbin/vtund") then
maxclients = 10 * math.ceil(vtunclients / 10)
maxservers = 10 * math.ceil(vtunservers / 10)
end
2023-12-13 00:57:36 -07:00
for dev = 50, 50 + maxclients + maxservers - 1
do
cfg.tun_devices_config = cfg.tun_devices_config ..
string.format("config interface 'tun%d'\n\toption ifname 'tun%d'\n\toption proto 'none'\n\n", dev, dev)
end
-- Not wireguard devices without the wg app
if not nixio.fs.stat("/usr/bin/wg") then
wgclients = 0
wgservers = 0
end
remove_all("/tmp/new_config")
nixio.fs.mkdir("/tmp/new_config")
for file in nixio.fs.glob("/etc/config.mesh/*")
do
local bfile = nixio.fs.basename(file)
if bfile == "vtun" or bfile == "wireguard" or bfile == "xlink" or bfile == "olsrd" or bfile == "firewall.user" or bfile:match("^_setup") or bfile:match("^aliases") then
-- Dont copy these
else
local f = io.open("/tmp/new_config/" .. bfile, "w")
if f then
f:write(expand_vars(read_all(file)))
f:close()
end
end
end
-- Tunnels
write_all("/tmp/new_config/vtun", expand_vars("<tun_network_config>"))
local nc = uci.cursor("/tmp/new_config")
-- append to firewall
local add_masq = false
local fw = io.open("/tmp/new_config/firewall", "a")
if fw then
if not is_null(cfg.dmz_mode) then
fw:write("\nconfig forwarding\n option src wifi\n option dest lan\n")
fw:write("\nconfig forwarding\n option src dtdlink\n option dest lan\n")
add_masq = true
else
fw:write("\nconfig 'include'\n option 'path' '/etc/firewall.natmode'\n option 'reload' '1'\n")
end
if nc:get("aredn", "@wan[0]", "olsrd_gw") == "1" then
fw:write("\nconfig forwarding\n option src wifi\n option dest wan\n")
fw:write("\nconfig forwarding\n option src dtdlink\n option dest wan\n")
end
if nixio.fs.access(portfile) then
for line in io.lines(portfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local dip = line:match("dmz_ip = (%w+)")
if dip and cfg.dmz_mode ~= 0 then
fw:write("\nconfig redirect\n option src wifi\n option proto tcp\n option src_dip " .. cfg.wifi_ip .. "\n option dest_ip " .. dip .. "\n")
fw:write("\nconfig redirect\n option src wifi\n option proto udp\n option src_dip " .. cfg.wifi_ip .. "\n option dest_ip " .. dip .. "\n")
else
local intf, type, oport, host, iport, enable = line:match("(.*):(.*):(.*):(.*):(.*):(.*)")
if enable == "1" then
local match = " option src_dport " .. oport .. "\n"
if type == "tcp" then
match = match .. " option proto tcp\n"
elseif type == "udp" then
match = match .. " option proto udp\n"
end
-- uci the host and then
-- set the inside port unless the rule uses an outside port range
host = "option dest_ip " .. host .. "\n"
if not oport:match("-") then
host = host .. " option dest_port " .. iport .. "\n"
end
if not is_null(cfg.dmz_mode) and intf == "both" then
intf = "wan"
end
if intf == "both" then
fw:write("\nconfig redirect\n option src wifi\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("\nconfig redirect\n option src dtdlink\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("config redirect\n option src wan\n " .. match .. " " .. host .. "\n")
elseif intf == "wifi" and is_null(cfg.dmz_mode) then
fw:write("\nconfig redirect\n option src dtdlink\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("\nconfig redirect\n option src wifi\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
elseif intf == "wan" then
fw:write("\nconfig redirect\n option src dtdlink\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("config redirect\n option src wan\n " .. match .. " " .. host .. "\n")
end
end
end
end
end
end
fw:close();
end
if add_masq then
nc:set("firewall", "@zone[2]", "masq", "0")
nc:commit("firewall")
end
-- setup node lan dhcp
First draft of advanced DHCP option specification on Ports tab. (#1073) * First draft of advanced DHCP option specification on Ports tab. Allows the node administrator to specify additional DHCP options that will be supplied to LAN clients in specific circumstances. This change adds two tables to the Ports configuration tab. The "Tags for Advanced DHCP Options" table allows the administrator to specify DHCP tags that will be assigned to clients that identify themselves with specific values for properties such as Vendor Class or MAC address. The "Advanced DHCP Options" table allows the administrator to specify arbitrary DHCP options to send to any client, or only to clients with a specific tag. Option numbers can be entered directly or chosen from a list of well-known options. Option values are manually entered by the administrator. In-browser validation is implemented for all input fields with easily recognizable content such as host names, MAC addresses, and port and option numbers. Placeholders are also supplied for input fields, such as MAC addresses with wildcard matching, that might otherwise be difficult to describe. Issues with the current version: - Sending DHCP options not requested by the client is implemented using the dhcp_option_force UCI configuration option, but does not currently work. - Tagging by client host name is supported by dnsmasq, but not yet by UCI. - DHCP option values must be entered manually by the administrator, but are not currently validated. * Better validation, placeholders, and hints for existing input fields. * Remove junk accidentally inserted in comment. * Preserve Advanced DHCP options across updates.
2024-01-21 18:25:16 -07:00
function load_dhcp_tags(dhcptagsfile)
local dhcp_tags = {}
for line in io.lines(dhcptagsfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local name, condition, pattern = line:match("(%S+)%s+(%S+)%s+(.*)")
if pattern then
local cond_table = dhcp_tags[condition]
if not cond_table then
cond_table = {}
dhcp_tags[condition] = cond_table
end
table.insert(cond_table, {name = name, pattern = pattern})
end
end
end
return dhcp_tags
end
function load_dhcp_options(dhcpoptionsfile)
local dhcp_options = {}
for line in io.lines(dhcpoptionsfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local tag, force, opt_num, opt_val = line:match("(%S*)%s+(%w+)%s+(%d+)%s+(.*)")
if opt_val then
table.insert(dhcp_options, {
tag = tag,
force = force == "force",
num = opt_num,
val = opt_val})
end
end
end
return dhcp_options
end
if nixio.fs.access(dhcptagsfile) then
for condition, cond_table in pairs(load_dhcp_tags(dhcptagsfile))
do
for i, props in ipairs(cond_table)
do
nc:add("dhcp", condition)
nc:set("dhcp", string.format("@%s[%d]", condition, i-1), "networkid", props.name)
nc:set("dhcp", string.format("@%s[%d]", condition, i-1), condition, props.pattern)
end
end
end
First draft of advanced DHCP option specification on Ports tab. (#1073) * First draft of advanced DHCP option specification on Ports tab. Allows the node administrator to specify additional DHCP options that will be supplied to LAN clients in specific circumstances. This change adds two tables to the Ports configuration tab. The "Tags for Advanced DHCP Options" table allows the administrator to specify DHCP tags that will be assigned to clients that identify themselves with specific values for properties such as Vendor Class or MAC address. The "Advanced DHCP Options" table allows the administrator to specify arbitrary DHCP options to send to any client, or only to clients with a specific tag. Option numbers can be entered directly or chosen from a list of well-known options. Option values are manually entered by the administrator. In-browser validation is implemented for all input fields with easily recognizable content such as host names, MAC addresses, and port and option numbers. Placeholders are also supplied for input fields, such as MAC addresses with wildcard matching, that might otherwise be difficult to describe. Issues with the current version: - Sending DHCP options not requested by the client is implemented using the dhcp_option_force UCI configuration option, but does not currently work. - Tagging by client host name is supported by dnsmasq, but not yet by UCI. - DHCP option values must be entered manually by the administrator, but are not currently validated. * Better validation, placeholders, and hints for existing input fields. * Remove junk accidentally inserted in comment. * Preserve Advanced DHCP options across updates.
2024-01-21 18:25:16 -07:00
do
local dhcp_option_list = {}
if nc:get("aredn", "@wan[0]", "lan_dhcp_route") == "1" or nc:get("aredn", "@wan[0]", "lan_dhcp_defaultroute") == "1" then
-- Provide stateless routes and default route
table.insert(dhcp_option_list, "121,10.0.0.0/8," .. cfg.lan_ip .. ",0.0.0.0/0," .. cfg.lan_ip)
table.insert(dhcp_option_list, "249,10.0.0.0/8," .. cfg.lan_ip .. ",0.0.0.0/0," .. cfg.lan_ip)
else
-- Provide stateless routes to the mesh, and a blank default route (option 3 has no values) to
-- suppress default route being sent
table.insert(dhcp_option_list, "121,10.0.0.0/8," .. cfg.lan_ip)
table.insert(dhcp_option_list, "249,10.0.0.0/8," .. cfg.lan_ip)
table.insert(dhcp_option_list, "3")
end
if nixio.fs.access(dhcpoptionsfile) then
local forced_advanced_options = {}
for _, option in ipairs(load_dhcp_options(dhcpoptionsfile))
do
local parts = {}
if option.tag ~= "" then
table.insert(parts, "tag:" .. option.tag)
end
table.insert(parts, option.num)
table.insert(parts, option.val)
table.insert(option.force and forced_advanced_options or dhcp_option_list, table.concat(parts, ","))
end
if #forced_advanced_options > 0 then
nc:set("dhcp", "@dhcp[0]", "dhcp_option_force", forced_advanced_options)
end
end
if #dhcp_option_list > 0 then
nc:set("dhcp", "@dhcp[0]", "dhcp_option", dhcp_option_list)
end
end
nc:commit("dhcp")
-- generate the wireless config file
local config = ""
local ifacecount = aredn.hardware.get_radio_count()
Initial OpenWRT 23.05.0 merge (#963) * Initial OpenWRT 23.05.0 merge * Fix get_rfchannels for new iwinfo format * Fix initial wlan name * Move patches to 5.15 from 5.10 * Fix flash write problem on Ubiquiti devices * Use new ssl patch * Reduce binary sizes * Have to have hostapd installed now, even on tiny builds * Simplify device support * Revert Mikrotik NAND sysupgrade system. OpenWRT doesnt really support Mikrotik NAND devices after 2019 and the new support appeared broken. So reverted to the 2022 mechanism which does work and avoid upgrade problems. * Fixes for tiny builds * More tiny shrinking * Fix newly added firewall rules * Update permanent packages * Update permanent packages * Support for Nanobeam 2AC (2.4GHz) device. 20MHz channels only. * Update support * Add GL.iNet B1300 * Add to radios.json * Update supported devices * Dont force the LAN DHCP to run * Revert CURL SSL test * Fix radio count when there are no radios * Switch the lan ports on the gl-b1300 * Add support for GL.iNET Beryl MT1300 * Fix visual lat/lon setting bug * Make the setup "Save Changes" button also save the location data * Fix location/map system with geo location fallback * Recolor * Fix default bandwidth selection * Support multi-band radios * Generic mechanism to set compat version to 1.1 * Switch ethernet ports * 20 MHz channels only * Update docs * Add ham channels to Mediatek chips (20MHz only) * Automatically update the permpkg list when we upgrade * Fix 10MHz mode for Ubiquiti AC devices * Fix tiny builds * Bump the watch timeout for restarting olsrd olsrd is reliable these days, and very occasionally this was restarting it unnecessarily
2023-12-06 11:12:11 -07:00
local devpaths = {}
for dev = 0, ifacecount - 1
do
local devname = "phy" .. dev
local radio = "radio" .. dev
local wlan = "wlan" .. dev
local devpath = nixio.fs.realpath(ieee80211 .. nixio.fs.readlink(ieee80211 .. devname)):match("^/sys/devices/(.*)/ieee802.*$")
if devpath:match("^platform.*/pci.*") then
devpath = devpath:match("^platform/(.*)")
end
local devpathc = devpaths[devpath] or 0
devpaths[devpath] = devpathc + 1
if devpathc > 0 then
devpath = devpath .. "+" .. devpathc
end
local is_mesh_rf = false
local htmode = "HT20"
local disabled = "0"
local chanbw = nil
local country = nil
local channel = nil
local distance = nil
local hwmode = "11g"
if iwinfo.nl80211.freqlist(devname)[1].mhz > 5000 then
hwmode="11a"
end
local network = nil
local mode = nil
local ssid = nil
local encryption = nil
local key = nil
if wlan == cfg.wifi_intf then
-- mesh RF adhoc configuration
is_mesh_rf = true
channel = cfg.wifi_channel
chanbw = cfg.wifi_chanbw
country = "HX"
distance = cfg.wifi_distance
ssid = cfg.wifi_ssid .. "-" .. chanbw .. "-v3"
mode = "adhoc"
encryption = "none"
network = "wifi"
elseif cfg.wifi2_enable == "1" and (ifacecount == 1 or (ifacecount > 1 and hwmode == cfg.wifi2_hwmode)) then
-- lan AP interface
channel = cfg.wifi2_channel
ssid = h2s(cfg.wifi2_ssid)
mode = "ap"
encryption = cfg.wifi2_encryption
key = h2s(cfg.wifi2_key)
network = "lan"
elseif cfg.wifi3_enable == "1" and (ifacecount == 1 or (ifacecount > 1 and hwmode == cfg.wifi3_hwmode)) then
-- wan client
ssid = h2s(cfg.wifi3_ssid)
mode = "sta"
if cfg.wifi3_key and cfg.wifi3_key ~= "" then
encryption = "psk2"
key = h2s(cfg.wifi3_key)
else
encryption = "none"
end
network = "wan"
htmode = nil
else
disabled = "1"
end
config = config .. "config wifi-device '" .. radio .. "'\n option type 'mac80211'\n"
config = config .. " option disabled '" .. disabled .. "'\n"
if channel then
config = config .. " option channel '" .. channel .. "'\n"
end
if chanbw then
config = config .. " option chanbw '" .. chanbw .. "'\n"
end
if country then
config = config .. " option country '" .. country .. "'\n"
end
if distance then
config = config .. " option distance '" .. distance .. "'\n"
end
config = config .. " option hwmode '" .. hwmode .. "'\n"
if htmode then
config = config .. " option htmode '" .. htmode .. "'\n"
end
config = config .. " option path '" .. devpath .. "'\n\n"
config = config .. "config wifi-iface\n"
config = config .. " option ifname '" .. wlan .. "'\n"
config = config .. " option device '" .. radio .. "'\n"
if network then
config = config .. " option network '" .. network .. "'\n"
end
if mode then
config = config .. " option mode '" .. mode .. "'\n"
end
if ssid then
config = config .. " option ssid '" .. ssid .. "'\n"
end
if encryption then
config = config .. " option encryption '" .. encryption .. "'\n"
end
if key then
config = config .. " option key '" .. key .. "'\n"
end
config = config .. "\n"
if is_mesh_rf and wifi_mon_enable then
config = config .. "config wifi-iface\n"
config = config .. " option ifname '" .. wlan .. "-1'\n"
config = config .. " option device '" .. radio .. "'\n"
config = config .. " option network 'wifi_mon'\n option mode 'monitor'\n\n"
end
end
write_all("/tmp/new_config/wireless", config)
-- indicate whether lan is running in dmz mode
nc:set("aredn", "@dmz[0]", "mode", cfg.dmz_mode)
nc:commit("aredn")
-- generate the host and ethers files
local h = io.open("/etc/hosts", "w")
local e = io.open("/etc/ethers", "w")
if h and e then
h:write("# automatically generated file - do not edit\n")
h:write("# use /etc/hosts.user for custom entries\n")
h:write("127.0.0.1\tlocalhost\n")
if not is_null(cfg.wifi_ip) then
h:write(cfg.lan_ip .. "\tlocalnode\n")
h:write(cfg.wifi_ip .. "\t" .. node .. " " .. tactical .. "\n")
else
h:write(cfg.lan_ip .. "\tlocalnode " .. node .. " " .. tactical .. "\n")
end
if not is_null(cfg.dtdlink_ip) then
h:write(cfg.dtdlink_ip .. "\tdtdlink." .. node .. ".local.mesh dtdlink." .. node .."\n")
end
if is_null(cfg.dmz_mode) then
h:write(decimal_to_ip(ip_to_decimal(cfg.lan_ip) + 1) .. "\tlocalap\n")
end
e:write("# automatically generated file - do not edit\n")
e:write("# use /etc/ethers.user for custom entries\n")
local netaddr = nixio.bit.band(ip_to_decimal(cfg.lan_ip), ip_to_decimal(cfg.lan_mask))
if nixio.fs.access(dhcpfile) then
for line in io.lines(dhcpfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local mac, ip, host, noprop = line:match("(%S+)%s+(%S+)%s+(%S+)%s*(%S*)")
if mac and ip and host and noprop then
ip = decimal_to_ip(netaddr + ip)
if validate_same_subnet(ip, cfg.lan_ip, cfg.lan_mask) and validate_ip_netmask(ip, cfg.lan_mask) then
h:write(ip .. "\t" .. host .. " " .. noprop .. "\n")
e:write(mac .. "\t" .. ip .. "\n")
end
end
end
end
end
-- aliases need to ba added to /etc/hosts or they will now show up on the localnode
-- nor will the services thehy offer
-- also add a comment to the hosts file so we can display the aliases differently if needed
local f = io.open(aliasfile, "r")
if f then
for line in f:lines()
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local ip, host = line:match("(%S+)%s+(%S+)")
if ip then
if host:match("%.") and not host:match("%.local%.mesh$") then
host = host .. ".local.mesh"
end
h:write(ip .. "\t" .. host .. " #ALIAS\n")
end
end
end
f:close()
end
h:write("\n")
if nixio.fs.access("/etc/hosts.user", "r") then
for line in io.lines("/etc/hosts.user")
do
h:write(line .. "\n")
end
end
if nixio.fs.access("/etc/ethers.user", "r") then
for line in io.lines("/etc/ethers.user")
do
e:write(line .. "\n")
end
end
h:close()
e:close()
end
-- generate olsrd.conf
if nixio.fs.access("/etc/config.mesh/olsrd", "r") then
local of = io.open("/tmp/new_config/olsrd", "w")
if of then
for line in io.lines("/etc/config.mesh/olsrd")
do
if line:match("<olsrd_bridge>") then
if is_null(cfg.olsrd_bridge) then
line = line:gsub("<olsrd_bridge>", '"wifi" "lan"')
else
line = line:gsub("<olsrd_bridge>", '"lan"')
end
elseif line:match("^[^#]") then
for parm in line:gmatch("<([^%s]*)>")
do
line = line:gsub("<" .. parm .. ">", cfg[parm])
end
end
of:write(line .. "\n")
end
if not is_null(cfg.dmz_mode) then
local a, b, c, d = cfg.dmz_lan_ip:match("(.*)%.(.*)%.(.*)%.(.*)")
of:write(string.format("\nconfig Hna4\n\toption netaddr %s.%s.%s.%d\n\toption netmask 255.255.255.%d\n\n", a, b, c, d - 1, nixio.bit.band(255 * 2 ^ cfg.dmz_mode, 255)))
end
if cfg.wifi_enable ~= "1" and not is_null(cfg.wifi_ip) then
of:write(string.format("config Hna4\n\toption netaddr %s\n\toption netmask 255.255.255.255\n\n", cfg.wifi_ip))
end
if is_supernode then
of:write("config Hna4\n\toption netaddr 10.0.0.0\n\toption netmask 255.0.0.0\n\n")
end
if nixio.fs.stat("/etc/config.mesh/xlink") then
uci.cursor("/etc/config.mesh"):foreach("xlink", "interface",
function(section)
if section.netmask ~= "255.255.255.255" then
local addr = decimal_to_ip(nixio.bit.band(ip_to_decimal(section.ipaddr), ip_to_decimal(section.netmask)))
of:write(string.format("config Hna4\n\toption netaddr %s\n\toption netmask %s\n\n", addr, section.netmask))
end
end
)
end
if nc:get("aredn", "@wan[0]", "olsrd_gw") == "1" then
of:write("config LoadPlugin\n\toption library 'olsrd_dyn_gw.so.0.5'\n\toption Interval '60'\n\tlist Ping '8.8.8.8'\n\tlist Ping '8.8.4.4'\n\n")
end
of:write("config LoadPlugin 'nameservice'\n\toption library 'olsrd_nameservice.so.0.4'\n\toption interval '30'\n\toption timeout '300'\n\toption sighup_pid_file '/var/run/dnsmasq/dnsmasq.pid'\n\toption name_change_script '/usr/local/bin/olsrd-namechange'\n")
aredn.services.reset_validation()
local names, hosts, services = aredn.services.get()
for _, name in ipairs(names)
do
of:write("\tlist name '" .. name .. "'\n")
end
for _, host in ipairs(hosts)
do
if host.host ~= "" then
2023-12-13 23:49:28 -07:00
of:write("\tlist hosts '" .. host.ip .. " " .. host.host .. "'\n")
end
end
for _, service in ipairs(services)
do
of:write("\tlist service '" .. service .. "'\n")
end
of:write("\n")
-- add all the tunnel interfaces
if vtunclients + vtunservers + wgclients + wgservers > 0 then
of:write("config Interface\n")
2023-12-13 00:57:36 -07:00
for dev = 50, 50 + vtunclients - 1
do
of:write("\tlist interface 'tun" .. dev .. "'\n")
end
for dev = 50 + maxclients, 50 + maxclients + vtunservers - 1
do
of:write("\tlist interface 'tun" .. dev .. "'\n")
end
2024-01-07 17:17:52 -07:00
if wgclients > 0 then
for dev = 0, wgclients - 1
do
of:write("\tlist interface 'wgc" .. dev .. "'\n")
end
end
if wgservers > 0 then
for dev = 0, wgservers - 1
do
of:write("\tlist interface 'wgs" .. dev .. "'\n")
end
end
of:write("\toption Ip4Broadcast '255.255.255.255'\n")
local tun_weight = tonumber(nc:get("aredn", "@tunnel[0]", "weight") or 1)
local is_supernode = nc:get("aredn", "@supernode[0]", "enable") == "1"
if not tun_weight or tun_weight < 1 or is_supernode then
of:write("\toption Mode 'ether'\n")
elseif tun_weight > 1 then
of:write("\toption LinkQualityMult 'default " .. (1 / tun_weight) .. "'\n")
end
end
nc:set("aredn", "@tunnel[0]", "maxclients", maxclients)
nc:set("aredn", "@tunnel[0]", "maxservers", maxservers)
nc:commit("aredn")
-- add xlink interfaces
if nixio.fs.stat("/etc/config.mesh/xlink") then
uci.cursor("/etc/config.mesh"):foreach("xlink", "interface",
function(section)
2023-12-13 23:49:28 -07:00
of:write("\nconfig Interface\n\tlist interface '" .. section[".name"] .. "'\n")
if section.peer then
of:write("\toption Ip4Broadcast '" .. section.peer .. "'\n")
else
of:write("\toption Ip4Broadcast '255.255.255.255'\n")
end
local weight = tonumber(section.weight or 0)
if weight then
if weight > 1 then
of:write("\toption LinkQualityMult 'default " .. (1 / weight) .. "'\n")
elseif weight < 1 then
2023-12-13 23:49:28 -07:00
of:write("\toption Mode 'ether'\n")
end
else
of:write("\toption Mode 'ether'\n")
end
end
)
end
of:close()
end
end
-- Update user firewall
local _, diff = filecopy("/etc/config.mesh/firewall.user", "/etc/firewall.user", true)
if diff then
changes.firewall = true
end
-- Update services script
local sf = io.open("/tmp/local_services", "w")
if sf then
sf:write("#!/bin/sh\n")
if cfg.wifi_proto ~= "disabled" then
local wifi_channel = tonumber(cfg.wifi_channel)
if is_null(cfg.wifi_txpower) or tonumber(cfg.wifi_txpower) > aredn.hardware.wifi_maxpower(cfg.wifi_intf, wifi_channel) then
cfg.wifi_txpower = aredn.hardware.wifi_maxpower(cfg.wifi_intf, wifi_channel)
elseif tonumber(cfg.wifi_txpower) < 1 then
cfg.wifi_txpower = 1
end
if cfg.wifi_enable == "1" then
sf:write("/usr/sbin/iw dev " .. cfg.wifi_intf .. " set txpower fixed " .. cfg.wifi_txpower .. "00\n")
end
if not is_null(cfg.aprs_lat) and not is_null(cfg.aprs_lon) then
nc:set("aredn", "@location[0]", "lat", cfg.aprs_lat)
nc:set("aredn", "@location[0]", "lon", cfg.aprs_lon)
nc:commit("aredn")
end
end
sf:close()
local _, diff = filecopy("/tmp/local_services", "/etc/local/services", true)
if diff then
changes.localservices = true
end
os.remove("/tmp/local_services")
nixio.fs.chmod("/etc/local/services", "777")
end
---
--- Make it official
---
-- Handle special cases
local config_special = {
lqm_enable = c:get("aredn", "@lqm[0]", "enable"),
tunnel_weight = c:get("aredn", "@tunnel[0]", "weight"),
supernode_enable = c:get("aredn", "@supernode[0]", "enable"),
watchdog_enable = c:get("aredn", "@watchdog[0]", "enable"),
watchdog_pings = c:get("aredn", "@watchdog[0]", "ping_addresses"),
watchdog_daily = c:get("aredn", "@watchdog[0]", "daily"),
wifi_mode_0 = c:get("wireless", "@wifi-iface[0]", "mode"),
wifi_mode_1 = c:get("wireless", "@wifi-iface[1]", "mode")
}
local nfiles = {}
for file in nixio.fs.glob("/tmp/new_config/*")
do
nfiles[nixio.fs.basename(file)] = true
end
-- Remove files we no longer need
for file in nixio.fs.glob("/etc/config/*")
do
if not nfiles[nixio.fs.basename(file)] then
nixio.fs.remove(file)
changes.reboot = true
end
end
for file, _ in pairs(nfiles)
do
local ffile = "/tmp/new_config/" .. file
local _, diff = filecopy(ffile, "/etc/config/" .. file, true)
if diff then
if file == "system" then
2024-01-11 21:51:25 -07:00
changes.log = true
changes.system = true
elseif file == "aredn" then
local oc = uci:cursor()
if oc:get("aredn", "@lqm[0]", "enable") ~= config_special.lqm_enable then
changes.manager = true
end
if oc:get("aredn", "@tunnel[0]", "weight") ~= config_special.tunnel_weight then
changes.olsrd = true
end
if oc:get("aredn", "@supernode[0]", "enable") ~= config_special.supernode_enable then
changes.reboot = true
end
if oc:get("aredn", "@watchdog[0]", "enable") ~= config_special.watchdog_enable then
changes.reboot = true
end
if oc:get("aredn", "@watchdog[0]", "ping_addresses") ~= config_special.watchdog_pings then
changes.manager = true
end
if oc:get("aredn", "@watchdog[0]", "daily") ~= config_special.watchdog_daily then
changes.manager = true
end
elseif file == "network" then
changes.network = true
changes.tunnels = true -- restarting network devices requires tunnels to restart
elseif file == "dhcp" then
changes.dnsmasq = true
elseif file == "olsrd" then
changes.olsrd = true
elseif file == "firewall" then
changes.firewall = true
elseif file == "wireless" then
local oc = uci:cursor()
if oc:get("wireless", "@wifi-iface[0]", "mode") ~= config_special.wifi_mode_0 or oc:get("wireless", "@wifi-iface[1]", "mode") ~= config_special.wifi_mode_1 then
changes.reboot = true
else
changes.wireless = true
end
elseif file == "vtun" then
changes.tunnels = true
else
changes.reboot = true
end
end
nixio.fs.remove(ffile)
end
nixio.fs.rmdir("/tmp/new_config")
aredn.info.set_nvram("config", "mesh")
aredn.info.set_nvram("node", node)
aredn.info.set_nvram("tactical", tactical)
-- Set file flags for whichever parts of the system require a restart/reboot
for k, v in pairs(changes)
do
if v then
nixio.fs.mkdir("/tmp/reboot-required")
io.open("/tmp/reboot-required/" .. k, "w"):close()
end
end
return 0