PLC comms packet length checks

This commit is contained in:
Mikayla Fischler 2022-04-29 09:07:29 -04:00
parent d688f9a1c6
commit 4d5cbcf475
2 changed files with 80 additions and 64 deletions

View File

@ -431,40 +431,48 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
if self.linked then if self.linked then
if packet.type == RPLC_TYPES.KEEP_ALIVE then if packet.type == RPLC_TYPES.KEEP_ALIVE then
-- keep alive request received, echo back -- keep alive request received, echo back
local timestamp = packet.data[1] if packet.length == 1 then
local trip_time = util.time() - timestamp local timestamp = packet.data[1]
local trip_time = util.time() - timestamp
if trip_time > 500 then if trip_time > 500 then
log._warning("PLC KEEP_ALIVE trip time > 500ms (" .. trip_time .. ")") log._warning("PLC KEEP_ALIVE trip time > 500ms (" .. trip_time .. ")")
end
-- log._debug("RPLC RTT = ".. trip_time .. "ms")
_send_keep_alive_ack(timestamp)
else
log._debug(log_header .. "RPLC keep alive packet length mismatch")
end end
-- log._debug("RPLC RTT = ".. trip_time .. "ms")
_send_keep_alive_ack(timestamp)
elseif packet.type == RPLC_TYPES.LINK_REQ then elseif packet.type == RPLC_TYPES.LINK_REQ then
-- link request confirmation -- link request confirmation
log._debug("received unsolicited link request response") if packet.length == 1 then
log._debug("received unsolicited link request response")
local link_ack = packet.data[1] local link_ack = packet.data[1]
if link_ack == RPLC_LINKING.ALLOW then if link_ack == RPLC_LINKING.ALLOW then
_send_struct() _send_struct()
send_status(plc_state.degraded) send_status(plc_state.degraded)
log._debug("re-sent initial status data") log._debug("re-sent initial status data")
elseif link_ack == RPLC_LINKING.DENY then elseif link_ack == RPLC_LINKING.DENY then
-- @todo: make sure this doesn't become a MITM security risk -- @todo: make sure this doesn't become a MITM security risk
println_ts("received unsolicited link denial, unlinking") println_ts("received unsolicited link denial, unlinking")
log._debug("unsolicited RPLC link request denied") log._debug("unsolicited RPLC link request denied")
elseif link_ack == RPLC_LINKING.COLLISION then elseif link_ack == RPLC_LINKING.COLLISION then
-- @todo: make sure this doesn't become a MITM security risk -- @todo: make sure this doesn't become a MITM security risk
println_ts("received unsolicited link collision, unlinking") println_ts("received unsolicited link collision, unlinking")
log._warning("unsolicited RPLC link request collision") log._warning("unsolicited RPLC link request collision")
else
println_ts("invalid unsolicited link response")
log._error("unsolicited unknown RPLC link request response")
end
self.linked = link_ack == RPLC_LINKING.ALLOW
else else
println_ts("invalid unsolicited link response") log._debug(log_header .. "RPLC link req packet length mismatch")
log._error("unsolicited unknown RPLC link request response")
end end
self.linked = link_ack == RPLC_LINKING.ALLOW
elseif packet.type == RPLC_TYPES.MEK_STRUCT then elseif packet.type == RPLC_TYPES.MEK_STRUCT then
-- request for physical structure -- request for physical structure
_send_struct() _send_struct()
@ -482,25 +490,29 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
_send_ack(packet.type, self.reactor.__p_is_ok()) _send_ack(packet.type, self.reactor.__p_is_ok())
elseif packet.type == RPLC_TYPES.MEK_BURN_RATE then elseif packet.type == RPLC_TYPES.MEK_BURN_RATE then
-- set the burn rate -- set the burn rate
local success = false if packet.length == 1 then
local burn_rate = packet.data[1] local success = false
local max_burn_rate = self.max_burn_rate local burn_rate = packet.data[1]
local max_burn_rate = self.max_burn_rate
-- if no known max burn rate, check again -- if no known max burn rate, check again
if max_burn_rate == nil then if max_burn_rate == nil then
max_burn_rate = self.reactor.getMaxBurnRate() max_burn_rate = self.reactor.getMaxBurnRate()
self.max_burn_rate = max_burn_rate self.max_burn_rate = max_burn_rate
end
-- if we know our max burn rate, update current burn rate if in range
if max_burn_rate ~= ppm.ACCESS_FAULT then
if burn_rate > 0 and burn_rate <= max_burn_rate then
self.reactor.setBurnRate(burn_rate)
success = self.reactor.__p_is_ok()
end end
end
_send_ack(packet.type, success) -- if we know our max burn rate, update current burn rate if in range
if max_burn_rate ~= ppm.ACCESS_FAULT then
if burn_rate > 0 and burn_rate <= max_burn_rate then
self.reactor.setBurnRate(burn_rate)
success = self.reactor.__p_is_ok()
end
end
_send_ack(packet.type, success)
else
log._debug(log_header .. "RPLC set burn rate packet length mismatch")
end
elseif packet.type == RPLC_TYPES.ISS_CLEAR then elseif packet.type == RPLC_TYPES.ISS_CLEAR then
-- clear the ISS status -- clear the ISS status
iss.reset() iss.reset()
@ -510,31 +522,35 @@ function comms_init(id, modem, local_port, server_port, reactor, iss)
end end
elseif packet.type == RPLC_TYPES.LINK_REQ then elseif packet.type == RPLC_TYPES.LINK_REQ then
-- link request confirmation -- link request confirmation
local link_ack = packet.data[1] if packet.length == 1 then
local link_ack = packet.data[1]
if link_ack == RPLC_LINKING.ALLOW then if link_ack == RPLC_LINKING.ALLOW then
println_ts("linked!") println_ts("linked!")
log._debug("RPLC link request approved") log._debug("RPLC link request approved")
-- reset remote sequence number -- reset remote sequence number
self.r_seq_num = nil self.r_seq_num = nil
_send_struct() _send_struct()
send_status(plc_state.degraded) send_status(plc_state.degraded)
log._debug("sent initial status data") log._debug("sent initial status data")
elseif link_ack == RPLC_LINKING.DENY then elseif link_ack == RPLC_LINKING.DENY then
println_ts("link request denied, retrying...") println_ts("link request denied, retrying...")
log._debug("RPLC link request denied") log._debug("RPLC link request denied")
elseif link_ack == RPLC_LINKING.COLLISION then elseif link_ack == RPLC_LINKING.COLLISION then
println_ts("reactor PLC ID collision (check config), retrying...") println_ts("reactor PLC ID collision (check config), retrying...")
log._warning("RPLC link request collision") log._warning("RPLC link request collision")
else
println_ts("invalid link response, bad channel? retrying...")
log._error("unknown RPLC link request response")
end
self.linked = link_ack == RPLC_LINKING.ALLOW
else else
println_ts("invalid link response, bad channel? retrying...") log._debug(log_header .. "RPLC link req packet length mismatch")
log._error("unknown RPLC link request response")
end end
self.linked = link_ack == RPLC_LINKING.ALLOW
else else
log._debug("discarding non-link packet before linked") log._debug("discarding non-link packet before linked")
end end

View File

@ -12,7 +12,7 @@ os.loadAPI("config.lua")
os.loadAPI("plc.lua") os.loadAPI("plc.lua")
os.loadAPI("threads.lua") os.loadAPI("threads.lua")
local R_PLC_VERSION = "alpha-v0.4.7" local R_PLC_VERSION = "alpha-v0.4.8"
local print = util.print local print = util.print
local println = util.println local println = util.println