2022-02-22 18:25:01 -07:00
#! /usr/bin/lua
--[[
2024-05-29 01:45:25 -06:00
Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks
2023-12-12 21:01:23 -07:00
Copyright (C) 2021-2023 Tim Wilkinson
2023-01-15 00:07:22 -07:00
Orignal Perl Copyright (C) 2015 Conrad Lara
See Contributors file for additional contributors
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
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.
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
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.
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
Additional Terms:
2022-02-22 18:25:01 -07:00
2024-05-29 01:45:25 -06:00
Additional use restrictions exist on the AREDN® trademark and logo.
2023-01-15 00:07:22 -07:00
See AREDNLicense.txt for more info.
2022-02-22 18:25:01 -07:00
2024-05-29 01:45:25 -06:00
Attributions to the AREDN® Project must be retained in the source code.
2023-01-15 00:07:22 -07:00
If importing this code into a new or existing project attribution
2024-05-29 01:45:25 -06:00
to the AREDN® project must be added to the source code.
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
You must not misrepresent the origin of the material contained within.
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
Modified versions must be modified to attribute to the original source
and be marked in reasonable ways as differentiate it from the original
version
2022-02-22 18:25:01 -07:00
--]]
require("nixio")
require("aredn.utils")
2023-12-12 21:01:23 -07:00
require('aredn.info')
2022-02-22 18:25:01 -07:00
require("aredn.hardware")
2023-01-15 00:07:22 -07:00
require("iwinfo")
2023-12-12 21:01:23 -07:00
require("aredn.services")
2022-02-22 18:25:01 -07:00
-- 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
2022-02-22 18:25:01 -07:00
return true
else
return false
end
end
2024-06-17 16:24:57 -06:00
function is_notnull(v)
return not is_null(v)
end
2022-02-22 18:25:01 -07:00
2023-01-15 00:07:22 -07:00
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
2024-05-14 10:46:25 -06:00
local function tablesize(t)
local len = 0
for _ in pairs(t)
do
len = len + 1
end
return len
end
local function get_subtable(container, key)
local subtable = container[key]
if not subtable then
subtable = {}
container[key] = subtable
end
return subtable
end
2022-02-22 18:25:01 -07:00
-- helpers end
2024-05-14 10:46:25 -06:00
local FORCED = "force"
local UNFORCED = "onrequest"
2023-06-21 22:07:21 -06:00
local c = uci.cursor()
2023-12-06 12:39:23 -07:00
local cm = uci.cursor("/etc/config.mesh")
2023-06-21 22:07:21 -06:00
2023-01-15 00:07:22 -07:00
local ieee80211 = "/sys/class/ieee80211/"
2022-12-22 13:22:49 -07:00
local lanintf = aredn.hardware.get_board_network_ifname("lan")
2023-12-12 21:01:23 -07:00
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")
2022-02-22 18:25:01 -07:00
2023-12-12 21:01:23 -07:00
local wifi_mon_enable = false
2022-02-22 18:25:01 -07:00
local deleteme = {}
local cfg = {
2024-10-27 15:59:38 -06:00
description_node = "",
2022-02-22 18:25:01 -07:00
lan_intf = lanintf,
2022-12-22 13:22:49 -07:00
wan_intf = aredn.hardware.get_board_network_ifname("wan"),
2023-01-15 00:07:22 -07:00
bridge_network_config = "",
lan_network_config = "",
wan_network_config = "",
dtdlink_network_config = "",
2023-09-19 21:06:09 -06:00
wifi_network_config = "",
2023-12-06 12:39:23 -07:00
olsrd_dtd_interface_mode = "ether",
tun_network_config = "",
2023-12-12 21:01:23 -07:00
wireguard_network_config = "",
2024-08-15 21:28:45 -06:00
dtdlink_interfaces = "\tlist network 'dtdlink'",
2024-05-26 17:41:18 -06:00
vpn_interfaces = "",
2023-12-12 21:01:23 -07:00
olsrd_pollrate = "0.05",
2024-03-27 18:01:00 -06:00
tun_devices_config = "",
hello_interval = "4.0",
tc_interval = "10.0",
mid_interval = "10.0",
2024-09-03 16:53:33 -06:00
hna_interval = "10.0",
ntp_enabled = "0"
2023-12-12 21:01:23 -07:00
}
-- 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,
2024-03-25 00:10:42 -06:00
wireless = false,
2024-08-15 21:28:45 -06:00
localservices = false,
2024-08-25 17:35:02 -06:00
wpad = false,
poe = false,
pou = false
2013-11-14 23:11:16 -07:00
}
2024-01-30 14:25:37 -07:00
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
2024-08-15 21:28:45 -06:00
function is_nat_mode()
return is_null(cfg.dmz_mode)
end
function is_dmz_mode()
return is_notnull(cfg.dmz_mode) and cfg.dmz_mode ~= "1"
end
function is_altnet_mode()
return cfg.dmz_mode == "1"
end
2023-01-15 22:50:39 -07:00
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))
2024-01-30 14:25:37 -07:00
if not valid_config(line) then
print("Invalid config fragment: " .. inc)
os.exit(1)
end
2023-01-15 22:50:39 -07:00
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)
2023-02-07 20:57:20 -07:00
elseif cfg[parm] then
2023-01-15 22:50:39 -07:00
line = line:gsub("<" .. parm .. ">", cfg[parm])
2023-02-07 20:57:20 -07:00
else
line = nil
2023-01-15 22:50:39 -07:00
end
end
end
if line then
nlines[#nlines + 1] = line
end
end
return table.concat(nlines, "")
end
2024-10-24 22:00:16 -06:00
-- load the configuration
local cms = cm:get_all("setup", "globals")
for k, v in pairs(cms)
2022-02-22 18:25:01 -07:00
do
2024-10-24 22:00:16 -06:00
if not k:match("^%.") then
2022-02-22 18:25:01 -07:00
cfg[k] = v
end
end
if cfg.wifi_enable == "1" then
2023-05-25 22:27:59 -06:00
if not cfg.wifi_intf or cfg.wifi_intf == "" then
cfg.wifi_intf = aredn.hardware.get_board_network_ifname("wifi"):match("^(%S+)")
end
2023-06-22 18:17:43 -06:00
local mtu = c:get("aredn", "@lqm[0]", "mtu")
mtu = tonumber(mtu)
2023-06-21 22:07:21 -06:00
if mtu and mtu >= 256 and mtu <= 1500 then
cfg.wifi_mtu = mtu
end
2018-12-12 14:16:07 -07:00
else
2023-01-15 00:07:22 -07:00
cfg.wifi_intf = "br-nomesh"
2022-02-22 18:25:01 -07:00
end
2023-09-19 21:06:09 -06:00
-- Supernode options
2023-12-06 12:39:23 -07:00
local is_supernode = (cm:get("aredn", "@supernode[0]", "enable") == "1")
2023-09-19 21:06:09 -06:00
if is_supernode then
cfg.olsrd_dtd_interface_mode = "isolated"
2023-12-06 13:14:17 -07:00
cfg.olsrd_pollrate = "0.01"
2023-09-19 21:06:09 -06:00
end
2022-02-22 18:25:01 -07:00
-- delete some config lines if necessary
2024-09-18 20:31:05 -06:00
if cfg.wan_proto ~= "static" then
2022-02-22 18:25:01 -07:00
deleteme.wan_ip = true
deleteme.wan_gw = true
deleteme.wan_mask = true
end
2024-08-15 21:28:45 -06:00
if is_dmz_mode() or is_altnet_mode() or cfg.wan_proto ~= "disabled" then
2022-02-22 18:25:01 -07:00
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
2024-10-25 21:45:54 -06:00
-- sensible dmz_mode default
if is_null(cfg.dmz_mode) then
cfg.dmz_mode = "0"
end
-- switch to dmz values if needed
if is_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
end
cfg.dhcp_limit = cfg.dhcp_end - cfg.dhcp_start + 1
2022-02-22 18:25:01 -07:00
-- 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
2023-12-12 21:01:23 -07:00
if aredn.info.get_nvram(parm:lower()) == "" then
2024-10-27 15:59:38 -06:00
print ("WARNING: nv parameter '" .. parm .. "' in file '" .. file .. "' does not exist")
2022-02-22 18:25:01 -07:00
end
else
if not cfg[parm] and not deleteme[parm] then
2024-10-27 15:59:38 -06:00
print ("WARNING: parameter '" .. parm .. "' in file '" .. file .. "' does not exist")
2022-02-22 18:25:01 -07:00
end
end
end
end
end
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"
2022-02-22 18:25:01 -07:00
local aliasfile = "/etc/config.mesh/aliases"
local servfile = "/etc/config.mesh/_setup.services"
2024-08-15 21:28:45 -06:00
if is_nat_mode() then
2022-02-22 18:25:01 -07:00
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"
2022-02-22 18:25:01 -07:00
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"
2022-02-22 18:25:01 -07:00
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
2022-03-17 13:26:52 -06:00
io.open("/etc/config.mesh/aliases.dmz", "a"):close()
2022-02-22 18:25:01 -07:00
end
nixio.fs.symlink("aliases.dmz", "/etc/config.mesh/aliases")
end
2023-12-12 21:01:23 -07:00
-- 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"))
2024-01-30 14:25:37 -07:00
if not valid_config(cfg.bridge_network_config) then
print("Invalid config fragment: /etc/aredn_include/bridge.network.user")
os.exit(1)
end
2023-12-12 21:01:23 -07:00
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)
2023-01-15 00:07:22 -07:00
do
2023-12-12 21:01:23 -07:00
list[port:gsub("%..*$", "")] = true
2023-01-15 00:07:22 -07:00
end
end
2023-12-12 21:01:23 -07:00
local config = "config device\n option name 'br0'\n option type 'bridge'\n option vlan_filtering '1'\n"
for port, _ in pairs(list)
2023-01-15 00:07:22 -07:00
do
2023-12-12 21:01:23 -07:00
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"))
2024-01-30 14:25:37 -07:00
if not valid_config(config) then
print("Invalid config fragment: /etc/aredn_include/" .. net .. ".network.user")
os.exit(1)
end
2023-12-12 21:01:23 -07:00
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)
2023-02-07 20:57:20 -07:00
do
2023-12-12 21:01:23 -07:00
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
2023-02-07 20:57:20 -07:00
end
end
2023-12-12 21:01:23 -07:00
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"
2023-01-15 00:07:22 -07:00
else
2023-12-12 21:01:23 -07:00
vlan = "4:u"
2023-01-15 00:07:22 -07:00
end
2023-12-12 21:01:23 -07:00
-- handle wan vlan override
2024-10-27 15:59:38 -06:00
local wport, wvlan = (cm:get("setup", "globals", "wan_intf") or ""):match("(%w+%.)(%d+)")
2024-10-24 22:00:16 -06:00
if wvlan then
vlan = wvlan .. ":t"
ports = { wport .. wvlan }
2023-01-15 00:07:22 -07:00
end
end
2023-12-12 21:01:23 -07:00
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
2023-01-15 00:07:22 -07:00
2023-12-12 21:01:23 -07:00
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"
2023-01-15 00:07:22 -07:00
end
2023-12-12 21:01:23 -07:00
config = config .. "\n"
ports = { "br0." .. v }
end
2023-01-15 00:07:22 -07:00
2023-12-12 21:01:23 -07:00
local proto = cfg[net .. "_proto"] or ""
2024-09-17 19:40:48 -06:00
local ipaddr = deleteme[net .. "_ip"] and "" or cfg[net .. "_ip"] or ""
local netmask = deleteme[net .. "_mask"] and "" or cfg[net .. "_mask"] or ""
2023-12-12 21:01:23 -07:00
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
2024-09-17 19:40:48 -06:00
local gateway = deleteme[net .. "_gw"] and "" or cfg[net .. "_gw"] or ""
2023-01-15 00:07:22 -07:00
2023-12-12 21:01:23 -07:00
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
2023-01-15 00:07:22 -07:00
2023-12-12 21:01:23 -07:00
if not wireless then
if #ports == 0 then
config = config .. " option bridge_empty '1'\n"
2023-01-15 00:07:22 -07:00
else
2023-12-12 21:01:23 -07:00
for _, port in ipairs(ports)
do
config = config .. " list ports '" .. port .. "'\n"
2023-01-15 00:07:22 -07:00
end
end
2023-12-12 21:01:23 -07:00
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"
2023-01-15 00:07:22 -07:00
end
2022-12-22 13:22:49 -07:00
end
2023-12-12 21:01:23 -07:00
config = config .. "\nconfig interface " .. net .. "\n"
if wireless then
config = config .. " option device '" .. ports[1] .. "'\n"
else
config = config .. " option device 'br-" .. net .. "'\n"
2023-12-06 12:39:23 -07:00
end
2023-12-12 21:01:23 -07:00
if proto ~= "" then
config = config .. " option proto '" .. proto .. "'\n"
2023-12-06 12:39:23 -07:00
end
2023-12-12 21:01:23 -07:00
if mtu ~= "" then
config = config .. " option mtu '" .. mtu .. "'\n"
2023-12-06 12:39:23 -07:00
end
2023-12-12 21:01:23 -07:00
if ipaddr ~= "" then
config = config .. " option ipaddr '" .. ipaddr .. "'\n"
2023-12-06 12:39:23 -07:00
end
2023-12-12 21:01:23 -07:00
if netmask ~= "" then
config = config .. " option netmask '" .. netmask .. "'\n"
2023-12-06 12:39:23 -07:00
end
2023-12-12 21:01:23 -07:00
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"
2022-02-22 18:25:01 -07:00
end
end
2023-12-12 21:01:23 -07:00
cfg[net .. "_network_config"] = config
end
2022-02-22 18:25:01 -07:00
2023-12-12 21:01:23 -07:00
-- Generate the tunnel configurations
2024-09-12 00:14:26 -06:00
local is_supernode = cm:get("aredn", "@supernode[0]", "enable") == "1"
2023-12-12 21:01:23 -07:00
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
2024-09-12 00:14:26 -06:00
if is_supernode and tun_start:match("^172%.31%.") then
tun_start = "172.30." .. tun_start:sub(8, #tun_start)
cm:set("vtun", "@network[0]", "start", tun_start)
cm:commit("vtun")
end
2023-12-12 21:01:23 -07:00
cfg.tun_network_config = cfg.tun_network_config .. "\toption start '" .. tun_start .. "'\n"
2022-02-22 18:25:01 -07:00
end
2023-12-12 21:01:23 -07:00
if tun_dns then
cfg.tun_network_config = cfg.tun_network_config .. "\toption dns '" .. tun_dns .. "'\n"
2022-02-22 18:25:01 -07:00
end
2023-12-12 21:01:23 -07:00
cfg.tun_network_config = cfg.tun_network_config .. "\n"
2022-02-22 18:25:01 -07:00
end
2024-08-15 21:28:45 -06:00
local def_tun_weight = tonumber(cm:get("aredn", "@tunnel[0]", "weight") or 1) or 0
if is_supernode then
def_tun_weight = 0
end
local tun_weights = {}
2023-12-13 00:26:27 -07:00
local vtunclients = 0
2023-12-12 21:01:23 -07:00
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",
2024-01-01 18:36:18 -07:00
s.node:upper(), s.passwd, s.clientip, s.serverip, s.netip)
2024-08-15 21:28:45 -06:00
local w = s.weight or def_tun_weight
if not tun_weights[w] then
tun_weights[w] = {}
end
table.insert(tun_weights[w], string.format("tun%d", 50 + vtunclients))
2023-12-13 00:26:27 -07:00
vtunclients = vtunclients + 1
2023-12-12 21:01:23 -07:00
end
2022-02-22 18:25:01 -07:00
end
2023-12-12 21:01:23 -07:00
)
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("^(.+=)(.+=)(.+=)(.+=)$")
2024-01-10 01:02:54 -07:00
local addr, port = s.clientip:match("^(%d+%.%d+%.%d+%.%d+):(%d+)$")
2023-12-12 21:01:23 -07:00
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",
2024-01-10 01:02:54 -07:00
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)
2024-08-15 21:28:45 -06:00
local w = s.weight or def_tun_weight
if not tun_weights[w] then
tun_weights[w] = {}
end
table.insert(tun_weights[w], string.format("wgc%d", wgclients))
2023-12-12 21:01:23 -07:00
wgclients = wgclients + 1
end
2022-02-22 18:25:01 -07:00
end
2023-12-12 21:01:23 -07:00
)
2023-12-13 00:26:27 -07:00
local vtunservers = 0
2023-12-12 21:01:23 -07:00
local wgservers = 0
2024-08-15 21:28:45 -06:00
local vtunclients_roundup = 10 * math.ceil(vtunclients / 10)
2023-12-12 21:01:23 -07:00
cm:foreach("vtun", "server",
function(s)
if s.enabled == "1" then
2024-01-07 17:17:52 -07:00
if s.netip:match(":") then
2023-12-12 21:01:23 -07:00
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
2023-12-12 21:01:23 -07:00
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",
2024-01-10 01:02:54 -07:00
wgservers, client_priv, (abc .. "." .. d))
2023-12-12 21:01:23 -07:00
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)
2024-08-15 21:28:45 -06:00
local w = s.weight or def_tun_weight
if not tun_weights[w] then
tun_weights[w] = {}
end
table.insert(tun_weights[w], string.format("wgs%d", wgservers))
2023-12-12 21:01:23 -07:00
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",
2024-01-01 18:36:18 -07:00
s.host, s.node:upper(), s.passwd, s.clientip, s.serverip, s.netip)
2024-08-15 21:28:45 -06:00
local w = s.weight or def_tun_weight
if not tun_weights[w] then
tun_weights[w] = {}
end
table.insert(tun_weights[w], string.format("tun%d", 50 + vtunclients_roundup + vtunservers))
2023-12-13 00:26:27 -07:00
vtunservers = vtunservers + 1
2022-02-22 18:25:01 -07:00
end
end
end
2023-12-12 21:01:23 -07:00
)
-- Create the tunnel devices we need
2023-12-13 14:59:54 -07:00
local maxclients = 0
local maxservers = 0
2023-12-12 21:01:23 -07:00
-- No tunnel devices without the vtund app
2023-12-13 14:59:54 -07:00
if nixio.fs.stat("/usr/sbin/vtund") then
maxclients = 10 * math.ceil(vtunclients / 10)
maxservers = 10 * math.ceil(vtunservers / 10)
2023-12-12 21:01:23 -07:00
end
2023-12-13 00:57:36 -07:00
for dev = 50, 50 + maxclients + maxservers - 1
2023-12-12 21:01:23 -07:00
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
2023-12-13 14:59:54 -07:00
wgclients = 0
wgservers = 0
end
2022-02-22 18:25:01 -07:00
2024-05-26 17:41:18 -06:00
-- Put the tunnels into the vpn zone
local vpnzone = false
if maxclients + maxservers + wgclients + wgservers > 0 then
vpnzone = true
for i = 50, 50 + maxclients + maxservers - 1
do
2024-08-15 21:28:45 -06:00
cfg.vpn_interfaces = cfg.vpn_interfaces .. "\tlist network 'tun" .. i .. "'\n"
2024-05-26 17:41:18 -06:00
end
for i = 0, wgclients-1
do
2024-08-15 21:28:45 -06:00
cfg.vpn_interfaces = cfg.vpn_interfaces .. "\tlist network 'wgc" .. i .. "'\n"
2024-05-26 17:41:18 -06:00
end
for i = 0, wgservers-1
do
2024-08-15 21:28:45 -06:00
cfg.vpn_interfaces = cfg.vpn_interfaces .. "\tlist network 'wgs" .. i .. "'\n"
2024-05-26 17:41:18 -06:00
end
end
-- Put xlinks into dtdlink zone
if nixio.fs.stat("/etc/config.mesh/xlink") then
uci.cursor("/etc/config.mesh"):foreach("xlink", "interface",
function(section)
2024-08-15 21:28:45 -06:00
cfg.dtdlink_interfaces = cfg.dtdlink_interfaces .. "\n\tlist network '" .. section[".name"] .. "'"
2024-05-26 17:41:18 -06:00
end
)
end
2024-09-03 16:53:33 -06:00
-- NTP
if cm:get("aredn", "@ntp[0]", "period") == "continually" then
cfg.ntp_enabled = "1"
end
2023-12-12 21:01:23 -07:00
remove_all("/tmp/new_config")
nixio.fs.mkdir("/tmp/new_config")
2022-02-22 18:25:01 -07:00
2023-12-12 21:01:23 -07:00
for file in nixio.fs.glob("/etc/config.mesh/*")
do
local bfile = nixio.fs.basename(file)
2024-10-24 22:00:16 -06:00
if bfile == "setup" or bfile == "vtun" or bfile == "wireguard" or bfile == "xlink" or bfile == "olsrd" or bfile == "firewall.user" or bfile:match("^_setup") or bfile:match("^aliases") then
2023-12-12 21:01:23 -07:00
-- 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()
2022-02-22 18:25:01 -07:00
end
end
end
2023-12-12 21:01:23 -07:00
-- Tunnels
write_all("/tmp/new_config/vtun", expand_vars("<tun_network_config>"))
local nc = uci.cursor("/tmp/new_config")
2022-02-22 18:25:01 -07:00
-- append to firewall
2023-12-12 21:01:23 -07:00
local fw = io.open("/tmp/new_config/firewall", "a")
2022-02-22 18:25:01 -07:00
if fw then
2024-08-15 21:28:45 -06:00
if not is_nat_mode() then
2022-02-22 18:25:01 -07:00
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")
2024-05-26 17:41:18 -06:00
if vpnzone then
fw:write("\nconfig forwarding\n option src vpn\n option dest lan\n")
end
2022-02-22 18:25:01 -07:00
end
2023-12-21 12:06:15 -07:00
if nc:get("aredn", "@wan[0]", "olsrd_gw") == "1" then
2022-02-22 18:25:01 -07:00
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")
2024-05-26 17:41:18 -06:00
if vpnzone then
fw:write("\nconfig forwarding\n option src vpn\n option dest wan\n")
end
2022-02-22 18:25:01 -07:00
end
2022-02-26 13:49:12 -07:00
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+)")
2024-08-15 21:28:45 -06:00
if dip and is_dmz_mode() then
2022-02-26 13:49:12 -07:00
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
2024-05-26 17:41:18 -06:00
local match = "option src_dport " .. oport .. "\n"
2022-02-26 13:49:12 -07:00
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
2024-05-26 17:41:18 -06:00
host = "option dest_ip " .. host .. "\n"
2022-05-22 20:05:08 -06:00
if not oport:match("-") then
2022-02-26 13:49:12 -07:00
host = host .. " option dest_port " .. iport .. "\n"
end
2024-08-15 21:28:45 -06:00
if is_dmz_mode() and intf == "both" then
2022-02-26 13:49:12 -07:00
intf = "wan"
end
if intf == "both" then
2024-05-26 17:41:18 -06:00
fw:write("\nconfig redirect\n option src wifi\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("\nconfig redirect\n option src dtdlink\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
if vpnzone then
fw:write("\nconfig redirect\n option src vpn\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
end
fw:write("config redirect\n option src wan\n option dest lan\n " .. match .. " " .. host .. "\n")
2024-08-15 21:28:45 -06:00
elseif intf == "wifi" and is_nat_mode() then
2024-05-26 17:41:18 -06:00
fw:write("\nconfig redirect\n option src dtdlink\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("\nconfig redirect\n option src wifi\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
if vpnzone then
fw:write("\nconfig redirect\n option src vpn\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
end
2022-02-26 13:49:12 -07:00
elseif intf == "wan" then
2024-05-26 17:41:18 -06:00
fw:write("\nconfig redirect\n option src dtdlink\n option dest lan\n " .. match .. " option src_dip " .. cfg.wifi_ip .. "\n " .. host .. "\n")
fw:write("config redirect\n option src wan\n option dest lan\n " .. match .. " " .. host .. "\n")
2022-02-26 13:49:12 -07:00
end
2022-02-22 18:25:01 -07:00
end
end
end
end
end
fw:close();
end
2024-06-17 16:24:57 -06:00
-- setup nat
2024-08-15 21:28:45 -06:00
if is_nat_mode() then
2024-06-17 16:24:57 -06:00
-- zone[0] = lan, zone[1] = wan, zone[2] = wifi, zone[3] = dtdlink, zone[4] = vpn
local masq_src = cfg.lan_ip .. "/" .. netmask_to_cidr(cfg.lan_mask)
for z = 2, 4
do
nc:set("firewall", "@zone[" .. z .. "]", "masq", "1")
nc:set("firewall", "@zone[" .. z .. "]", "masq_src", masq_src)
end
2023-12-12 21:01:23 -07:00
nc:commit("firewall")
2022-02-22 18:25:01 -07:00
end
-- setup node lan dhcp
2024-05-14 10:46:25 -06:00
local function load_dhcp_tags(dhcptagsfile)
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 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
2024-05-14 10:46:25 -06:00
table.insert(get_subtable(dhcp_tags, condition),
{name = name, pattern = pattern})
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
end
end
end
return dhcp_tags
end
2024-05-14 10:46:25 -06:00
local function load_dhcp_options(dhcpoptionsfile)
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 dhcp_options = {}
2024-05-14 10:46:25 -06:00
if nixio.fs.access(dhcpoptionsfile) then
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
local by_tag = get_subtable(dhcp_options, tag)
if tag == "" and force == FORCED then
force = UNFORCED -- force is unsupported for untagged options
end
table.insert(get_subtable(by_tag, force),
{num = opt_num, val = opt_val})
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
end
end
end
return dhcp_options
end
2024-05-14 10:46:25 -06:00
local function option_item(tag, option)
local parts = {}
if tag ~= "" then
table.insert(parts, "tag:" .. tag)
end
table.insert(parts, option.num)
table.insert(parts, option.val)
return table.concat(parts, ",")
end
local function create_classifying_section(condition, cond_list)
for i, props in ipairs(cond_list)
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
2024-05-14 10:46:25 -06:00
local secname = condition
local pat = props.pattern
if (condition == "subscriberid") then
secname = "subscrid"
pat = '"' .. pat:gsub('"', '\\"') .. '"'
print(props.pattern, "->", pat)
end
nc:add("dhcp", secname)
local section_ref = string.format("@%s[%d]", secname, i-1)
nc:set("dhcp", section_ref, "networkid", props.name)
nc:set("dhcp", section_ref, condition, pat)
end
end
local function create_tag_section(tag, force, optlist)
if tag ~= "" then
nc:set("dhcp", tag, "tag")
if force == FORCED then
nc:set("dhcp", tag, "force", 1)
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
end
2024-05-14 10:46:25 -06:00
local options = {}
for _, option in ipairs(optlist) do
table.insert(options, option_item("", option)) -- tag is on section
end
nc:set("dhcp", tag, "dhcp_option", options)
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
end
2022-02-22 18:25:01 -07:00
end
2024-05-14 10:46:25 -06:00
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
2024-05-14 10:46:25 -06:00
local advanced_options = load_dhcp_options(dhcpoptionsfile)
if nixio.fs.access(dhcptagsfile) then
for condition, cond_list in pairs(load_dhcp_tags(dhcptagsfile))
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
2024-05-14 10:46:25 -06:00
create_classifying_section(condition, cond_list)
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
end
2024-05-14 10:46:25 -06:00
end
for tag, forcelist in pairs(advanced_options)
do
if forcelist then
if tag == "" -- tag-section name cannot be empty
or tablesize(forcelist) > 1 -- section name must be unique
then -- place unforced options in the anonymous section
for _, option in ipairs(forcelist[UNFORCED]) do
table.insert(dhcp_option_list, option_item(tag, option))
end
forcelist[UNFORCED] = nil
end
for force, optlist in pairs(forcelist)
do
create_tag_section(tag, force, optlist)
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
end
end
2024-05-14 10:46:25 -06:00
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
if #dhcp_option_list > 0 then
nc:set("dhcp", "@dhcp[0]", "dhcp_option", dhcp_option_list)
end
end
2023-12-12 21:01:23 -07:00
nc:commit("dhcp")
2022-02-22 18:25:01 -07:00
-- generate the wireless config file
2023-01-15 00:07:22 -07:00
local config = ""
2024-01-22 21:22:27 -07:00
local ifacecount = aredn.hardware.get_radio_count()
2023-12-06 11:12:11 -07:00
local devpaths = {}
2024-01-22 21:22:27 -07:00
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/(.*)")
2023-01-15 00:07:22 -07:00
end
2024-01-22 21:22:27 -07:00
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"
2024-10-14 16:05:53 -06:00
if nixio.fs.stat("/sys/kernel/debug/ieee80211/" .. devname .. "/ath10k") then
htmode = "VHT20"
if wlan == cfg.wifi_intf then
local bw = tonumber(cfg.wifi_chanbw)
if bw == 40 then
htmode = "VHT40"
elseif bw == 80 then
htmode = "VHT80"
elseif bw == 160 then
htmode = "VHT160"
end
end
end
2024-01-22 21:22:27 -07:00
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)
2023-01-15 00:07:22 -07:00
else
2024-01-22 21:22:27 -07:00
encryption = "none"
2023-04-28 12:01:58 -06:00
end
2024-01-22 21:22:27 -07:00
network = "wan"
htmode = nil
else
disabled = "1"
end
2023-01-15 00:07:22 -07:00
2024-01-22 21:22:27 -07:00
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
2024-10-14 16:05:53 -06:00
if hwmode == "11g" then
config = config .. " option band '2g'\n"
else
config = config .. " option band '5g'\n"
end
2024-01-22 21:22:27 -07:00
if htmode then
config = config .. " option htmode '" .. htmode .. "'\n"
end
config = config .. " option path '" .. devpath .. "'\n\n"
2023-04-28 12:01:58 -06:00
2024-01-22 21:22:27 -07:00
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"
2023-01-15 00:07:22 -07:00
2024-01-22 21:22:27 -07:00
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"
2023-04-28 12:01:58 -06:00
end
2023-01-15 00:07:22 -07:00
end
2023-12-12 21:01:23 -07:00
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")
2024-06-17 16:24:57 -06:00
if is_notnull(cfg.wifi_ip) then
2023-12-12 21:01:23 -07:00
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
2024-06-17 16:24:57 -06:00
if is_notnull(cfg.dtdlink_ip) then
2023-12-12 21:01:23 -07:00
h:write(cfg.dtdlink_ip .. "\tdtdlink." .. node .. ".local.mesh dtdlink." .. node .."\n")
end
2024-08-15 21:28:45 -06:00
if is_nat_mode() then
2023-12-12 21:01:23 -07:00
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")
2022-02-22 18:25:01 -07:00
2023-12-12 21:01:23 -07:00
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
2024-08-15 21:28:45 -06:00
if is_dmz_mode() then
2023-12-12 21:01:23 -07:00
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
2024-08-15 21:28:45 -06:00
if is_altnet_mode() then
local a, b, c, d = cfg.lan_ip:match("(.*)%.(.*)%.(.*)%.(.*)")
2024-10-26 22:37:35 -06:00
local m, n, o, p = cfg.lan_mask:match("(.*)%.(.*)%.(.*)%.(.*)")
of:write(string.format("\nconfig Hna4\n\toption netaddr %s.%s.%d.%d\n\toption netmask %s\n\n", a, b, nixio.bit.band(c, o), nixio.bit.band(d, p), cfg.lan_mask))
2024-08-15 21:28:45 -06:00
end
2023-12-12 21:01:23 -07:00
2024-06-17 16:24:57 -06:00
if cfg.wifi_enable ~= "1" and is_notnull(cfg.wifi_ip) then
2023-12-12 21:01:23 -07:00
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")
2024-10-25 21:45:54 -06:00
local is_44net = nc:get("aredn", "@supernode[0]", "44net")
if is_44net == "1" then
of:write("config Hna4\n\toption netaddr 44.0.0.0\n\toption netmask 255.128.0.0\n\n")
of:write("config Hna4\n\toption netaddr 44.128.0.0\n\toption netmask 255.192.0.0\n\n")
2024-08-15 21:28:45 -06:00
end
2023-12-12 21:01:23 -07:00
end
2024-03-04 22:08:27 -07:00
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
2023-12-12 21:01:23 -07:00
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")
2023-12-12 21:01:23 -07:00
end
end
for _, service in ipairs(services)
do
of:write("\tlist service '" .. service .. "'\n")
end
of:write("\n")
-- add all the tunnel interfaces
2023-12-13 00:26:27 -07:00
if vtunclients + vtunservers + wgclients + wgservers > 0 then
2024-08-15 21:28:45 -06:00
for weight, ifaces in pairs(tun_weights)
2023-12-13 00:26:27 -07:00
do
2024-08-15 21:28:45 -06:00
of:write("\nconfig Interface\n")
for _, iface in ipairs(ifaces)
2024-01-07 17:17:52 -07:00
do
2024-08-15 21:28:45 -06:00
of:write("\tlist interface '" .. iface .. "'\n")
2024-01-07 17:17:52 -07:00
end
2024-08-15 21:28:45 -06:00
of:write("\toption Ip4Broadcast '255.255.255.255'\n")
weight = tonumber(weight)
if weight < 1 then
of:write("\toption Mode 'ether'\n")
elseif weight > 1 then
of:write("\toption LinkQualityMult 'default " .. (1 / weight) .. "'\n")
2023-12-13 00:26:27 -07:00
end
2024-08-15 21:28:45 -06:00
of:write("\toption HelloInterval '" .. cfg.hello_interval .. "'\n")
of:write("\toption TcInterval '" .. cfg.tc_interval .. "'\n")
of:write("\toption MidInterval '" .. cfg.mid_interval .. "'\n")
of:write("\toption HnaInterval '" .. cfg.hna_interval .. "'\n")
2023-12-13 00:26:27 -07:00
end
2023-12-12 21:01:23 -07:00
end
2023-12-13 14:59:54 -07:00
nc:set("aredn", "@tunnel[0]", "maxclients", maxclients)
nc:set("aredn", "@tunnel[0]", "maxservers", maxservers)
2023-12-16 18:55:18 -07:00
nc:commit("aredn")
2023-12-12 21:01:23 -07:00
-- 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")
2023-12-12 21:01:23 -07:00
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")
2023-12-12 21:01:23 -07:00
end
else
of:write("\toption Mode 'ether'\n")
end
2024-03-27 18:01:00 -06:00
of:write("\toption HelloInterval '" .. cfg.hello_interval .. "'\n")
of:write("\toption TcInterval '" .. cfg.tc_interval .. "'\n")
of:write("\toption MidInterval '" .. cfg.mid_interval .. "'\n")
of:write("\toption HnaInterval '" .. cfg.hna_interval .. "'\n")
2023-12-12 21:01:23 -07:00
end
)
end
2024-08-15 21:28:45 -06:00
-- OLSRD user extras
if nixio.fs.stat("/etc/aredn_include/olsrd.user") then
of:write("\n")
of:write(expand_vars(read_all("/etc/aredn_include/olsrd.user")))
end
2023-12-12 21:01:23 -07:00
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
2024-06-17 16:24:57 -06:00
if is_notnull(cfg.aprs_lat) and is_notnull(cfg.aprs_lon) then
2023-12-12 21:01:23 -07:00
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
2024-03-25 00:10:42 -06:00
changes.localservices = true
2023-12-12 21:01:23 -07:00
end
os.remove("/tmp/local_services")
nixio.fs.chmod("/etc/local/services", "777")
end
---
--- Make it official
---
2023-12-17 22:14:38 -07:00
-- Handle special cases
local config_special = {
2024-10-27 22:29:29 -06:00
dmz_mode = c:get("setup", "globals", "dmz_mode"),
2023-12-12 21:01:23 -07:00
lqm_enable = c:get("aredn", "@lqm[0]", "enable"),
tunnel_weight = c:get("aredn", "@tunnel[0]", "weight"),
2023-12-17 22:14:38 -07:00
supernode_enable = c:get("aredn", "@supernode[0]", "enable"),
2023-12-19 00:07:52 -07:00
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"),
2024-04-28 12:01:47 -06:00
web_access = c:get("aredn", "@wan[0]", "web_access"),
ssh_access = c:get("aredn", "@wan[0]", "ssh_access"),
telnet_access = c:get("aredn", "@wan[0]", "telnet_access"),
2024-10-08 21:58:42 -06:00
lan_dhcp_route = c:get("aredn", "@wan[0]", "lan_dhcp_route"),
2023-12-17 22:14:38 -07:00
wifi_mode_0 = c:get("wireless", "@wifi-iface[0]", "mode"),
2024-08-19 00:21:10 -06:00
wifi_mode_1 = c:get("wireless", "@wifi-iface[1]", "mode"),
wifi_channel_0 = c:get("wireless", "@wifi-device[0]", "channel"),
2024-08-25 17:35:02 -06:00
wifi_channel_1 = c:get("wireless", "@wifi-device[1]", "channel"),
power_eth = c:get("aredn", "@poe[0]", "passthrough"),
2024-09-03 16:53:33 -06:00
power_usb = c:get("aredn", "@usb[0]", "passthrough"),
ntp_period = c:get("aredn", "@ntp[0]", "period")
2023-12-12 21:01:23 -07:00
}
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)
2024-10-08 22:08:01 -06:00
if file == "/etc/config/ubootenv" then
-- Ignore
else
changes.reboot = true
end
2023-12-12 21:01:23 -07:00
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
2023-12-12 21:01:23 -07:00
changes.system = true
2024-09-03 16:53:33 -06:00
changes.ntp = true
2023-12-12 21:01:23 -07:00
elseif file == "aredn" then
local oc = uci:cursor()
2024-10-27 22:29:29 -06:00
if oc:get("setup", "globals", "dmz_mode") ~= config_special.dmz_mode then
2024-08-15 21:28:45 -06:00
changes.reboot = true
end
2023-12-17 22:14:38 -07:00
if oc:get("aredn", "@lqm[0]", "enable") ~= config_special.lqm_enable then
2023-12-12 21:01:23 -07:00
changes.manager = true
end
2023-12-17 22:14:38 -07:00
if oc:get("aredn", "@tunnel[0]", "weight") ~= config_special.tunnel_weight then
2023-12-12 21:01:23 -07:00
changes.olsrd = true
end
2023-12-17 22:14:38 -07:00
if oc:get("aredn", "@supernode[0]", "enable") ~= config_special.supernode_enable then
2023-12-12 21:01:23 -07:00
changes.reboot = true
end
2023-12-19 00:07:52 -07:00
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
2024-04-28 12:01:47 -06:00
if oc:get("aredn", "@wan[0]", "web_access") ~= config_special.web_access or oc:get("aredn", "@wan[0]", "ssh_access") ~= config_special.ssh_access or oc:get("aredn", "@wan[0]", "telnet_access") ~= config_special.telnet_access then
changes.firewall = true
end
2024-08-25 17:35:02 -06:00
if oc:get("aredn", "@poe[0]", "passthrough") ~= config_special.power_eth then
2024-08-25 18:18:03 -06:00
changes.poe = true
2024-08-25 17:35:02 -06:00
end
if oc:get("aredn", "@usb[0]", "passthrough") ~= config_special.power_usb then
2024-08-25 18:18:03 -06:00
changes.pou = true
2024-08-25 17:35:02 -06:00
end
2024-09-03 16:53:33 -06:00
if oc:get("aredn", "@ntp[0]", "period") ~= config_special.ntp_period then
changes.ntp = true
local period = oc:get("aredn", "@ntp[0]", "period")
if period == "continually" then
os.execute("/etc/init.d/sysntp enable > /dev/null 2>&1")
else
os.execute("/etc/init.d/sysntp disable > /dev/null 2>&1")
end
if period == "daily" then
if nixio.fs.stat("/etc/cron.hourly/update-clock") then
nixio.fs.rename("/etc/cron.hourly/update-clock", "/etc/cron.daily/update-clock")
end
else
if nixio.fs.stat("/etc/cron.daily/update-clock") then
nixio.fs.rename("/etc/cron.daily/update-clock", "/etc/cron.hourly/update-clock")
end
end
end
2024-10-08 21:58:42 -06:00
if oc:get("aredn", "@wan[0]", "lan_dhcp_route") ~= config_special.lan_dhcp_route then
changes.firewall = true
end
2023-12-12 21:01:23 -07:00
elseif file == "network" then
changes.network = true
2024-01-10 01:02:54 -07:00
changes.tunnels = true -- restarting network devices requires tunnels to restart
2023-12-12 21:01:23 -07:00
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
2023-12-17 22:14:38 -07:00
local oc = uci:cursor()
2024-08-19 00:21:10 -06:00
if oc:get("wireless", "@wifi-device[0]", "channel") ~= config_special.wifi_channel_0 or oc:get("wireless", "@wifi-device[1]", "channel") ~= config_special.wifi_channel_1 then
changes.manager = true
end
2023-12-17 22:14:38 -07:00
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
2024-08-15 21:28:45 -06:00
-- Only start the hostapd (etc) if we need to. This doesn't change what is currently running
-- only what automatically runs in the future
2024-08-22 14:40:29 -06:00
if oc:get("wireless", "@wifi-iface[0]", "mode") == "ap" or oc:get("wireless", "@wifi-iface[1]", "mode") == "ap" or
oc:get("wireless", "@wifi-iface[0]", "mode") == "sta" or oc:get("wireless", "@wifi-iface[1]", "mode") == "sta" then
2024-08-15 21:28:45 -06:00
os.execute("/etc/init.d/wpad enable > /dev/null 2>&1")
else
os.execute("/etc/init.d/wpad disable > /dev/null 2>&1")
end
2023-12-17 22:14:38 -07:00
changes.reboot = true
else
changes.wireless = true
end
2023-12-12 21:01:23 -07:00
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("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
2022-02-22 18:25:01 -07:00
end
return 0