aredn/files/www/cgi-bin/ports

1335 lines
46 KiB
Plaintext
Raw Normal View History

#!/usr/bin/lua
--[[
Part of AREDN -- Used for creating Amateur Radio Emergency Data Networks
Copyright (C) 2021 Tim Wilkinson
Original 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.hardware")
require("aredn.http")
require("aredn.utils")
aredn.html = require("aredn.html")
require("uci")
aredn.info = require("aredn.info")
local html = aredn.html
local cursor = uci.cursor()
local config = aredn.info.get_nvram("config")
local node = aredn.info.get_nvram("node")
if not node or node == "" then
node = "NOCALL"
end
local tactical = aredn.info.get_nvram("tactical")
if not tactical then
tactical = ""
end
-- post_data
local parms = {}
if os.getenv("REQUEST_METHOD") == "POST" then
require('luci.http')
Update AREDN to OpenWRT 22.3.2 (Major Upgrade) (#574) * Update to Openwrt 21.02 and add support for the CPE710 v1 Update scripts to change references to ifname to device due to a change in Openwrt naming reverse-wpad-basic-wolfssl and disable SSL on Curl NOTE: The compile host must have python3-distutils installed for gpsd to build * aredn: initial working upgrade to openwrt 21.02.1 * aredn: update 1 to working upgrade to openwrt 21.02.1 * aredn: add cpe710v1 to build config * Andrew's patches * Remove duplicates + display perl * Temp disable wifi extension patch * ifname/ports support * Add spectrum patch back in * Generic function to extra interfaces * New api to get wifi ifname * Disables jails * Style link * aredn: partial upgrade to openwrt 22.0.3.0 added AC device images and partial migration to 22.0.3.0 firewall upgrade pending * aredn: update mesh-release and revert config.mk * Unused * NFT firewall rewrite * Common-isze configs * Fix network layout for hap2 * Use local packages dev (new firewall rules) * Add HAP2 * Add pause after network restart to let bridge reinitialize * Various lua fixes for new lua version * Tweak config * Re-fix networking (lost patch change) * Add new radio names * Tolerate missing wifi * Fix hap-lite switch setup * More devices * New radio id * Build Rocket 5AC lite * Remove need for luci.sys * Remove need for luci.sys * Explicitly name wlan interfaces * Handle different compatibility verisoning * Update networking for switches * ipref version bump * Extra flag for curl * Better compat_version fix * Remove wolfssl * Fix dns server * Fix device name * Unused * Remove things we dont need * Remove unused packages * Generic macaddr overrides * Fix uci commit * Fix luci.template.parser to avoid luci.http loading the real thing * Rocket-M build * Add search-domain dhcp option * Turn of ipv6 * No IPV6 in dnsmasq * Override mac addresses if devices all the same * Working from master (for now) * Put back hostap * Disable old ethmac fixup * Tweak configs * Move back to v22.03.2 Leave ipq4019 builds to master * Need IPV6 to compile nft firewall * Rocket-M fixes * Before we start * WIP * Working snapshot * Cleaned patches * Merged patch * Single patch to support HAP2 * Fix typo * Add nanostation-m * 5/10Mhz patch * 5+10MHz patch for ath10k-ct driver * Extend 2Ghz channel check to include -4 to -1 * Add chanbw setup for ath10k (like ath9k) * Added TP-Link CPE710 v1 * Override firmwares * Missing patch * Dropbear config like 3.22.8.0 * Add Ubiquiti Rocket 5AC Lite * Fix c6 * Update * Need more scan channels * Remove IPV6 * Improve mac fixups * Put back missing nft app * IPv6 removed so dont have to disable it * Fix rocket-m flash bug * Fix nanostation-m * Nanobridge is tiny * Fix wifi order for ar750 * Rocket M5 XW support * New rates * Fix firewall4 so we don't need IPv6 * Allow channel width to be restricted * Move channel list into library * Fix naming * Mechanism to block specific channels on specific radios * Refresh buttons * routerboard-sxt-5nd * CPE605 v1.0 * Improve rocket m xw * tpink * Update patch * Update to remove disable * Remove BW restrictions on cpe710 * Restrict to what has been tested * Remove test BW restrictions * sxtsq-5-ac * Update * Update * powerbeam-m5-300 support * Fix * Fix hap2 * Tidy unused patches * Remove limit * Add ubnt_bullet-m-ar7241 * Added ubnt_nanobeam-ac-gen2 * Fix typo * Tolerate missing dtd ip * Explicitly gix hap2 mac addresses * Fix some broken patches * Hap2 wont work at 5MHz * Ubiquiti LiteBeam 5AC Gen2 * Fix compat_version for sxt 5ac * Update patch * Unused * Fix lan configuration for some devices * Rolling average of noise level * Unused * Split out the ath10k rssi monitor (its very simple at the moment) * Ignore .DS_Store * Reboot if ethernet doesnt come up (but only once!) * reboot returns - add exit * Add some logging info * Fix ] * Check all possibly ethernet bridges * Improve mac fixing * Remove HostAP on small memory devices * Reduce dropbear footprint * Add setsid * Kill hostap when upgrading to save memory * Different way to detect hostapd unavailable * New build steps * Improve manager logging * Fix name conflict for the two monitors * Try to improve test mesh name resolve problem * Migrate tiny to generic (tiny doesnt work properly) * Typo * Another attempt to fix macs for Mikrotik * Protect against missing trackers * Fix wpad for ipq40xx * Remove old tunnel check code * Enable ZRAM swap to aid low memory devices * ath10k noise can something be out of range - protect against that * Updated with current devices and status * Update firmware which has been tested * Updated with more builds * More binary/README * Fix css error * Start noise at sensible base level * Unfix the css so it looks how it use to. * Save as much memory as we can on lowmem nodes * Hide some options on low memory devices * Add "eol" to 32MB devices * Restart network rather than reboot node if it seems to be broken * Fixes * Revert network reset * Fix ar750 networking * Continue to trim tiny configs * More devices * Dump IW output messages * Fix Rocket 5AC intermittent ethernet issue * Ethernet fix for PowerBeam 5AC 500 * More tiny size reduction * More support data * Fixed POE and USB power features * Add Ubiquiti NanoBeam AC (gen1) * NanoStation (not NanoBeam) * Add mii-tool package * Device updates * Bump update time to 5 minutes * Fix ethernet negotiation for rocker-5ac and nanobeam * Fix iplookup * Config changes based on call feedback * Radio listing fixes * Update with more untested builds * Fallback TxMbps extracted from iw station dump * Fix tunnel detection for low memory nodes * Remove unused feed packages * snapshot build * Update stability info * Add powerbeam-5ac-500 * Typo * Add missing 3.22.1.0 * Add MikroTik LHG 5 AC * Fix permissions * Fix permissions * AirGrid's take Bullet builds * Mikrotik AC3 * Improve supportdata structure a little to make it easier to find things * Restore WAN VLAN overrides * Fix vlan regex for hap2 and hap3 * Support old and new style poe controls * hap-ac3 is version 1.1 * Handle typo in some openwrt config files * Fix HAP AC3 install * Update hap ac3 status * Support user overrides for network ports (non-swconfig devices) * LHG 5AC support * Remove -nand * Remove non-working platform.sh change * tunnel weight override * Omit LinkQualityMult when value is 1 * Add mANTBox 19s and 15s * Support ath79 mikrotik devices which require ath10k in the initramfs Co-authored-by: apcameron <apcameron@softhome.net> Co-authored-by: Joe AE6XE <ae6xe@arrl.net> Co-authored-by: Joe Ayers <joe@arrl.net>
2022-12-22 13:22:49 -07:00
local request = luci.http.Request(nixio.getenv(),
function()
local v = io.read(1024)
if not v then
io.close()
end
return v
end
)
parms = request:formvalue()
end
function navbar()
html.print("<tr><td>")
html.print("<hr><table cellpadding=5 border=0 width=100%><tr>")
html.print("<td align=center width=15%><a href='status'>Node Status</a></td>")
html.print("<td align=center width=15%><a href='setup'>Basic Setup</a></td>")
html.print("<td align=center width=15% class=navbar_select><a href='ports'>Port Forwarding,<br>DHCP, and Services</a></td>")
html.print("<td align=center width=15%><a href='vpn'>Tunnel<br>Server</a></td>")
html.print("<td align=center width=15%><a href='vpnc'>Tunnel<br>Client</a></td>")
html.print("<td align=center width=15%><a href='admin'>Administration</a></td>")
html.print("<td align=center width=15%><a href='advancedconfig'>Advanced<br>Configuration</a></td>")
html.print("</tr></table><hr>")
end
function validate_service_name(name)
if not name or name == "" or name:match("[:-\"|<>]") then
return false
else
return true
end
end
function validate_service_protocol(proto)
if not proto or proto == "" or proto:match("[:-\"|<>]") or not proto:match("^%w+") then
return false
else
return true
end
end
function validate_service_suffix(suffix)
if not suffix or suffix:match("[:-\"|<>]") or not suffix:match("^[%w/?._=#-]*$") then
return false
else
return true
end
end
local serv_err = {}
function serverr(msg)
serv_err[#serv_err + 1] = msg:gsub(">", "&gt;"):gsub("<", "&lt;")
end
local port_err = {}
function porterr(msg)
port_err[#port_err + 1] = msg
end
local dmz_err = {}
function dmzerr(msg)
dmz_err[#dmz_err + 1] = msg
end
local dhcp_err = {}
function dhcperr(msg)
dhcp_err[#dhcp_err + 1] = msg
end
local alias_err = {}
function aliaserr(msg)
alias_err[#alias_err + 1] = msg
end
local errors = {}
function err(msg)
errors[#errors + 1] = msg
end
local hidden = {}
function hide(m)
hidden[#hidden + 1] = m
end
local hosts = {}
local addrs = {}
local macs = {}
if config ~= "mesh" or nixio.fs.stat("/tmp/reboot-required") then
http_header()
html.header(node .. " setup", true)
html.print("<body><center><table width=820><tr><td>")
html.alert_banner()
navbar()
html.print("</td></tr><tr><td align=center><br><b>")
if config == "" then
html.print("This page is not available until the configuration has been set.")
else
html.print("The specified configuration is invalid, try flushing your browser cache or reboot the mesh node.")
end
html.print("</b></td></tr>")
html.print("</table></center>")
html.footer();
html.print("</body></html>")
http_footer()
os.exit()
end
-- check for dmz mode
local dmz_mode = tonumber(cursor:get("aredn", "@dmz[0]", "mode"))
if not dmz_mode then
dmz_mode = 2
end
local lanip, lanbcast, lanmask = aredn.hardware.get_interface_ip4(aredn.hardware.get_iface_name("lan"))
local lannet_d = nixio.bit.band(ip_to_decimal(lanip), ip_to_decimal(lanmask))
local tmpdir = "/tmp/web/ports"
if not parms.reload then
remove_all(tmpdir)
end
nixio.fs.mkdir(tmpdir)
local fsuffix = dmz_mode == 0 and ".nat" or ".dmz"
local portfile = "/etc/config.mesh/_setup.ports" .. fsuffix
local dhcpfile = "/etc/config.mesh/_setup.dhcp" .. fsuffix
local servfile = "/etc/config.mesh/_setup.services" .. fsuffix
local aliasfile = "/etc/config.mesh/aliases" .. fsuffix
-- if a reset or a first time page load
-- read the data from the config files
if parms.button_reset or not parms.reload then
local i = 0
if nixio.fs.stat(portfile) then
for line in io.lines(portfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local k, v = line:match("(%S+)%s+=%s+(%S+)")
if v then
parms[k] = v
else
local intf, type, out, ip, _in, enable = line:match("(.*):(.*):(.*):(.*):(.*):(.*)")
if intf then
i = i + 1
parms["port" .. i .. "_intf"] = intf
parms["port" .. i .. "_type"] = type
parms["port" .. i .. "_out"] = out
parms["port" .. i .. "_ip"] = ip
parms["port" .. i .. "_in"] = _in
parms["port" .. i .. "_enable"] = enable
end
end
end
end
end
parms.port_num = i
-- set dhcp reservations
-- ip addresses are stored as offsets from the lan network address
i = 0
if nixio.fs.stat(dhcpfile) then
for line in io.lines(dhcpfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local a, b, x = line:match("(%S*)%s+(%S*)%s+(.*)")
if x then
local c, d = x:match("(%S*)%s+(%S*)")
if not c then
c = x
d = ""
end
i = i + 1
local prefix = "dhcp" .. i .. "_"
parms[prefix .. "mac"] = a
parms[prefix .. "ip"] = decimal_to_ip(lannet_d + tonumber(b))
parms[prefix .. "host"] = c
parms[prefix .. "noprop"] = d
end
end
end
end
parms.dhcp_num = i
-- services
i = 0
if nixio.fs.stat(servfile) then
for line in io.lines(servfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local a, b, c, d, x = line:match("([^|]*)|([^|]*)|([^|]*)|([^|]*)|(.*)")
if x then
local e, f = x:match("(.*)|(.*)")
if not e then
e = x
f = ""
end
i = i + 1
local prefix = "serv" .. i .. "_"
parms[prefix .. "name"] = a
parms[prefix .. "link"] = b
parms[prefix .. "proto"] = c
parms[prefix .. "host"] = d
parms[prefix .. "port"] = e
parms[prefix .. "suffix"] = f
end
end
end
end
parms.serv_num = i
-- aliases
i = 0
if nixio.fs.stat(aliasfile) then
for line in io.lines(aliasfile)
do
if not (line:match("^%s*#") or line:match("^%s*$")) then
local a, b = line:match("(.*)%s+(.*)")
if b then
i = i + 1
parms["alias" .. i .. "_ip"] = a
parms["alias" .. i .. "_host"] = b
end
end
end
end
parms.alias_num = i
-- sanatize the 'add' values
parms.port_add_intf = dmz_mode ~= 0 and "wan" or "wifi"
parms.port_add_type = "tcp"
if not parms.dmz_ip then
parms.dmz_ip = ""
end
parms.port_add_out = ""
parms.port_add_ip = ""
parms.port_add_in = ""
parms.dhcp_add_host = ""
parms.dhcp_add_ip = ""
parms.dhcp_add_mac = ""
parms.dhcp_add_noprop = ""
parms.serv_add_name = ""
parms.serv_add_proto = ""
parms.serv_add_host = ""
parms.serv_add_port = ""
parms.serv_add_suffix = ""
parms.alias_add_host = ""
parms.alias_add_ip = ""
end
local dhcp_start = tonumber(cursor:get("dhcp", "@dhcp[0]", "start"))
local dhcp_limit = tonumber(cursor:get("dhcp", "@dhcp[0]", "limit"))
local dhcp_end = dhcp_start + dhcp_limit - 1
-- load and validate the ports
local list = {}
for i = 1,parms.port_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local port_num = 0
local usedports = {}
local f = io.open(tmpdir .. "/ports", "w")
if f then
local vars = { "_intf", "_type", "_out", "_ip", "_in" }
for _, val in ipairs(list)
do
for _ = 1,1 -- a non-loop so we can break out to continue the parent loop
do
for _, var in ipairs(vars)
do
local varname = "port" .. val .. var
local v = parms[varname]
if v then
v = v:gsub("^%s+", ""):gsub("%s+$", "")
else
v = ""
end
parms[varname] = v
_G[var] = v
end
local varname = "port" .. val .. "_enable"
if not parms[varname] then
parms[varname] = "0"
end
_enable = parms[varname]
if val == "_add" then
_enable = "1"
end
local continue = false
if val == "_add" then
if not ((_out ~= "" or _ip ~= "" or _in ~= "") and (parms.port_add or parms.button_save)) then
break
end
else
if parms["port" .. val .. "_del"] then
break
end
end
2022-07-31 13:12:17 -06:00
if val == "_add" and parms.button_save then
porterr(val .. " this rule must be added or cleared out before saving changes")
break
end
if _out:match("-") then
if validate_port_range(_out) then
_in = _out:match("^%s*(%d+)")
else
porterr(val .. "'" .. _out .. "' is not a valid port range")
end
else
if _out == "" then
porterr(val .. " an outside port is required")
elseif not validate_port(_out) then
porterr(val .. "'" .. _out .. "' is not a valid port")
end
end
if _ip == "" then
porterr(val .. " an address must be selected")
elseif not validate_ip(_ip) then
porterr(val .. "'" .. _ip .. "' is not a valid address")
end
if _in == "" then
porterr(val .. "a LAN port is required")
elseif not validate_port(_in) then
porterr(val .. "'" .. _in .. "' is not a valid port")
end
if val == "_add" and #port_err > 0 then
break
end
-- commit the data for this rule
port_num = port_num + 1
usedports[_out] = true
if _type ~= "tcp" and _type ~= "udp" then
_type = "both"
end
f:write(_intf .. ":" .. _type .. ":" .. _out .. ":" .. _ip .. ":" .. _in .. ":" .. _enable .. "\n")
2022-07-31 13:12:17 -06:00
for _, var in ipairs(vars)
do
parms["port" .. port_num .. var] = _G[var]
end
if val == "_add" then
parms.port_add_intf = "wifi"
parms.port_add_out = ""
parms.port_add_ip = ""
parms.port_add_in = ""
end
end
end
if parms.dmz_ip and parms.dmz_ip ~= "" then
f:write("dmz_ip = " .. parms.dmz_ip .. "\n")
if not validate_ip(parms.dmz_ip) then
dmzerr(parms.dmz_ip .. " is not a valid address")
end
end
f:close()
end
parms.port_num = port_num
-- load and validate the dhcp reservations
local list = {}
for i = 1,parms.dhcp_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local dhcp_num = 0
for _, val in ipairs(list)
do
for _ = 1,1
do
local host = parms["dhcp" .. val .. "_host"]
local ip = parms["dhcp" .. val .. "_ip"]
local mac = parms["dhcp" .. val .. "_mac"]
local noprop = parms["dhcp" .. val .. "_noprop"]
if not noprop then
noprop = ""
end
local foundhost = false
if val == "_add" then
if host ~= "" then
local pattern = "%s" .. host .. "%s"
if nixio.fs.stat("/var/run/hosts_olsr.stable") then
for line in io.lines("/var/run/hosts_olsr.stable")
do
if line:lower():match(pattern) then
foundhost = true
dhcperr(val .. [[ <font color='red'>Warning!</font> ']] .. host .. [[ is already in use!<br>
Please choose another hostname.<br>
Prefixing the hostname with your callsign will help prevent duplicates on the network.
]])
break
end
end
end
end
if not ((host ~= "" or ip ~= "" or mac ~= "" or foundhost) and (parms.dhcp_add or parms.button_save)) then
break
end
elseif parms["dhcp" .. val .. "_del"] then
break
end
if val == "_add" and parms.button_save then
dhcperr(val .. " this reservation must be added or cleared before saving changes")
break
end
if validate_hostname(host) then
if not foundhost then
local lhost = host:lower()
if lhost == node:lower() or lhost == tactical:lower() then
dhcperr(val .. " hostname '" .. host .. "' is already in use")
end
for key, _ in pairs(hosts)
do
if key:lower() == lhost then
dhcperr(val .. " hostname '" .. host .. "' is already in use")
break
end
end
end
else
if host then
dhcperr(val .. " '" .. host .. "' is not a valid hostname")
else
dhcperr(val .. " a hostname is required")
end
end
if validate_ip(ip) then
if addrs[ip] then
dhcperr(val .. " '" .. ip .. "' is already in use")
elseif ip == lanip or not validate_same_subnet(ip, lanip, lanmask) or not validate_ip_netmask(ip, lanmask) then
dhcperr(val .. " '" .. ip .. "' is not a valid LAN address")
end
else
if ip then
dhcperr(val .. " '" .. ip .. "' is not a valid address")
else
dhcperr(val .. " an IP Address must be selected")
end
end
if mac:match("[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]:[a-fA-F0-9][a-fA-F0-9]") then
if macs[mac] then
dhcperr(val .. " MAC " .. mac .. " is already in use")
end
else
if mac then
dhcperr(val .. " '" .. mac .. "' is not a valid mac address")
else
dhcperr(val .. " a MAC address is required")
end
end
if val == "_add" and #dhcp_err > 0 then
break
end
dhcp_num = dhcp_num + 1
local prefix = "dhcp" .. dhcp_num .. "_"
parms[prefix .. "host"] = host
parms[prefix .. "ip"] = ip
parms[prefix .. "mac"] = mac
parms[prefix .. "noprop"] = noprop
hosts[host] = true
addrs[ip] = true
macs[mac] = true
if val == "_add" then
parms.dhcp_add_host = ""
parms.dhcp_add_ip = ""
parms.dhcp_add_mac = ""
parms.dhcp_add_noprop = ""
end
end
end
-- add existing leases
for lease, lval in pairs(parms)
do
local n = lease:match("^lease(%d+)_add$")
if n and lval ~= "" then
local found = false
for k, v in pairs(parms)
do
if k:match("dhcp%d+_mac") then
if v == parms["lease" .. n .. "_mac"] then
found = true
break
end
end
end
if not found then
dhcp_num = dhcp_num + 1
local prefix1 = "lease" .. n .. "_"
local prefix2 = "dhcp" .. dhcp_num .. "_"
local host = parms[prefix1 .. "host"]
local ip = parms[prefix1 .. "ip"]
local mac = parms[prefix1 .. "mac"]
local noprop = parms[prefix1 .. "noprop"]
parms[prefix2 .. "host"] = host
parms[prefix2 .. "ip"] = ip
parms[prefix2 .. "mac"] = mac
parms[prefix2 .. "noprop"] = noprop and noprop or "0"
local lhost = host:lower()
if lhost == node:lower() or lhost == tactical:lower() then
dhcperr(dhcp_num .. " hostname '" .. host .. "' is already in use")
end
for key, _ in pairs(hosts)
do
if key:lower() == lhost then
dhcperr(dhcp_num .. " hostname '" .. host .. "' is already in use")
break
end
end
if addrs[ip] then
dhcperr(dhcp_num .. " is already in use")
end
if macs[mac] then
dhcperr(dhcp_num .. " MAC " .. mac .. " is already in use")
end
end
end
end
parms.dhcp_num = dhcp_num
dhcphosts = {}
dhcphosts[lanip] = "localhost"
-- replace "blank" dhcp hostname and save the dhcp info into the tmpdir
local f = io.open(tmpdir .. "/dhcp", "w")
if f then
local nn = 1
for i = 1,parms.dhcp_num
do
if parms["dhcp" .. i .. "_host"] == "*" then
while hosts["noname" .. nn]
do
nn = nn + 1
end
parms["dhcp" .. i .. "_host"] = "noname" .. nn
hosts["noname" .. nn] = true
end
f:write(parms["dhcp" .. i .. "_mac"] .. " " .. (ip_to_decimal(parms["dhcp" .. i .. "_ip"]) - lannet_d) .. " " .. parms["dhcp" .. i .. "_host"] .. " " .. parms["dhcp" .. i .. "_noprop"] .. "\n")
if not (dhcphosts[parms["dhcp" .. i .. "_ip"]]) then
dhcphosts[parms["dhcp" .. i .. "_ip"]] = parms["dhcp" .. i .. "_host"]
end
end
f:close()
end
-- aliases
local list = {}
for i = 1,parms.alias_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local alias_num = 0
for _, val in ipairs(list)
do
for _ = 1,1
do
local foundhost = false
local host = parms["alias" .. val .. "_host"]
local ip = parms["alias" .. val .. "_ip"]
-- if adding aliases check the name is not already in use,
-- also check that it dos not contain anything that will be weird on the mesh
-- for instance: supercoolservice.kg6wxc-host.local.mesh is certainly a valid host name, but it won't work for the mesh.
if val == "_add" then
if host ~= "" then
local pattern = "%s" .. host .. "%s"
if nixio.fs.stat("/var/run/hosts_olsr.stable") then
for line in io.lines("/var/run/hosts_olsr.stable")
do
if line:lower():match(pattern) then
foundhost = true
aliaserr(val .. [[ <font color='red'>Warning!</font> ']] .. host .. [[ is already in use!<br>
Please choose another hostname.<br>
Prefixing the hostname with your callsign will help prevent duplicates on the network.
]])
break
end
end
end
if not validate_hostname(host) then
aliaserr(val .. " <font color='red'>Warning!</font> The alias name: '" .. host .."' is invalid")
end
if host:match("%.") then
aliaserr(val .. " '" .. host .. "' cannot contain the dot '.' character")
end
end
if not ((host ~= "" or ip ~= "" or foundhost) and (parms.alias_add or parms.button_save)) then
break
end
elseif parms["alias" .. val .. "_del"] then
break
end
if val == "_add" and parms.button_save then
aliaserr(val .. " this alias must be added or cleared out before saving changes")
break
end
if val == "_add" and #alias_err > 0 and alias_err[#alias_err]:match("^" .. val .. " ") then
break
end
alias_num = alias_num + 1
parms["alias" .. alias_num .. "_host"] = host
parms["alias" .. alias_num .. "_ip"] = ip
hosts[host] = true
if val == "_add" then
parms.alias_add_host = ""
parms.alias_add_ip = ""
end
end
end
-- write to temp file
local f = io.open(tmpdir .. "/aliases", "w")
if f then
for i = 1,alias_num
do
f:write(parms["alias" .. i .. "_ip"] .. " " .. parms["alias" .. i .. "_host"] .. "\n")
end
f:close()
end
parms.alias_num = alias_num
-- load and validate services
local list = {}
for i = 1,parms.serv_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local serv_num = 0
hosts[""] = true
hosts[node] = true
usedports[""] = true
local servicenames = {}
local vars = { "name", "link", "proto", "host", "port", "suffix" }
local f = io.open(tmpdir .. "/services", "w")
if f then
for _, val in ipairs(list)
do
for _ = 1,1
do
for _, var in ipairs(vars)
do
local varname = "serv" .. val .. "_" .. var
local v = parms[varname]
if v then
v = v:gsub("^%s+", ""):gsub("%s+$", "")
else
v = ""
end
parms[varname] = v
_G[var] = v
end
if link == "" then
link = "0"
end
if dmz_mode == 0 then
host = node
end
-- remove services that have had their host or port deleted
if val ~= "_add" and not (dmz_mode == 0 and true or hosts[host]) then
break
end
if val == "_add" then
if not ((name ~= "" or proto ~= "" or port ~= "" or suffix ~= "") and (parms.serv_add or parms.button_save)) then
break
end
else
if parms["serv" .. val .. "_del"] or not (name ~= "" or proto ~= "" or port ~= "" or suffix ~= "") then
break
end
end
if val == "_add" and parms.button_save then
serverr(val .. " this service must be added or cleared out before saving changes")
break
end
if name == "" then
serverr(val .. " a name is required")
elseif not validate_service_name(name) then
serverr(val .. " '" .. name .. "' is not a valid service name")
elseif servicenames[name] then
serverr(val .. " the name '" .. name .. "' is already in use")
end
if link == "1" then
if proto == "" then
proto = "http"
end
parms["serv" .. val .. "_proto"] = proto
if not validate_service_protocol(proto) then
serverr(val .. " '" .. proto .. "' is not a valid protocol")
elseif port == "" then
serverr(val .. " a port number is required")
elseif not validate_port(port) then
serverr(val .. " '" .. port .. "' is not a valid port")
elseif not validate_service_suffix(suffix) then
serverr(val .. " '" .. suffix .. "' is not a valid service suffix")
end
elseif val == "_add" then
proto = ""
port = ""
suffix = ""
end
if val == "_add" and #serv_err > 0 then
break
end
-- commit the data for this service
serv_num = serv_num + 1
servicenames[name] = true
f:write(name .. "|" .. link .. "|" .. proto .. "|" .. host .. "|" .. port .. "|" .. suffix .. "\n")
for _, var in ipairs(vars)
do
parms["serv" .. serv_num .. "_" .. var] = _G[var]
end
if val == "_add" then
parms.serv_add_name = ""
parms.serv_add_link = ""
parms.serv_add_proto = ""
parms.serv_add_host = ""
parms.serv_add_port = ""
parms.serv_add_suffix = ""
end
end
end
f:close()
end
parms.serv_num = serv_num
-- save configuration
if parms.button_save and not (#port_err > 0 or #dhcp_err > 0 or #dmz_err > 0 or #serv_err > 0 or #alias_err > 0) then
filecopy(tmpdir .. "/ports", portfile)
filecopy(tmpdir .. "/dhcp", dhcpfile)
filecopy(tmpdir .. "/services", servfile)
filecopy(tmpdir .. "/aliases", aliasfile)
2022-07-31 13:12:17 -06:00
os.remove("/tmp/service-validation-state")
if os.execute("/usr/local/bin/node-setup -a -p mesh > /dev/null 2>&1") ~= 0 then
err("problem with configuration")
end
if os.execute("/etc/init.d/dnsmasq restart > /dev/null 2>&1") ~= 0 then
err("problem with dnsmasq")
end
if os.execute("/etc/init.d/firewall restart > /dev/null 2>&1") ~= 0 then
err("problem with port setup")
end
if os.execute("/etc/init.d/olsrd restart > /dev/null 2>&1") ~= 0 then
err("problem with olsr setup")
end
end
-- generate the page
http_header()
html.header(node .. " setup", true)
html.print("<body><center>")
html.alert_banner()
html.print("<form method=post action=/cgi-bin/ports enctype='multipart/form-data'>")
html.print("<table width=820>")
html.print("<tr><td>")
navbar()
html.print("</td></tr>")
-- control buttons
html.print([[<tr><td align=center>
<a href='/help.html#ports' target='_blank'>Help</a>
&nbsp;&nbsp;&nbsp;
<input type=submit name=button_save value='Save Changes' title='Save and use these settings now (takes about 20 seconds)'>&nbsp;
<input type=submit name=button_reset value='Reset Values' title='Revert to the last saved settings'>&nbsp;
Update AREDN to OpenWRT 22.3.2 (Major Upgrade) (#574) * Update to Openwrt 21.02 and add support for the CPE710 v1 Update scripts to change references to ifname to device due to a change in Openwrt naming reverse-wpad-basic-wolfssl and disable SSL on Curl NOTE: The compile host must have python3-distutils installed for gpsd to build * aredn: initial working upgrade to openwrt 21.02.1 * aredn: update 1 to working upgrade to openwrt 21.02.1 * aredn: add cpe710v1 to build config * Andrew's patches * Remove duplicates + display perl * Temp disable wifi extension patch * ifname/ports support * Add spectrum patch back in * Generic function to extra interfaces * New api to get wifi ifname * Disables jails * Style link * aredn: partial upgrade to openwrt 22.0.3.0 added AC device images and partial migration to 22.0.3.0 firewall upgrade pending * aredn: update mesh-release and revert config.mk * Unused * NFT firewall rewrite * Common-isze configs * Fix network layout for hap2 * Use local packages dev (new firewall rules) * Add HAP2 * Add pause after network restart to let bridge reinitialize * Various lua fixes for new lua version * Tweak config * Re-fix networking (lost patch change) * Add new radio names * Tolerate missing wifi * Fix hap-lite switch setup * More devices * New radio id * Build Rocket 5AC lite * Remove need for luci.sys * Remove need for luci.sys * Explicitly name wlan interfaces * Handle different compatibility verisoning * Update networking for switches * ipref version bump * Extra flag for curl * Better compat_version fix * Remove wolfssl * Fix dns server * Fix device name * Unused * Remove things we dont need * Remove unused packages * Generic macaddr overrides * Fix uci commit * Fix luci.template.parser to avoid luci.http loading the real thing * Rocket-M build * Add search-domain dhcp option * Turn of ipv6 * No IPV6 in dnsmasq * Override mac addresses if devices all the same * Working from master (for now) * Put back hostap * Disable old ethmac fixup * Tweak configs * Move back to v22.03.2 Leave ipq4019 builds to master * Need IPV6 to compile nft firewall * Rocket-M fixes * Before we start * WIP * Working snapshot * Cleaned patches * Merged patch * Single patch to support HAP2 * Fix typo * Add nanostation-m * 5/10Mhz patch * 5+10MHz patch for ath10k-ct driver * Extend 2Ghz channel check to include -4 to -1 * Add chanbw setup for ath10k (like ath9k) * Added TP-Link CPE710 v1 * Override firmwares * Missing patch * Dropbear config like 3.22.8.0 * Add Ubiquiti Rocket 5AC Lite * Fix c6 * Update * Need more scan channels * Remove IPV6 * Improve mac fixups * Put back missing nft app * IPv6 removed so dont have to disable it * Fix rocket-m flash bug * Fix nanostation-m * Nanobridge is tiny * Fix wifi order for ar750 * Rocket M5 XW support * New rates * Fix firewall4 so we don't need IPv6 * Allow channel width to be restricted * Move channel list into library * Fix naming * Mechanism to block specific channels on specific radios * Refresh buttons * routerboard-sxt-5nd * CPE605 v1.0 * Improve rocket m xw * tpink * Update patch * Update to remove disable * Remove BW restrictions on cpe710 * Restrict to what has been tested * Remove test BW restrictions * sxtsq-5-ac * Update * Update * powerbeam-m5-300 support * Fix * Fix hap2 * Tidy unused patches * Remove limit * Add ubnt_bullet-m-ar7241 * Added ubnt_nanobeam-ac-gen2 * Fix typo * Tolerate missing dtd ip * Explicitly gix hap2 mac addresses * Fix some broken patches * Hap2 wont work at 5MHz * Ubiquiti LiteBeam 5AC Gen2 * Fix compat_version for sxt 5ac * Update patch * Unused * Fix lan configuration for some devices * Rolling average of noise level * Unused * Split out the ath10k rssi monitor (its very simple at the moment) * Ignore .DS_Store * Reboot if ethernet doesnt come up (but only once!) * reboot returns - add exit * Add some logging info * Fix ] * Check all possibly ethernet bridges * Improve mac fixing * Remove HostAP on small memory devices * Reduce dropbear footprint * Add setsid * Kill hostap when upgrading to save memory * Different way to detect hostapd unavailable * New build steps * Improve manager logging * Fix name conflict for the two monitors * Try to improve test mesh name resolve problem * Migrate tiny to generic (tiny doesnt work properly) * Typo * Another attempt to fix macs for Mikrotik * Protect against missing trackers * Fix wpad for ipq40xx * Remove old tunnel check code * Enable ZRAM swap to aid low memory devices * ath10k noise can something be out of range - protect against that * Updated with current devices and status * Update firmware which has been tested * Updated with more builds * More binary/README * Fix css error * Start noise at sensible base level * Unfix the css so it looks how it use to. * Save as much memory as we can on lowmem nodes * Hide some options on low memory devices * Add "eol" to 32MB devices * Restart network rather than reboot node if it seems to be broken * Fixes * Revert network reset * Fix ar750 networking * Continue to trim tiny configs * More devices * Dump IW output messages * Fix Rocket 5AC intermittent ethernet issue * Ethernet fix for PowerBeam 5AC 500 * More tiny size reduction * More support data * Fixed POE and USB power features * Add Ubiquiti NanoBeam AC (gen1) * NanoStation (not NanoBeam) * Add mii-tool package * Device updates * Bump update time to 5 minutes * Fix ethernet negotiation for rocker-5ac and nanobeam * Fix iplookup * Config changes based on call feedback * Radio listing fixes * Update with more untested builds * Fallback TxMbps extracted from iw station dump * Fix tunnel detection for low memory nodes * Remove unused feed packages * snapshot build * Update stability info * Add powerbeam-5ac-500 * Typo * Add missing 3.22.1.0 * Add MikroTik LHG 5 AC * Fix permissions * Fix permissions * AirGrid's take Bullet builds * Mikrotik AC3 * Improve supportdata structure a little to make it easier to find things * Restore WAN VLAN overrides * Fix vlan regex for hap2 and hap3 * Support old and new style poe controls * hap-ac3 is version 1.1 * Handle typo in some openwrt config files * Fix HAP AC3 install * Update hap ac3 status * Support user overrides for network ports (non-swconfig devices) * LHG 5AC support * Remove -nand * Remove non-working platform.sh change * tunnel weight override * Omit LinkQualityMult when value is 1 * Add mANTBox 19s and 15s * Support ath79 mikrotik devices which require ath10k in the initramfs Co-authored-by: apcameron <apcameron@softhome.net> Co-authored-by: Joe AE6XE <ae6xe@arrl.net> Co-authored-by: Joe Ayers <joe@arrl.net>
2022-12-22 13:22:49 -07:00
<input type=button name=button_refresh value='Refresh' title='Refresh this page' onclick='window.location.reload();'>&nbsp;
<tr><td>&nbsp;</td></tr>]])
hide("<input type=hidden name=reload value=1></td></tr>")
-- messages
if parms.button_save then
if #port_err > 0 or #dhcp_err > 0 or #dmz_err > 0 or #serv_err > 0 then
html.print("<tr><td align=center><b>Configuration NOT saved!</b></td></tr>")
elseif #errors > 0 then
html.print("<tr><td align=center><b>Configuration saved, however:<br>")
for _, err in ipairs(errors)
do
html.print(err .. "<br>")
end
html.print("</b></td></tr>")
else
html.print("<tr><td align=center><b>Configuration saved and is now active.</b></td></tr>")
end
html.print("<tr><td>&nbsp;</td></tr>")
end
-- everything else
function print_reservations()
html.print("<table cellpadding=0 cellspacing=0><tr><th colspan=4>DHCP Address Reservations</th></tr>")
html.print("<tr><td colspan=4 height=5></td></tr>")
html.print("<tr><td align=center>Hostname</td><td align=center>IP Address</td><td align=center>MAC Address</td>")
2022-07-31 13:12:17 -06:00
if dmz_mode ~= 0 then
html.print("<td align=center style='font-size:10px;'>Do Not<br>Propagate</td><td></td></tr>")
else
html.print("<td></td><td></td></tr>")
end
html.print("<tr><td colspan=4 height=5></td></tr>")
local list = {}
for i = 1,parms.dhcp_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
for _, val in ipairs(list)
do
local host = parms["dhcp" .. val .. "_host"]
local ip = parms["dhcp" .. val .. "_ip"]
local mac = parms["dhcp" .. val .. "_mac"]:lower()
local noprop = parms["dhcp" .. val .. "_noprop"]
if val == "_add" and #list > 1 then
html.print("<tr><td colspan=4 height=10></td></tr>")
end
html.print("<tr><td><input style='width=180;' type=text name=dhcp" .. val .. "_host value='" .. host .. "'></td>")
html.print("<td align=center><select name=dhcp" .. val .. "_ip>")
if val == "_add" then
html.print("<option value=''>- IP Address -</option>\n")
end
for i = dhcp_start,dhcp_end
do
local selip = decimal_to_ip(lannet_d + i - lannet_d % 256)
if selip ~= lanip then
local ipname = dhcphosts[selip]
if not ipname or selip == ip then
ipname = selip
end
html.print("<option " .. (ip == selip and "selected" or "") .. " value='" .. selip .. "'>" .. ipname .. "</option>")
end
end
html.print("</select></td>")
html.print("<td><input style='width:120;' type=text name=dhcp" .. val .. "_mac value='" .. mac .. "'></td>")
if dmz_mode ~= 0 then
if noprop == "#NOPROP" then
html.print("<td align=center><input type=checkbox id=dhcp" .. val .. "_noprop name=dhcp" .. val .. "_noprop value='#NOPROP' checked></td>")
else
html.print("<td align=center><input type=checkbox id=dhcp" .. val .. "_noprop name=dhcp" .. val .. "_noprop value='#NOPROP'></td>")
end
else
html.print("<td></td>")
end
html.print("<td><nobr>&nbsp;<input type=submit name=")
if val == "_add" then
html.print("dhcp_add value=Add title='Add this as a DHCP reservation'")
else
html.print("dhcp" .. val .. "_del value=Del title='Remove this reservation'")
end
html.print("></nobr></td></tr>")
while #dhcp_err > 0 and dhcp_err[1]:match("^" .. val .. " ")
do
html.print("<tr><th colspan=4>" .. dhcp_err[1]:gsub("^%S+ ", "") .. "</th></tr>")
table.remove(dhcp_err, 1)
end
html.print("<tr><td height=5></td></tr>")
end
html.print("<tr><td>&nbsp;</td></tr>")
html.print("<tr><th colspan=4>Current DHCP Leases</th></tr>\n<tr>")
local i = 0
if nixio.fs.stat("/tmp/dhcp.leases") then
for line in io.lines("/tmp/dhcp.leases")
do
i = i + 1
local _, mac, ip, host = line:match("(%S+)%s+(%S+)%s+(%S+)%s+(%S+)")
html.print("<tr><td height=5></td></tr>")
html.print("<tr><td align=center>" .. host .. "</td><td align=center><small>" .. ip .. "</small></td>")
html.print("<td align=center><small>" .. mac .. "</small></td><td></td><td><nobr>&nbsp;")
html.print("<input type=submit name=lease" .. i .. "_add value=Add ")
html.print("title='Use these values as an address reservation'></nobr></td></tr>")
hide("<input type=hidden name=lease" .. i .. "_host value=" .. host .. ">")
hide("<input type=hidden name=lease" .. i .. "_ip value=" .. ip .. ">")
hide("<input type=hidden name=lease" .. i .. "_mac value=" .. mac .. ">")
end
end
if i == 0 then
html.print("<tr><td align=center colspan=4>there are no active leases</td></tr>")
end
html.print("</table>")
end
function print_forwarding()
html.print("<table cellpadding=0 cellspacing=0>")
html.print("<tr><th colspan=6>Port Forwarding</th></tr>")
html.print("<tr><td colspan=6 height=5></td></tr>")
html.print("<tr><td align=center>Interface</td><td align=center>Type</td>")
html.print("<td align=center>Outside Port</td><td align=center>LAN IP</td>")
html.print("<td align=center>LAN Port</td><td>&nbsp;</td></tr>")
html.print("<tr><td colspan=6 height=5></td></tr>")
local list = {}
for i = 1,parms.port_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local vars = { "_intf", "_type", "_out", "_ip", "_in", "_enable", "_adv", "_link", "_proto", "_suffix", "_name" }
for _, val in ipairs(list)
do
for _, var in ipairs(vars)
do
_G[var] = parms["port" .. val .. var]
end
if val == "_add" and #list > 1 then
html.print("<tr><td colspan=6 height=10></td></tr>")
end
html.print("<tr>")
hide("<input style='width:90;' type=hidden name=port" .. val .. "_enable value=1>")
-- port forwarding settings
html.print("<td align=center valign=top><select name=port" .. val .. "_intf title='forward inbound packets from this interface'>")
if dmz_mode == 0 then
html.print("<option " .. (_intf == "wifi" and "selected" or "") .. " value='wifi'>WiFi</option>")
html.print("<option " .. (_intf == "wan" and "selected" or "") .. " value='wan'>WAN</option>")
html.print("<option " .. (_intf == "both" and "selected" or "") .. " value='both'>Both</option>")
else
html.print("<option " .. (_intf == "wan" and "selected" or "") .. " value='wan'>WAN</option>")
end
html.print("</select></td>")
html.print("<td align=center valign=top><select name=port" .. val .. "_type>")
html.print("<option " .. (_type == "tcp" and "selected" or "") .. " value='tcp'>TCP</option>")
html.print("<option " .. (_type == "udp" and "selected" or "") .. " value='udp'>UDP</option>")
html.print("<option " .. (_type == "both" and "selected" or "") .. " value='both'>Both</option>")
html.print("</select></td>")
html.print("<td align=center valign=top><input style='width:90;' type=text name=port" .. val .. "_out value='" .. _out .. "'></td>")
html.print("<td align=center valign=top><select name=port" .. val .. "_ip>")
if val == "_add" then
html.print("<option value=''>- IP Address -</option>")
end
local lanlimit = nixio.bit.lshift(1, 32 - netmask_to_cidr(lanmask)) - 2
for i = 1,lanlimit
do
local selip = decimal_to_ip(lannet_d + i)
local ipname = dhcphosts[selip]
if not ipname then
ipname = selip
end
html.print("<option " .. (_ip == selip and "selected" or "") .. " value='" .. selip .. "'>" .. ipname .. "</option>")
end
html.print("</select></td>")
html.print("<td align=left valign=top><input style='width:90;' type=text name=port" .. val .. "_in value='" .. _in .. "'></td>")
html.print("<td><nobr>&nbsp;<input type=submit name=")
if val == "_add" then
html.print("port_add value=Add title='Add this as a port forwarding rule'")
else
html.print("port" .. val .. "_del value=Del title='Remove this rule'")
end
html.print("></nobr></td></tr>")
-- display any errors
while #port_err > 0 and port_err[1]:match("^" .. val .. " ")
do
local err = port_err[1]:gsub("^%S+ ", "")
html.print("<tr><th colspan=7>" .. err .. "</th></tr>")
table.remove(port_err, 1)
end
html.print("<tr><td colspan=6 height=5></td></tr>")
end
-- dmz server for nat mode
if dmz_mode == 0 then
html.print("<tr><td colspan=7 height=10></td></tr>")
html.print("<tr><td colspan=4 align=right>DMZ Server &nbsp; </td>")
html.print("<td colspan=3><select name=dmz_ip onChange='form.submit()' ")
html.print("title='Send all other inbound traffic to this host'>")
html.print("<option value=''>None</option>")
local lanlimit = nixio.bit.lshift(1, 32 - netmask_to_cidr(lanmask)) - 2
for i = 1,lanlimit
do
local selip = decimal_to_ip(lannet_d + i)
if selip ~= lanip then
local ipname = dhcphosts[selip]
if not ipname then
ipname = selip
end
html.print("<option " .. (parms.dmz_ip == selip and "selected" or "") .. " value='" .. selip .. "'>" .. ipname .. "</option>")
end
end
html.print("</select></td>")
for _, e in ipairs(dmz_err)
do
html.print("<tr><th colspan=8>" .. e .. "</th></tr>")
end
end
html.print("</table>")
end
function print_services()
local activesvc = nil
if nixio.fs.stat("/var/etc/olsrd.conf") then
activesvc = {}
for line in io.lines("/var/etc/olsrd.conf")
do
local plparam = line:match([[^%s*(PlParam "service" ".*")%s*$]])
if plparam then
activesvc[plparam] = true
end
end
end
html.print("<table cellpadding=0 cellspacing=0><tr><th colspan=4>Advertised Services</th></tr>")
if not (dmz_mode ~= 0 or parms.port_num ~= 0 or parms.dmz_ip) then
if dmz_mode ~= 0 then
html.print("<tr><td>&nbsp;</td></tr><tr><td height=10></td></tr>")
else
html.print("<tr><td>&nbsp;<br><br></td></tr>")
end
html.print("<tr><td colspan=4 align=center>none</td></tr>")
html.print("</table>")
return;
end
if dmz_mode ~= 0 then
html.print("<tr><td height=5></td></tr>")
html.print("<tr><td>Name</td><td>Link</td><td>URL</td><td></td></tr>")
html.print("<tr><td height=5></td></tr>")
else
html.print("<tr><td>Name</td><td>Link</td><td>URL</td><td><br><br></td></tr>")
end
local list = {}
for i = 1,parms.serv_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
local vars = { "_name", "_link", "_proto", "_host", "_port", "_suffix" }
for _, val in ipairs(list)
do
for _, var in ipairs(vars)
do
_G[var] = parms["serv" .. val .. var]
end
if dmz_mode == 0 then
_host = node
parms["serv" .. val .. "_host"] = node
end
if val == "_add" and #list > 1 then
html.print("<tr><td colspan=4 height=10></td></tr>")
end
html.print("<tr>")
html.print("<td><input type=text style='width:120;' name=serv" .. val .. "_name value='" .. _name .. "' title='what to call this service'></td>")
html.print("<td><nobr><input type=checkbox name=serv" .. val .. "_link value=1")
if val ~= "_add" then
html.print(" onChange='form.submit()'")
end
if _link == "1" then
html.print(" checked")
end
html.print(" title='create a clickable link for this service'>")
html.print("<input type=text style='width:40;' name=serv" .. val .. "_proto value='" .. _proto .. "' title='URL Protocol'")
if val ~= "_add" and _link ~= "1" then
html.print(" disabled")
end
html.print("></nobr></td>")
if dmz_mode ~= 0 then
html.print("<td><nobr><b>:</b>//<select name=serv" .. val .. "_host")
if val ~= "_add" and _link ~= "1" then
html.print(" disabled")
end
html.print(">")
html.print("<option " .. (node == _host and "selected" or "") .. " value='" .. node .. "'>" .. node .. "</option>")
for i = 1,parms.alias_num
do
html.print("<option " .. (parms["alias" .. i .. "_host"] == _host and "selected" or "") .. " value='" .. parms["alias" .. i .. "_host"] .. "'>" .. parms["alias" .. i .. "_host"] .. "</option>")
end
for i = 1,parms.dhcp_num
do
html.print("<option " .. (parms["dhcp" .. i .. "_host"] == _host and "selected" or "") .. " value='" .. parms["dhcp" .. i .. "_host"] .. "'>" .. parms["dhcp" .. i .. "_host"] .. "</option>")
end
html.print("</select>")
else
html.print("<td><nobr><b>:</b>//<small>" .. _host .. "</small>")
end
html.print("<b>:</b><input type=text style='width:40;' name=serv" .. val .. "_port value='" .. _port .. "' title='port number'")
if val ~= "_add" and _link ~= "1" then
html.print(" disabled")
end
html.print("> / <input type=text style='width:80;' name=serv" .. val .. "_suffix value='" .. _suffix .. "' ")
html.print("title='leave blank unless the URL needs a more specific path'")
if val ~= "_add" and _link ~= "1" then
html.print(" disabled")
end
html.print("></nobr></td>")
html.print("<td><nobr>&nbsp;<input type=submit name=")
if val == "_add" then
html.print("serv_add value=Add title='Add this as a service'>")
else
html.print("serv" .. val .. "_del value=Del title='Remove this service'>")
end
local svc = string.format([[PlParam "service" "%s://%s:%s/%s|tcp|%s"]], (_link == "1" and _proto or "http"), _host, (_link == "1" and _port or "0"), _suffix, _name)
if val ~= "_add" and activesvc and not activesvc[svc] then
2022-07-31 13:12:17 -06:00
html.print("<img style='vertical-align:middle' src='/alert-circle-outline.png' title='Service is not being advertised'>")
end
html.print("</nobr></td></tr>")
-- display any errors
while #serv_err > 0 and serv_err[1]:match("^" .. val .. " ")
do
html.print("<tr><th colspan=4>" .. serv_err[1]:gsub("^%S+ ", "") .. "</th></tr>")
table.remove(serv_err, 1)
end
if _link ~= "1" and val ~= "_add" then
hide("<input type=hidden name=serv" .. val .. "_proto value='" .. _proto .. "'>")
hide("<input type=hidden name=serv" .. val .. "_host value='" .. _host .. "'>")
hide("<input type=hidden name=serv" .. val .. "_port value='" .. _port .. "'>")
hide("<input type=hidden name=serv" .. val .. "_suffix value='" .. _suffix .. "'>")
end
html.print("<tr><td colspan=4 height=4></td></tr>")
end
html.print("</table>")
end
function print_aliases()
html.print("<table cellpadding=0 cellspacing=0><tr><th colspan=4>DNS Aliases</th></tr>")
html.print("<tr><td colspan=3 height=5></td></tr>")
html.print("<tr><td align=center>Alias Name</td><td></td><td align=center>IP Address</td></tr>")
html.print("<tr><td colspan=3 height=5></td></tr>")
local list = {}
for i = 1,parms.alias_num
do
list[#list + 1] = i
end
list[#list + 1] = "_add"
for _, val in ipairs(list)
do
local host = parms["alias" .. val .. "_host"]
local ip = parms["alias" .. val .. "_ip"]
if val == "_add" and #list > 1 then
html.print("<tr><td colspan=3 height=10></td></tr>\n")
end
html.print("<tr><td align=center><input type=text name=alias" .. val .. "_host value='" .. host .. "' size=20></td>")
html.print("<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>")
html.print("<td align=center><select name=alias" .. val .. "_ip>")
if val == "_add" then
html.print("<option value=''>- IP Address -</option>")
end
for i = dhcp_start,dhcp_end
do
local selip = decimal_to_ip(lannet_d + i - lannet_d % 256)
if selip ~= lanip then
local ipname = dhcphosts[selip]
if not ipname then
ipname = selip
end
html.print("<option " .. (ip == selip and "selected" or "") .. " value='" .. selip .. "'>" .. ipname .. "</option>")
end
end
html.print("</select></td>")
html.print("<td><nobr>&nbsp;<input type=submit name=")
if val == "_add" then
html.print("alias_add value=Add title='Add Alias'")
else
html.print("alias" .. val .. "_del value=Del title='Remove Alias'")
end
html.print("></nobr></td></tr>")
end
for _, e in ipairs(alias_err)
do
html.print("<tr><th colspan=4>" .. e:gsub("^%S+ ", "") .. "</th></tr>")
end
html.print("</table>")
end
html.print("<tr><td align=center>")
html.print("<table width=100%><tr><td align=center valign=top>")
if dmz_mode ~= 0 then
print_reservations()
else
print_forwarding()
end
html.print("</td>")
html.print("<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>")
html.print("<td align=center valign=top>")
print_services()
html.print("</td>")
html.print("</tr>")
html.print("<tr><td colspan=3><hr></td></tr>")
html.print("<tr><td align=center valign=top>")
if dmz_mode ~= 0 then
print_forwarding()
else
print_reservations()
end
html.print("</td>")
html.print("<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>")
html.print("<td align=center valign=top>")
print_aliases()
html.print("</td></tr>")
html.print("</table>")
hide("<input type=hidden name=port_num value=" .. parms.port_num .. ">")
hide("<input type=hidden name=dhcp_num value=" .. parms.dhcp_num .. ">")
hide("<input type=hidden name=serv_num value=" .. parms.serv_num .. ">")
hide("<input type=hidden name=alias_num value=" .. parms.alias_num .. ">")
for _, h in ipairs(hidden)
do
html.print(h)
end
html.print("<tr><td>")
html.footer()
html.print(" </td></tr>")
html.print("</form></center></table>")
html.print("</body></html>")
http_footer()