moved packet constructors and fixes to comms namespace references in plc comms code

This commit is contained in:
Mikayla Fischler 2022-04-21 10:26:02 -04:00
parent 04f8dc7d75
commit 4842f9cb0d
6 changed files with 153 additions and 139 deletions

View File

@ -1,6 +1,10 @@
-- #REQUIRES comms.lua
-- #REQUIRES ppm.lua
local PROTOCOLS = comms.PROTOCOLS
local RPLC_TYPES = comms.RPLC_TYPES
local RPLC_LINKING = comms.RPLC_LINKING
-- Internal Safety System
-- identifies dangerous states and SCRAMs reactor if warranted
-- autonomous from main SCADA supervisor/coordinator control
@ -193,78 +197,6 @@ function iss_init(reactor)
}
end
function rplc_packet()
local self = {
frame = nil,
id = nil,
type = nil,
length = nil,
body = nil
}
local _rplc_type_valid = function ()
return self.type == RPLC_TYPES.KEEP_ALIVE or
self.type == RPLC_TYPES.LINK_REQ or
self.type == RPLC_TYPES.STATUS or
self.type == RPLC_TYPES.MEK_STRUCT or
self.type == RPLC_TYPES.MEK_SCRAM or
self.type == RPLC_TYPES.MEK_ENABLE or
self.type == RPLC_TYPES.MEK_BURN_RATE or
self.type == RPLC_TYPES.ISS_ALARM or
self.type == RPLC_TYPES.ISS_GET or
self.type == RPLC_TYPES.ISS_CLEAR
end
-- make an RPLC packet
local make = function (id, packet_type, length, data)
self.id = id
self.type = packet_type
self.length = length
self.data = data
end
-- decode an RPLC packet from a SCADA frame
local decode = function (frame)
if frame then
self.frame = frame
if frame.protocol() == comms.PROTOCOLS.RPLC then
local data = frame.data()
local ok = #data > 2
if ok then
make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
ok = _rplc_type_valid()
end
return ok
else
log._debug("attempted RPLC parse of incorrect protocol " .. frame.protocol(), true)
return false
end
else
log._debug("nil frame encountered", true)
return false
end
end
local get = function ()
return {
scada_frame = self.frame,
id = self.id,
type = self.type,
length = self.length,
data = self.data
}
end
return {
make = make,
decode = decode,
get = get
}
end
-- reactor PLC communications
function comms_init(id, modem, local_port, server_port, reactor, iss)
local self = {
@ -432,13 +364,13 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
if s_pkt.is_valid() then
-- get as RPLC packet
if s_pkt.protocol() == PROTOCOLS.RPLC then
local rplc_pkt = rplc_packet()
local rplc_pkt = comms.rplc_packet()
if rplc_pkt.decode(s_pkt) then
pkt = rplc_pkt.get()
end
-- get as SCADA management packet
elseif s_pkt.protocol() == PROTOCOLS.SCADA_MGMT then
local mgmt_pkt = mgmt_packet()
local mgmt_pkt = comms.mgmt_packet()
if mgmt_pkt.decode(s_pkt) then
pkt = mgmt_packet.get()
end
@ -478,11 +410,11 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
send_status()
log._debug("re-sent initial status data")
elseif link_ack == RPLC_LINKING.DENY then
-- @todo: make sure this doesn't become an MITM security risk
-- @todo: make sure this doesn't become a MITM security risk
print_ts("received unsolicited link denial, unlinking\n")
log._debug("unsolicited rplc link request denied")
elseif link_ack == RPLC_LINKING.COLLISION then
-- @todo: make sure this doesn't become an MITM security risk
-- @todo: make sure this doesn't become a MITM security risk
print_ts("received unsolicited link collision, unlinking\n")
log._warning("unsolicited rplc link request collision")
else

View File

@ -10,7 +10,7 @@ os.loadAPI("scada-common/comms.lua")
os.loadAPI("config.lua")
os.loadAPI("plc.lua")
local R_PLC_VERSION = "alpha-v0.2.0"
local R_PLC_VERSION = "alpha-v0.2.1"
local print = util.print
local println = util.println

View File

@ -153,7 +153,7 @@ function rtu_comms(modem, local_port, server_port)
if s_pkt.is_valid() then
-- get as MODBUS TCP packet
if s_pkt.protocol() == PROTOCOLS.MODBUS_TCP then
local m_pkt = modbus.packet()
local m_pkt = comms.modbus_packet()
if m_pkt.decode(s_pkt) then
pkt = m_pkt.get()
end

View File

@ -17,7 +17,7 @@ os.loadAPI("dev/boiler_rtu.lua")
os.loadAPI("dev/imatrix_rtu.lua")
os.loadAPI("dev/turbine_rtu.lua")
local RTU_VERSION = "alpha-v0.2.0"
local RTU_VERSION = "alpha-v0.2.1"
local print = util.print
local println = util.println

View File

@ -88,6 +88,9 @@ function scada_packet()
local modem_event = function () return self.modem_msg_in end
local raw = function () return self.raw end
local sender = function () return self.s_port end
local receiver = function () return self.r_port end
local is_valid = function () return self.valid end
local seq_num = function () return self.seq_num end
@ -107,6 +110,8 @@ function scada_packet()
receive = receive,
modem_event = modem_event,
raw = raw,
sender = sender,
receiver = receiver,
is_valid = is_valid,
seq_num = seq_num,
protocol = protocol,
@ -115,6 +120,141 @@ function scada_packet()
}
end
-- MODBUS packet
function modbus_packet()
local self = {
frame = nil,
txn_id = txn_id,
protocol = protocol,
length = length,
unit_id = unit_id,
func_code = func_code,
data = data
}
-- make a MODBUS packet
local make = function (txn_id, protocol, length, unit_id, func_code, data)
self.txn_id = txn_id
self.protocol = protocol
self.length = length
self.unit_id = unit_id
self.func_code = func_code
self.data = data
end
-- decode a MODBUS packet from a SCADA frame
local decode = function (frame)
if frame then
self.frame = frame
local data = frame.data()
local size_ok = #data ~= 6
if size_ok then
make(data[1], data[2], data[3], data[4], data[5], data[6])
end
return size_ok and self.protocol == comms.PROTOCOLS.MODBUS_TCP
else
log._debug("nil frame encountered", true)
return false
end
end
-- get this packet
local get = function ()
return {
scada_frame = self.frame,
txn_id = self.txn_id,
protocol = self.protocol,
length = self.length,
unit_id = self.unit_id,
func_code = self.func_code,
data = self.data
}
end
return {
make = make,
decode = decode,
get = get
}
end
-- reactor PLC packet
function rplc_packet()
local self = {
frame = nil,
id = nil,
type = nil,
length = nil,
body = nil
}
local _rplc_type_valid = function ()
return self.type == RPLC_TYPES.KEEP_ALIVE or
self.type == RPLC_TYPES.LINK_REQ or
self.type == RPLC_TYPES.STATUS or
self.type == RPLC_TYPES.MEK_STRUCT or
self.type == RPLC_TYPES.MEK_SCRAM or
self.type == RPLC_TYPES.MEK_ENABLE or
self.type == RPLC_TYPES.MEK_BURN_RATE or
self.type == RPLC_TYPES.ISS_ALARM or
self.type == RPLC_TYPES.ISS_GET or
self.type == RPLC_TYPES.ISS_CLEAR
end
-- make an RPLC packet
local make = function (id, packet_type, length, data)
self.id = id
self.type = packet_type
self.length = length
self.data = data
end
-- decode an RPLC packet from a SCADA frame
local decode = function (frame)
if frame then
self.frame = frame
if frame.protocol() == comms.PROTOCOLS.RPLC then
local data = frame.data()
local ok = #data > 2
if ok then
make(data[1], data[2], data[3], { table.unpack(data, 4, #data) })
ok = _rplc_type_valid()
end
return ok
else
log._debug("attempted RPLC parse of incorrect protocol " .. frame.protocol(), true)
return false
end
else
log._debug("nil frame encountered", true)
return false
end
end
local get = function ()
return {
scada_frame = self.frame,
id = self.id,
type = self.type,
length = self.length,
data = self.data
}
end
return {
make = make,
decode = decode,
get = get
}
end
-- SCADA management packet
function mgmt_packet()
local self = {
frame = nil,

View File

@ -1,3 +1,5 @@
-- #REQUIRES comms.lua
-- modbus function codes
local MODBUS_FCODE = {
READ_COILS = 0x01,
@ -263,63 +265,3 @@ function new(rtu_dev)
handle_packet = handle_packet
}
end
function packet()
local self = {
frame = nil,
txn_id = txn_id,
protocol = protocol,
length = length,
unit_id = unit_id,
func_code = func_code,
data = data
}
-- make a MODBUS packet
local make = function (txn_id, protocol, length, unit_id, func_code, data)
self.txn_id = txn_id
self.protocol = protocol
self.length = length
self.unit_id = unit_id
self.func_code = func_code
self.data = data
end
-- decode a MODBUS packet from a SCADA frame
local decode = function (frame)
if frame then
self.frame = frame
local data = frame.data()
local size_ok = #data ~= 6
if size_ok then
make(data[1], data[2], data[3], data[4], data[5], data[6])
end
return size_ok and self.protocol == comms.PROTOCOLS.MODBUS_TCP
else
log._debug("nil frame encountered", true)
return false
end
end
-- get this packet
local get = function ()
return {
scada_frame = self.frame,
txn_id = self.txn_id,
protocol = self.protocol,
length = self.length,
unit_id = self.unit_id,
func_code = self.func_code,
data = self.data
}
end
return {
make = make,
decode = decode,
get = get
}
end