#580 supervisor wired/wireless dual networking

This commit is contained in:
Mikayla Fischler 2025-10-19 17:30:05 -04:00
parent 4d6c388f37
commit fc24f39991
4 changed files with 300 additions and 218 deletions

View File

@ -17,7 +17,7 @@ local max_distance = nil
local comms = {}
-- protocol/data versions (protocol/data independent changes tracked by util.lua version)
comms.version = "3.0.8"
comms.version = "3.0.9"
comms.api_version = "0.0.10"
---@enum PROTOCOL
@ -49,13 +49,14 @@ local MGMT_TYPE = {
ESTABLISH = 0, -- establish new connection
KEEP_ALIVE = 1, -- keep alive packet w/ RTT
CLOSE = 2, -- close a connection
RTU_ADVERT = 3, -- RTU capability advertisement
RTU_DEV_REMOUNT = 4, -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
RTU_TONE_ALARM = 5, -- instruct RTUs to play specified alarm tones
DIAG_TONE_GET = 6, -- (API) diagnostic: get alarm tones
DIAG_TONE_SET = 7, -- (API) diagnostic: set alarm tones
DIAG_ALARM_SET = 8, -- (API) diagnostic: set alarm to simulate audio for
INFO_LIST_CMP = 9 -- (API) info: list all computers on the network
PROBE = 3,
RTU_ADVERT = 4, -- RTU capability advertisement
RTU_DEV_REMOUNT = 5, -- RTU multiblock possbily changed (formed, unformed) due to PPM remount
RTU_TONE_ALARM = 6, -- instruct RTUs to play specified alarm tones
DIAG_TONE_GET = 7, -- (API) diagnostic: get alarm tones
DIAG_TONE_SET = 8, -- (API) diagnostic: set alarm tones
DIAG_ALARM_SET = 9, -- (API) diagnostic: set alarm to simulate audio for
INFO_LIST_CMP = 10 -- (API) info: list all computers on the network
}
---@enum CRDN_TYPE
@ -89,6 +90,12 @@ local ESTABLISH_ACK = {
---@enum DEVICE_TYPE device types for establish messages
local DEVICE_TYPE = { PLC = 0, RTU = 1, SVR = 2, CRD = 3, PKT = 4 }
---@enum PROBE_ACK
local PROBE_ACK = {
OPEN = 0,
CONFLICT = 1
}
---@enum PLC_AUTO_ACK
local PLC_AUTO_ACK = {
FAIL = 0, -- failed to set burn rate/burn rate invalid
@ -130,6 +137,8 @@ comms.CRDN_TYPE = CRDN_TYPE
comms.ESTABLISH_ACK = ESTABLISH_ACK
comms.DEVICE_TYPE = DEVICE_TYPE
comms.PROBE_ACK = PROBE_ACK
comms.PLC_AUTO_ACK = PLC_AUTO_ACK
comms.UNIT_COMMAND = UNIT_COMMAND

View File

@ -82,7 +82,9 @@ end
function network.nic(modem)
local self = {
-- modem interface name
iface = ppm.get_iface(modem),
iface = "?",
-- phy name
name = "?",
-- used to quickly return out of tx/rx functions if there is nothing to do
connected = true,
-- used to avoid costly MAC calculations if not required
@ -94,6 +96,10 @@ function network.nic(modem)
---@class nic:Modem
local public = {}
-- get the phy name
---@nodiscard
function public.phy_name() return self.name end
-- check if this NIC has a connected modem
---@nodiscard
function public.is_connected() return self.connected end
@ -102,11 +108,14 @@ function network.nic(modem)
---@param reconnected_modem Modem
function public.connect(reconnected_modem)
modem = reconnected_modem
self.iface = ppm.get_iface(modem)
self.name = util.c(util.trinary(modem.isWireless(), "WLAN_PHY", "ETH_PHY"), "{", self.iface, "}")
self.connected = true
self.use_hash = c_eng.hmac and modem.isWireless()
-- open only previously opened channels
modem.closeAll()
-- open previously opened channels
for _, channel in ipairs(self.channels) do
modem.open(channel)
end

View File

@ -18,7 +18,7 @@ local _bp = {
wd_nic = nil, ---@type nic|nil wired nic
wl_nic = nil, ---@type nic|nil wireless nic
nic_map = {}
nic_map = {} ---@type nic[] connected nics
}
backplane.nics = _bp.nic_map

View File

@ -10,10 +10,11 @@ local svsessions = require("supervisor.session.svsessions")
local supervisor = {}
local PROTOCOL = comms.PROTOCOL
local DEVICE_TYPE = comms.DEVICE_TYPE
local PROTOCOL = comms.PROTOCOL
local DEVICE_TYPE = comms.DEVICE_TYPE
local ESTABLISH_ACK = comms.ESTABLISH_ACK
local MGMT_TYPE = comms.MGMT_TYPE
local PROBE_ACK = comms.PROBE_ACK
local MGMT_TYPE = comms.MGMT_TYPE
---@type svr_config
---@diagnostic disable-next-line: missing-fields
@ -156,14 +157,11 @@ function supervisor.comms(_version, fp_ok, facility)
local function println(message) if not fp_ok then util.println_ts(message) end end
local self = {
last_est_acks = {}
last_est_acks = {} ---@type ESTABLISH_ACK[]
}
comms.set_trusted_range(config.TrustedRange)
-- configure network channels
pcie.nic.reset_open(config)
-- pass system data and objects to svsessions
svsessions.init(fp_ok, config, facility)
@ -175,8 +173,7 @@ function supervisor.comms(_version, fp_ok, facility)
---@param ack ESTABLISH_ACK
---@param data? any optional data
local function _send_establish(nic, packet, ack, data)
local s_pkt = comms.scada_packet()
local m_pkt = comms.mgmt_packet()
local s_pkt, m_pkt = comms.scada_packet(), comms.mgmt_packet()
m_pkt.make(MGMT_TYPE.ESTABLISH, { ack, data })
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
@ -185,6 +182,188 @@ function supervisor.comms(_version, fp_ok, facility)
self.last_est_acks[packet.src_addr()] = ack
end
-- send a probe response
---@param nic nic
---@param packet scada_packet
---@param ack PROBE_ACK
local function _send_probe(nic, packet, ack)
local s_pkt, m_pkt = comms.scada_packet(), comms.mgmt_packet()
m_pkt.make(MGMT_TYPE.PROBE, { ack })
s_pkt.make(packet.src_addr(), packet.seq_num() + 1, PROTOCOL.SCADA_MGMT, m_pkt.raw_sendable())
nic.transmit(packet.remote_channel(), config.SVR_Channel, s_pkt)
end
--#region Establish Handlers
-- handle a PLC establish
---@param nic nic
---@param packet mgmt_frame
---@param src_addr integer
---@param i_seq_num integer
---@param last_ack ESTABLISH_ACK
local function _establish_plc(nic, packet, src_addr, i_seq_num, last_ack)
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping PLC establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.PLC then
-- PLC linking request
if packet.length == 4 and type(packet.data[4]) == "number" then
local reactor_id = packet.data[4]
-- check ID validity
if reactor_id < 1 or reactor_id > config.UnitCount then
-- reactor index out of range
if last_ack ~= ESTABLISH_ACK.DENY then
log.warning(util.c("PLC_ESTABLISH: denied assignment ", reactor_id, " outside of configured unit count ", config.UnitCount))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
else
-- try to establish the session
local plc_id = svsessions.establish_plc_session(nic, src_addr, i_seq_num, reactor_id, firmware_v)
if plc_id == false then
-- reactor already has a PLC assigned
if last_ack ~= ESTABLISH_ACK.COLLISION then
log.warning(util.c("PLC_ESTABLISH: assignment collision with reactor ", reactor_id))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.COLLISION)
else
-- got an ID; assigned to a reactor successfully
println(util.c("PLC (", firmware_v, ") [@", src_addr, "] \xbb reactor ", reactor_id, " connected"))
log.info(util.c("PLC_ESTABLISH: PLC (", firmware_v, ") [@", src_addr, "] reactor unit ", reactor_id, " PLC connected with session ID ", plc_id, " on ", nic.phy_name()))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
end
end
else
log.debug("PLC_ESTABLISH: packet length mismatch/bad parameter type")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on PLC channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
end
-- handle an RTU gateway establish
---@param nic nic
---@param packet mgmt_frame
---@param src_addr integer
---@param i_seq_num integer
---@param last_ack ESTABLISH_ACK
local function _establish_rtu_gw(nic, packet, src_addr, i_seq_num, last_ack)
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping RTU_GW establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.RTU then
if packet.length == 4 then
-- this is an RTU advertisement for a new session
local rtu_advert = packet.data[4]
local s_id = svsessions.establish_rtu_session(nic, src_addr, i_seq_num, rtu_advert, firmware_v)
println(util.c("RTU (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("RTU_GW_ESTABLISH: RTU_GW (",firmware_v, ") [@", src_addr, "] connected with session ID ", s_id, " on ", nic.phy_name()))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
else
log.debug("RTU_GW_ESTABLISH: packet length mismatch")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on RTU channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
end
-- handle a coordinator establish
---@param nic nic
---@param packet mgmt_frame
---@param src_addr integer
---@param i_seq_num integer
---@param last_ack ESTABLISH_ACK
local function _establish_crd(nic, packet, src_addr, i_seq_num, last_ack)
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping coordinator establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.CRD then
-- this is an attempt to establish a new coordinator session
local s_id = svsessions.establish_crd_session(nic, src_addr, i_seq_num, firmware_v)
if s_id ~= false then
println(util.c("CRD (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("CRD_ESTABLISH: CRD (", firmware_v, ") [@", src_addr, "] connected with session ID ", s_id, " on ", nic.phy_name()))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW, { config.UnitCount, facility.get_cooling_conf() })
else
if last_ack ~= ESTABLISH_ACK.COLLISION then
log.info("CRD_ESTABLISH: denied new coordinator [@" .. src_addr .. "] due to already being connected to another coordinator")
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.COLLISION)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on CRD channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
end
-- handle a pocket debug establish
---@param nic nic
---@param packet mgmt_frame
---@param src_addr integer
---@param i_seq_num integer
---@param last_ack ESTABLISH_ACK
local function _establish_pdg(nic, packet, src_addr, i_seq_num, last_ack)
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping PKT establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.PKT then
-- this is an attempt to establish a new pocket diagnostic session
local s_id = svsessions.establish_pdg_session(nic, src_addr, i_seq_num, firmware_v)
println(util.c("PKT (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("PDG_ESTABLISH: pocket (", firmware_v, ") [@", src_addr, "] connected with session ID ", s_id, " on ", nic.phy_name()))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on PKT channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
end
--#endregion
-- PUBLIC FUNCTIONS --
---@class superv_comms
@ -240,89 +419,45 @@ function supervisor.comms(_version, fp_ok, facility)
local protocol = packet.scada_frame.protocol()
local i_seq_num = packet.scada_frame.seq_num()
if not nic then
log.error("received packet from unconfigured interface " .. packet.scada_frame.interface(), true)
elseif l_chan ~= config.SVR_Channel then
if l_chan ~= config.SVR_Channel then
log.debug("received packet on unconfigured channel " .. l_chan, true)
elseif r_chan == config.PLC_Channel then
-- look for an associated session
local session = svsessions.find_plc_session(src_addr)
if protocol == PROTOCOL.RPLC then
---@cast packet rplc_frame
-- reactor PLC packet
if session ~= nil then
if session then
if nic ~= session.nic then
-- this is from the same device but on a different interface
-- drop unless it is a connection probe
if (protocol == PROTOCOL.SCADA_MGMT) and (packet.type == MGMT_TYPE.PROBE) then
---@cast packet mgmt_frame
log.debug(util.c("PROBE_ACK: conflict with PLC @", src_addr, " on ", session.nic.phy_name(), " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.CONFLICT)
else
log.debug(util.c("unexpected packet for PLC @ ", src_addr, " received on ", nic.phy_name()))
end
else
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
else
-- any other packet should be session related, discard it
log.debug("discarding RPLC packet without a known session")
end
elseif protocol == PROTOCOL.RPLC then
-- reactor PLC packet should be session related, discard it
log.debug("discarding RPLC packet without a known session")
elseif protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
-- SCADA management packet
if session ~= nil then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
elseif packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session
local last_ack = self.last_est_acks[src_addr]
-- validate packet and continue
if packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session: validate packet and continue
if packet.length >= 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping PLC establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.PLC then
-- PLC linking request
if packet.length == 4 and type(packet.data[4]) == "number" then
local reactor_id = packet.data[4]
-- check ID validity
if reactor_id < 1 or reactor_id > config.UnitCount then
-- reactor index out of range
if last_ack ~= ESTABLISH_ACK.DENY then
log.warning(util.c("PLC_ESTABLISH: denied assignment ", reactor_id, " outside of configured unit count ", config.UnitCount))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
else
-- try to establish the session
local plc_id = svsessions.establish_plc_session(nic, src_addr, i_seq_num, reactor_id, firmware_v)
if plc_id == false then
-- reactor already has a PLC assigned
if last_ack ~= ESTABLISH_ACK.COLLISION then
log.warning(util.c("PLC_ESTABLISH: assignment collision with reactor ", reactor_id))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.COLLISION)
else
-- got an ID; assigned to a reactor successfully
println(util.c("PLC (", firmware_v, ") [@", src_addr, "] \xbb reactor ", reactor_id, " connected"))
log.info(util.c("PLC_ESTABLISH: PLC (", firmware_v, ") [@", src_addr, "] reactor unit ", reactor_id, " PLC connected with session ID ", plc_id))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
end
end
else
log.debug("PLC_ESTABLISH: packet length mismatch/bad parameter type")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on PLC channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
_establish_plc(nic, packet, src_addr, i_seq_num, self.last_est_acks[src_addr])
else
log.debug("invalid establish packet (on PLC channel)")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
elseif packet.type == MGMT_TYPE.PROBE then
-- connection probing
log.debug(util.c("PROBE_ACK: reporting open to PLC @", src_addr, " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.OPEN)
else
-- any other packet should be session related, discard it
log.debug(util.c("discarding PLC SCADA_MGMT packet without a known session from computer ", src_addr))
@ -334,62 +469,43 @@ function supervisor.comms(_version, fp_ok, facility)
-- look for an associated session
local session = svsessions.find_rtu_session(src_addr)
if protocol == PROTOCOL.MODBUS_TCP then
---@cast packet modbus_frame
-- MODBUS response
if session ~= nil then
if session then
if nic ~= session.nic then
-- this is from the same device but on a different interface
-- drop unless it is a connection probe
if (protocol == PROTOCOL.SCADA_MGMT) and (packet.type == MGMT_TYPE.PROBE) then
---@cast packet mgmt_frame
log.debug(util.c("PROBE_ACK: conflict with RTU_GW @", src_addr, " on ", session.nic.phy_name(), " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.CONFLICT)
else
log.debug(util.c("unexpected packet for RTU_GW @ ", src_addr, " received on ", nic.phy_name()))
end
else
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
else
-- any other packet should be session related, discard it
log.debug("discarding MODBUS_TCP packet without a known session")
end
elseif protocol == PROTOCOL.MODBUS_TCP then
---@cast packet modbus_frame
-- MODBUS response, should be session related, discard it
log.debug("discarding MODBUS_TCP packet without a known session")
elseif protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
-- SCADA management packet
if session ~= nil then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
elseif packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session
local last_ack = self.last_est_acks[src_addr]
-- validate packet and continue
if packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session: validate packet and continue
if packet.length >= 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping RTU establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.RTU then
if packet.length == 4 then
-- this is an RTU advertisement for a new session
local rtu_advert = packet.data[4]
local s_id = svsessions.establish_rtu_session(nic, src_addr, i_seq_num, rtu_advert, firmware_v)
println(util.c("RTU (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("RTU_ESTABLISH: RTU (",firmware_v, ") [@", src_addr, "] connected with session ID ", s_id))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
else
log.debug("RTU_ESTABLISH: packet length mismatch")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on RTU channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
_establish_rtu_gw(nic, packet, src_addr, i_seq_num, self.last_est_acks[src_addr])
else
log.debug("invalid establish packet (on RTU channel)")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
elseif packet.type == MGMT_TYPE.PROBE then
-- connection probing
log.debug(util.c("PROBE_ACK: reporting open to RTU_GW @", src_addr, " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.OPEN)
else
-- any other packet should be session related, discard it
log.debug(util.c("discarding RTU SCADA_MGMT packet without a known session from computer ", src_addr))
log.debug(util.c("discarding RTU gateway SCADA_MGMT packet without a known session from computer ", src_addr))
end
else
log.debug(util.c("illegal packet type ", protocol, " on RTU channel"))
@ -398,107 +514,61 @@ function supervisor.comms(_version, fp_ok, facility)
-- look for an associated session
local session = svsessions.find_crd_session(src_addr)
if protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
-- SCADA management packet
if session ~= nil then
if session then
if nic ~= session.nic then
-- this is from the same device but on a different interface
-- drop unless it is a connection probe
if (protocol == PROTOCOL.SCADA_MGMT) and (packet.type == MGMT_TYPE.PROBE) then
---@cast packet mgmt_frame
log.debug(util.c("PROBE_ACK: conflict with CRD @", src_addr, " on ", session.nic.phy_name(), " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.CONFLICT)
else
log.debug(util.c("unexpected packet for CRD @ ", src_addr, " received on ", nic.phy_name()))
end
else
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
elseif packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session
local last_ack = self.last_est_acks[src_addr]
-- validate packet and continue
end
elseif protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
-- SCADA management packet
if packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session: validate packet and continue
if packet.length >= 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping coordinator establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.CRD then
-- this is an attempt to establish a new coordinator session
local s_id = svsessions.establish_crd_session(nic, src_addr, i_seq_num, firmware_v)
if s_id ~= false then
println(util.c("CRD (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("CRD_ESTABLISH: coordinator (", firmware_v, ") [@", src_addr, "] connected with session ID ", s_id))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW, { config.UnitCount, facility.get_cooling_conf() })
else
if last_ack ~= ESTABLISH_ACK.COLLISION then
log.info("CRD_ESTABLISH: denied new coordinator [@" .. src_addr .. "] due to already being connected to another coordinator")
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.COLLISION)
end
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on coordinator channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
_establish_crd(nic, packet, src_addr, i_seq_num, self.last_est_acks[src_addr])
else
log.debug("CRD_ESTABLISH: establish packet length mismatch")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
elseif packet.type == MGMT_TYPE.PROBE then
-- connection probing
log.debug(util.c("PROBE_ACK: reporting open to CRD @", src_addr, " probed on ", nic.phy_name()))
_send_probe(nic, packet.scada_frame, PROBE_ACK.OPEN)
else
-- any other packet should be session related, discard it
log.debug(util.c("discarding coordinator SCADA_MGMT packet without a known session from computer ", src_addr))
end
elseif protocol == PROTOCOL.SCADA_CRDN then
---@cast packet crdn_frame
-- coordinator packet
if session ~= nil then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
else
-- any other packet should be session related, discard it
log.debug(util.c("discarding coordinator SCADA_CRDN packet without a known session from computer ", src_addr))
end
-- coordinator packet, should be session related, discard it
log.debug(util.c("discarding coordinator SCADA_CRDN packet without a known session from computer ", src_addr))
else
log.debug(util.c("illegal packet type ", protocol, " on coordinator channel"))
log.debug(util.c("illegal packet type ", protocol, " on CRD channel"))
end
elseif r_chan == config.PKT_Channel then
-- look for an associated session
local session = svsessions.find_pdg_session(src_addr)
if protocol == PROTOCOL.SCADA_MGMT then
if session then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
elseif protocol == PROTOCOL.SCADA_MGMT then
---@cast packet mgmt_frame
-- SCADA management packet
if session ~= nil then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
elseif packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session
local last_ack = self.last_est_acks[src_addr]
-- validate packet and continue
if packet.type == MGMT_TYPE.ESTABLISH then
-- establish a new session: validate packet and continue
if packet.length >= 3 and type(packet.data[1]) == "string" and type(packet.data[2]) == "string" then
local comms_v = packet.data[1]
local firmware_v = packet.data[2]
local dev_type = packet.data[3]
if comms_v ~= comms.version then
if last_ack ~= ESTABLISH_ACK.BAD_VERSION then
log.info(util.c("dropping PDG establish packet with incorrect comms version v", comms_v, " (expected v", comms.version, ")"))
end
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.BAD_VERSION)
elseif dev_type == DEVICE_TYPE.PKT then
-- this is an attempt to establish a new pocket diagnostic session
local s_id = svsessions.establish_pdg_session(nic, src_addr, i_seq_num, firmware_v)
println(util.c("PKT (", firmware_v, ") [@", src_addr, "] \xbb connected"))
log.info(util.c("PDG_ESTABLISH: pocket (", firmware_v, ") [@", src_addr, "] connected with session ID ", s_id))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.ALLOW)
else
log.debug(util.c("illegal establish packet for device ", dev_type, " on pocket channel"))
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
end
_establish_pdg(nic, packet, src_addr, i_seq_num, self.last_est_acks[src_addr])
else
log.debug("PDG_ESTABLISH: establish packet length mismatch")
_send_establish(nic, packet.scada_frame, ESTABLISH_ACK.DENY)
@ -509,14 +579,8 @@ function supervisor.comms(_version, fp_ok, facility)
end
elseif protocol == PROTOCOL.SCADA_CRDN then
---@cast packet crdn_frame
-- coordinator packet
if session ~= nil then
-- pass the packet onto the session handler
session.in_queue.push_packet(packet)
else
-- any other packet should be session related, discard it
log.debug(util.c("discarding pocket SCADA_CRDN packet without a known session from computer ", src_addr))
end
-- coordinator packet, should be session related, discard it
log.debug(util.c("discarding pocket SCADA_CRDN packet without a known session from computer ", src_addr))
else
log.debug(util.c("illegal packet type ", protocol, " on pocket channel"))
end