Skip to content

Commit

Permalink
add rtu response length check
Browse files Browse the repository at this point in the history
  • Loading branch information
vat9 committed Apr 1, 2011
1 parent 7bcafce commit 0de2113
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 18 deletions.
7 changes: 5 additions & 2 deletions appl/cmd/testmodbus.b
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,8 @@ getreply(p: ref Port): (byte, ref RMmsg, int, string)
p.rdlock.obtain();
n := len p.avail;
if(n >= 4) {
(addr, pdu, crc, err) = modbus->rtuunpack(p.avail);
if(err == nil) {
(addr, pdu, crc, n, err) = modbus->rtuunpack(p.avail);
if(err == nil && n > 0) {
(t, m) := RMmsg.unpack(pdu);
if(t > 0)
r = m;
Expand All @@ -496,6 +496,9 @@ getreply(p: ref Port): (byte, ref RMmsg, int, string)
sys->fprint(stderr, "RX <- %s\n", hexdump(p.avail));
}
p.avail = p.avail[n:];
} else if(err == Modbus->ERR_RTUCRC) {
if(n > 0)
p.avail = p.avail[n:];
}
}
p.rdlock.release();
Expand Down
41 changes: 28 additions & 13 deletions appl/lib/modbus.b
Original file line number Diff line number Diff line change
Expand Up @@ -777,27 +777,42 @@ rtupack(addr: byte, pdu: array of byte): array of byte
return atu;
}

rtuunpack(data: array of byte): (byte, array of byte, int, string)
rtuunpack(data: array of byte): (byte, array of byte, int, int, string)
{
e : string;
addr : byte;
pdu : array of byte;
c : int;
n := len data;
if(n >= 4) {
if(n > 4) {
addr = data[0];
pdu = data[1:n-2];
c = g16(data, n-2);
if(c != rtucrc(addr, pdu))
e = RTUCRC_ERROR;
f := int data[1];
if(f > 16r80) { # Modbus error
pdu = data[1:3];
c = g16(data, 4);
if(c != rtucrc(addr, pdu))
e = ERR_RTUCRC;
n = 5;
} else {
l := int data[2];
if(l+5 > n) {
e = ERR_RTUINCOMPLETE;
n = 0;
} else {
pdu = data[1:l+3];
c = g16(data, l+3);
if(c != rtucrc(addr, pdu))
e = ERR_RTUCRC;
n = l+5;
}
}
} else
e = "too short for an rtu packet";
return (addr, pdu, c, e);
e = ERR_RTUINCOMPLETE;
return (addr, pdu, c, n, e);
}

rtucrc(addr: byte, pdu: array of byte): int
{
# crc->reset(crc_state);
crc_state.crc = 16rFFFF;

n := len pdu + BIT8SZ;
Expand All @@ -813,13 +828,13 @@ crc16(crcs : ref CRCstate, buf : array of byte, nb : int) : int
n := nb;
if (n > len buf)
n = len buf;
crc := crcs.crc;
c := crcs.crc;
tab := crcs.crctab;
for (i := 0; i < n; i++) {
crc = (crc >> 8) ^ tab[int(byte crc ^ buf[i])];
c = (c >> 8) ^ tab[int(byte c ^ buf[i])];
}
crcs.crc = crc;
return crc;
crcs.crc = c;
return c;
}

rtucrc_test(addr: byte, pdu: array of byte): int
Expand Down
2 changes: 1 addition & 1 deletion appl/mkfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<../mkconfig

DIRS=\
cmd\
lib\
cmd\

<$ROOT/mkfiles/mksubdirs

5 changes: 3 additions & 2 deletions module/modbus.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
ModeTCP,
Maxmode: con iota;

RTUCRC_ERROR: con "CRC error";
ERR_RTUCRC: con "CRC error";
ERR_RTUINCOMPLETE: con "RTU incomlete";

# Function code types
Treadcoils, # 0x01
Expand Down Expand Up @@ -223,7 +224,7 @@
init: fn();

rtupack: fn(addr: byte, pdu: array of byte): array of byte;
rtuunpack: fn(data: array of byte): (byte, array of byte, int, string);
rtuunpack: fn(data: array of byte): (byte, array of byte, int, int, string);
rtucrc: fn(addr: byte, pdu: array of byte): int;
rtucrc_test: fn(addr: byte, pdu: array of byte): int;
};

0 comments on commit 0de2113

Please sign in to comment.