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

897 lines
32 KiB
Lua
Executable File

#! /usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2021 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")
local aredn_info = require('aredn.info')
require("aredn.hardware")
require("iwinfo")
-- helpers start
function is_null(v)
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()
-- validate args
local auto = false
local do_basic = true
local config = nil
for i, a in ipairs(arg)
do
if a == "-a" then
auto = true
elseif a == "-p" then
do_basic = false
elseif a[1] == '-' then
break
else
config = a
break
end
end
if not config then
print "usage: node-setup [-a] [-p] <configname>"
print "-a: automatic mode - don't ask any questions"
print "-p: only process port forwarding and dhcp settings"
return -1
end
if not (config == "mesh" and nixio.fs.access("/etc/config.mesh/_setup", "r")) then
print (string.format("'%s' is not a valid configuration", config))
return -1
end
local ieee80211 = "/sys/class/ieee80211/"
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 deleteme = {}
local cfg = {
lan_intf = lanintf,
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"
}
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))
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
if not auto then
-- Is this used now?
print "Non-auto mode no longer supported."
return -1
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 = (uci.cursor("/etc/config.mesh"):get("aredn", "@supernode[0]", "enable") == "1")
if is_supernode then
cfg.olsrd_dtd_interface_mode = "isolated"
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
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
-- 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
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"
local aliasfile = "/etc/config.mesh/aliases"
local servfile = "/etc/config.mesh/_setup.services"
if is_null(cfg.dmz_mode) then
portfile = portfile .. ".nat"
dhcpfile = dhcpfile .. ".nat"
aliasfile = aliasfile .. ".nat"
servfile = servfile .. ".nat"
else
portfile = portfile .. ".dmz"
dhcpfile = dhcpfile .. ".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
-- basic configuration
if do_basic then
-- 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"))
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"
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"))
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
for _, port in ipairs(ports)
do
config = config .. " list ports '" .. port .. "'\n"
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
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
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 not (bfile:match("^_setup") or bfile:match("^firewall.user") or bfile:match("^olsrd")) then
local f = io.open("/tmp/new_config/" .. bfile, "w")
if f then
f:write(expand_vars(read_all(file)))
f:close()
end
end
end
-- make it official
for file in nixio.fs.glob("/etc/config/*")
do
nixio.fs.remove(file)
end
for file in nixio.fs.glob("/tmp/new_config/*")
do
filecopy(file, "/etc/config/" .. nixio.fs.basename(file))
nixio.fs.remove(file)
end
nixio.fs.rmdir("/etc/new_config")
filecopy("/etc/config.mesh/firewall.user", "/etc/firewall.user")
aredn_info.set_nvram("config", "mesh")
aredn_info.set_nvram("node", node)
aredn_info.set_nvram("tactical", tactical)
end
-- generate the system 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
if not do_basic then
filecopy("/etc/config.mesh/firewall", "/etc/config/firewall")
filecopy("/etc/config.mesh/firewall.user", "/etc/firewall.user")
end
-- append to firewall
local add_masq = false
local fw = io.open("/etc/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 c: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
c:set("firewall", "@zone[2]", "masq", "0")
c:commit("firewall")
end
-- generate the services file
local sf = io.open("/etc/config/services", "w")
if sf then
if nixio.fs.access(servfile) then
for line in io.lines(servfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local name, link, proto, host, port, sffx = line:match("(.*)|(.*)|(.*)|(.*)|(.*)|(.*)")
if name and name ~= "" and host ~= "" then
if proto == "" then
proto = "http"
end
if link == "0" then
port = "0"
end
sf:write(string.format("%s://%s:%s/%s|tcp|%s\n", proto, host, port, sffx, name))
end
end
end
end
sf:close()
end
local sf = io.open("/etc/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
c:set("aredn", "@location[0]", "lat", cfg.aprs_lat)
c:set("aredn", "@location[0]", "lon", cfg.aprs_lon)
c:commit("aredn")
end
end
sf:close()
nixio.fs.chmod("/etc/local/services", "777")
end
-- generate olsrd.conf
if nixio.fs.access("/etc/config.mesh/olsrd", "r") then
local of = io.open("/etc/config/olsrd", "w")
if of then
if nixio.fs.access("/etc/config.mesh/olsrd") 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
local cwan = aredn.hardware.get_iface_name("wan"):match("^([^%.%s]+)")
local cdtd = aredn.hardware.get_iface_name("dtdlink"):match("^([^%.%s]+)")
if cwan ~= cdtd then
of:write(string.format("config Hna4\n\toption netaddr %s\n\toption netmask 255.255.255.255\n\n", cfg.wifi_ip))
end
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 c: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\n")
end
end
of:close()
end
end
-- indicate whether lan is running in dmz mode
c:set("aredn", "@dmz[0]", "mode", cfg.dmz_mode)
c:commit("aredn")
-- setup node lan dhcp
if c:get("aredn", "@wan[0]", "lan_dhcp_route") == "1" or c:get("aredn", "@wan[0]", "lan_dhcp_defaultroute") == "1" then
-- Provide stateless routes and default route
c:set("dhcp", "@dhcp[0]", "dhcp_option", {
"121,10.0.0.0/8," .. cfg.lan_ip .. ",0.0.0.0/0," .. cfg.lan_ip,
"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
-- surpress default route being sent
c:set("dhcp", "@dhcp[0]", "dhcp_option", {
"121,10.0.0.0/8," .. cfg.lan_ip,
"249,10.0.0.0/8," .. cfg.lan_ip,
"3"
})
end
c:commit("dhcp")
-- generate the wireless config file
local config = ""
local ifacenum = 0
local ifacecount = 0
local devpaths = {}
if nixio.fs.stat(ieee80211) then
for devname in nixio.fs.dir(ieee80211)
do
ifacecount = ifacecount + 1
end
for devname in nixio.fs.dir(ieee80211)
do
local dev = devname:match("^phy(%d+)$")
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
enable = "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 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
ifacenum = ifacenum + 1
end
end
write_all("/etc/config/wireless", config)
if not auto then
print "configuration complete.";
print "you should now reboot the router.";
end
return 0