mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-30 07:59:35 +00:00
378 lines
13 KiB
Lua
378 lines
13 KiB
Lua
--
|
|
-- (C) 2020 - ntop.org
|
|
--
|
|
|
|
local dirs = ntop.getDirs()
|
|
package.path = dirs.installdir .. "/scripts/lua/modules/system_config/?.lua;" .. package.path
|
|
package.path = dirs.installdir .. "/pro/scripts/lua/modules/?.lua;" .. package.path
|
|
require "lua_utils"
|
|
local system_config = require "system_config"
|
|
local json = require "dkjson"
|
|
local ipv4_utils = require "ipv4_utils"
|
|
local os_utils = require "os_utils"
|
|
local sys_utils = require "sys_utils"
|
|
local tz_utils = require "tz_utils"
|
|
|
|
-- ##############################################
|
|
|
|
-- Example
|
|
-- package.path = dirs.installdir .. "/scripts/lua/modules/system_config/?.lua;" .. package.path
|
|
-- -- Editable
|
|
-- local appliance_config = require "appliance_config":create(true)
|
|
-- -- Readable
|
|
-- local appliance_config = require "appliance_config":create()
|
|
|
|
-- ##############################################
|
|
|
|
local appliance_config = {}
|
|
|
|
-- ##############################################
|
|
|
|
function appliance_config:create(editable)
|
|
-- Instance of the base class
|
|
local _system_config = system_config:create()
|
|
|
|
-- Subclass using the base class instance
|
|
self.key = "appliance"
|
|
-- self is passed as argument so it will be set as base class metatable
|
|
-- and this will actually make it possible to override functions
|
|
local _appliance_config = _system_config:create(self)
|
|
|
|
if editable then
|
|
_appliance_config:editable()
|
|
else
|
|
_appliance_config:readable()
|
|
end
|
|
|
|
-- Return the instance
|
|
return _appliance_config
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function appliance_config:_get_config_skeleton()
|
|
local config = {}
|
|
local defaults = { }
|
|
local default_global_dns = self:_get_default_global_dns_preset()
|
|
|
|
local config = {
|
|
["defaults"] = defaults,
|
|
["disabled_wans"] = {},
|
|
["globals"] = {
|
|
["available_modes"] = {},
|
|
["dns"] = {
|
|
["global_preset"] = default_global_dns.id,
|
|
["global"] = default_global_dns.primary_dns,
|
|
["secondary"] = default_global_dns.secondary_dns,
|
|
["forge_global"] = false
|
|
},
|
|
["lan_recovery_ip"] = {
|
|
["ip"] = "192.168.160.10",
|
|
["netmask"] = "255.255.255.0",
|
|
["comment"] = "Static LAN IP address used to reach the box. In bridging mode it is set on the bridge interface, in routing mode on the first (in case of multiple interfaces) LAN interface"
|
|
},
|
|
["management_access"] = {
|
|
["bind_to"] = "lan",
|
|
},
|
|
},
|
|
["interfaces"] = {
|
|
["comment"]= "List of available network interfaces. Only those listed in globals.operating_mode are actually configured",
|
|
["configuration"] = {}
|
|
},
|
|
["gateways"] = {
|
|
},
|
|
["static_routes"] = {
|
|
},
|
|
["date_time"] = {
|
|
["ntp_sync"] = {
|
|
["enabled"] = true,
|
|
},
|
|
["timezone"] = "Europe/Rome",
|
|
},
|
|
["dhcp_server"] = {
|
|
["enabled"] = false,
|
|
["options"] = {
|
|
"ddns-update-style none",
|
|
"log-facility local7",
|
|
"authoritative"
|
|
},
|
|
["subnet"] = {
|
|
["network"] = "192.168.1.0",
|
|
["netmask"] = "255.255.255.0",
|
|
["first_ip"] = "192.168.1.10",
|
|
["last_ip"] = "192.168.1.200",
|
|
["gateway"] = "192.168.1.1",
|
|
["broadcast"] = "192.168.1.255",
|
|
["options"] = {
|
|
"option domain-name \"ntop.local\"",
|
|
"default-lease-time 600",
|
|
"max-lease-time 7200"
|
|
}
|
|
},
|
|
["leases"] = {}
|
|
}
|
|
}
|
|
return config
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
function appliance_config:_guess_config()
|
|
local config = self:_get_config_skeleton()
|
|
local devs = { }
|
|
local wifi = { }
|
|
local bridge = { }
|
|
local wired = { }
|
|
local dhcp_ifaces = {}
|
|
local wired_default = nil
|
|
local wifi_default = nil
|
|
local ip_devs = system_config._split_dev_names('ip addr | awk \'$1 == "inet" && $7 { split( $2, addr, "/" ); print $7, addr[1] }\'', " ")
|
|
local devs = system_config._split_dev_names('cat /proc/net/dev', ":")
|
|
local wifi_devs = system_config._split_dev_names('cat /proc/net/wireless', ":")
|
|
local lan_iface
|
|
local wan_iface = nil
|
|
|
|
-- set the timezone to the current system timezone
|
|
|
|
if not isEmptyString(tz_utils.TimeZone()) then
|
|
config["date_time"]["timezone"] = tz_utils.TimeZone()
|
|
end
|
|
|
|
-- Necessary for inactive wifi devices
|
|
for dev in pairs(devs) do
|
|
local rv = sys_utils.execShellCmd("iwconfig 2>/dev/null | grep \"" .. dev .. "\" | grep \"IEEE 802.11\"")
|
|
if not isEmptyString(rv) then
|
|
wifi_devs[dev] = 1
|
|
end
|
|
end
|
|
|
|
-- Find DHCP interface
|
|
local res = sys_utils.execShellCmd('ps aux | grep dhclient')
|
|
if not isEmptyString(res) then
|
|
for _, line in pairs(split(res, "\n")) do
|
|
local name = line:gmatch(".([^.]+).leases")()
|
|
|
|
if devs[name] ~= nil then
|
|
dhcp_ifaces[name] = 1
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Find the wan interface
|
|
local rv = sys_utils.execShellCmd("ip route show | grep \"default via\" | awk '{printf \"%s\", $5}'")
|
|
if not isEmptyString(rv) and devs[rv] ~= nil then
|
|
wan_iface = rv
|
|
end
|
|
|
|
local some_wired = nil
|
|
local static_wired = nil
|
|
|
|
-- Identify the type of the devices in the system
|
|
-- NOTE: we use pairsByKeys to impose an order across multiple guesses
|
|
for name, _ in pairsByKeys(devs) do
|
|
local addr = ip_devs[name]
|
|
-- print("==> "..tostring(name).."\n")
|
|
|
|
-- Not TUN/dummy/lo interface
|
|
if((name ~= "lo") and (not starts(name, "dummy")) and not(ntop.exists('/sys/class/net/'.. name ..'/tun_flags')) and not string.contains(name, ":")) then
|
|
if(ntop.exists('/sys/class/net/'.. name ..'/bridge')) then
|
|
local devs = system_config._split_dev_names('ls /sys/class/net/'.. name ..'/brif/', nil)
|
|
|
|
bridge[name] = { ["ports"] = devs }
|
|
if(addr ~= nil) then bridge[name]["ip"] = addr end
|
|
elseif(wifi_devs[name] ~= nil) then
|
|
wifi[name] = { }
|
|
if(addr ~= nil) then wifi[name]["ip"] = addr end
|
|
if(wifi_default == nil) then wifi_default = name end
|
|
else
|
|
-- Add per-interface gateway
|
|
config.gateways[name] = {interface=name, ping_address="8.8.8.8"}
|
|
|
|
wired[name] = { }
|
|
if(some_wired == nil) then some_wired = name end
|
|
if((name ~= wan_iface) and (dhcp_ifaces[name] == nil) and (static_wired == nil)) then static_wired = name end
|
|
|
|
if(addr ~= nil) then
|
|
wired[name]["ip"] = addr
|
|
end
|
|
|
|
-- print("[WIRED] ==> "..name.."\n")
|
|
end
|
|
end
|
|
end
|
|
|
|
wired_default = static_wired or some_wired
|
|
|
|
-- TODO modify this after supporting the other modes:
|
|
-- e.g. for bridge interface the lan should be br0
|
|
lan_iface = wired_default
|
|
|
|
-- ###################
|
|
-- Bridge interfaces
|
|
|
|
local bridging = {}
|
|
local operating_mode = nil
|
|
local bridging_defined = false
|
|
local bridge_ifname = nil
|
|
|
|
-- If we currently have a bridge interface, use its configuration
|
|
if table.len(bridge) > 0 then
|
|
local used_ifaces = {}
|
|
|
|
for a,b in pairsByKeys(bridge) do
|
|
if table.len(b.ports) > 1 then
|
|
bridge_ifname = a
|
|
bridging["name"] = a
|
|
bridging["interfaces"] = {unused={}}
|
|
bridging["comment"] = "Transparent bridge"
|
|
|
|
bridging["interfaces"]["lan"] = {}
|
|
bridging["interfaces"]["wan"] = {}
|
|
|
|
for n,c in pairsByKeys(b.ports) do
|
|
if(n == 1) then
|
|
table.insert(bridging["interfaces"]["lan"], c)
|
|
else
|
|
table.insert(bridging["interfaces"]["wan"], c)
|
|
end
|
|
used_ifaces[c] = true
|
|
end
|
|
|
|
operating_mode = "bridging"
|
|
bridging_defined = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if bridging_defined then
|
|
-- add other interfaces to the unused ones
|
|
for iface,_ in pairsByKeys(wired) do
|
|
if used_ifaces[iface] == nil then
|
|
table.insert(bridging["interfaces"]["unused"], iface)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- If we do not have a bridge interface but have enough interfaces
|
|
if((not bridging_defined) and(table.len(wired) > 1)) then
|
|
local n = 0
|
|
bridge_ifname = "br0"
|
|
|
|
bridging["name"] = bridge_ifname
|
|
bridging["interfaces"] = {unused={}}
|
|
bridging["comment"] = "Transparent bridge"
|
|
|
|
for a,b in pairsByKeys(wired) do
|
|
if(n == 0) then
|
|
bridging["interfaces"]["lan"] = { a }
|
|
elseif(n == 1) then
|
|
bridging["interfaces"]["wan"] = { a }
|
|
else
|
|
table.insert(bridging["interfaces"]["unused"], a)
|
|
end
|
|
|
|
n = n + 1
|
|
end
|
|
|
|
bridging_defined = true
|
|
end
|
|
|
|
if(bridging_defined) then
|
|
config["globals"]["available_modes"]["bridging"] = bridging
|
|
end
|
|
|
|
-- ###################
|
|
|
|
-- TODO standard or bridging
|
|
operating_mode = "bridging"
|
|
|
|
if(operating_mode ~= nil) then
|
|
config["globals"]["operating_mode"] = operating_mode
|
|
end
|
|
|
|
-- ###################
|
|
-- Network configuration
|
|
|
|
for a,b in pairs(wired) do
|
|
local speed = (interface.getMaxIfSpeed(a) or 10) * 1000 -- Mbps to Kbps that are more tc-friendly :)
|
|
|
|
config["interfaces"]["configuration"][a] = {
|
|
["family"] = "wired", ["masquerade"] = true, ["network"] = { },
|
|
["speed"] = {["upload"] = speed, ["download"] = speed} }
|
|
|
|
-- Note: we force static on the wired_default if not in bridging mode
|
|
if dhcp_ifaces[a] and ((a ~= wired_default) or (operating_mode == "bridging")) then
|
|
config["interfaces"]["configuration"][a]["network"]["mode"] = "dhcp"
|
|
config["interfaces"]["configuration"][a]["network"]["ip"] = "192.168.10.1"
|
|
config["interfaces"]["configuration"][a]["network"]["netmask"] = "255.255.255.0"
|
|
config["interfaces"]["configuration"][a]["network"]["gateway"] = "0.0.0.0"
|
|
else
|
|
-- non DHCP interface / wired_default
|
|
config["interfaces"]["configuration"][a]["network"]["mode"] = "static"
|
|
|
|
local netmask
|
|
|
|
if (ip_devs[a] == nil) then
|
|
-- e.g. on the wired_default
|
|
ip_devs[a] = "192.168.1.1"
|
|
netmask = "255.255.255.0"
|
|
else
|
|
-- The device has an IP address
|
|
local addresses = getAllInterfaceAddresses(a)
|
|
for _, addr in pairs(addresses) do
|
|
if addr.ip == ip_devs[a] then
|
|
netmask = addr.netmask
|
|
end
|
|
end
|
|
|
|
if isEmptyString(netmask) then netmask = "255.255.255.0" end
|
|
end
|
|
|
|
local gateway = system_config._interface_get_default_gateway(a)
|
|
config["interfaces"]["configuration"][a]["network"]["ip"] = ip_devs[a]
|
|
config["interfaces"]["configuration"][a]["network"]["netmask"] = netmask
|
|
|
|
if not isEmptyString(gateway) then
|
|
config["interfaces"]["configuration"][a]["network"]["gateway"] = gateway
|
|
end
|
|
end
|
|
end
|
|
|
|
if(wired_default ~= nil) then
|
|
-- Add the aliased interface to the configuration
|
|
config["interfaces"]["configuration"][wired_default..":1"] = { ["family"] = "wired", ["network"]={},
|
|
["speed"] = {["upload"]= speed, ["download"] = speed} }
|
|
config["interfaces"]["configuration"][wired_default..":1"]["network"]["mode"] = "static"
|
|
config["interfaces"]["configuration"][wired_default..":1"]["network"]["ip"] = "192.168.10.1"
|
|
config["interfaces"]["configuration"][wired_default..":1"]["network"]["netmask"] = "255.255.255.0"
|
|
end
|
|
|
|
if(bridge_ifname ~= nil) then
|
|
local speed = 100 * 1000 -- Kbps, not really important here
|
|
|
|
-- Add the bridge interface to the configuration
|
|
config["interfaces"]["configuration"][bridge_ifname] = { ["family"] = "bridge", ["network"]={},
|
|
["speed"] = {["upload"]= speed, ["download"] = speed} }
|
|
config["interfaces"]["configuration"][bridge_ifname]["network"]["mode"] = "dhcp"
|
|
config["interfaces"]["configuration"][bridge_ifname]["network"]["ip"] = "192.168.20.1"
|
|
config["interfaces"]["configuration"][bridge_ifname]["network"]["netmask"] = "255.255.255.0"
|
|
end
|
|
|
|
-- Not supported right now
|
|
--for a,b in pairs(wifi) do
|
|
--config["interfaces"]["configuration"][a] = { ["family"] = "wireless", ["network"] = { ["mode"] = "dhcp" } }
|
|
--end
|
|
|
|
-- Make sure we have a valid DHCP range
|
|
self:_fix_dhcp_from_lan(config, lan_iface)
|
|
|
|
-- Make sure to apply the mode specific settings
|
|
self:_apply_operating_mode_settings(config)
|
|
|
|
return config
|
|
end
|
|
|
|
-- ##############################################
|
|
|
|
return appliance_config
|