Simulation file and hex on command line now auto-removes any valid dll-crcs found.

pull/385/head
Fredrik Öhrström 2021-11-08 20:12:21 +01:00
rodzic 02e84048f0
commit f7cb6ce2ee
9 zmienionych plików z 155 dodań i 27 usunięć

Wyświetl plik

@ -1,4 +1,12 @@
Now any DLL crcs (frame A or B) are removed automatically
when telegrams are read from a simulation_... file or
passed as hex on the command line. If the DLL crc do not
check out (usually because they are not there), then the
telegram is kept as is. If the crcs are broken because
of a bad data, then the telegram will be passed on as is,
probably causing a bad parse later on.
Added multical602 heat meter.
Version 1.5.0: 2021-11-06

Wyświetl plik

@ -303,6 +303,7 @@ These telegrams are expected to have the data link layer crc bytes removed alrea
`simulation_abc.txt`, to read telegrams from the file (the file must have a name beginning with simulation_....)
expecting the same format that is the output from `--logtelegrams`. This format also supports replay with timing.
The telegrams are allowed to have valid dll crcs, which will be automatically stripped.
As meter quadruples you specify:
@ -604,8 +605,11 @@ echo 234433300602010014007a8e0000002f2f0efd3a1147000000008e40fd3a341200000000 |
or read hex data from a a file, `wmbusmeters myfile.txt:hex`
Any non-hex characters are ignored when using the suffix `:hex`. The hex string must be proper
with no spaces nor bad characters, when supplied on the command line.
Any non-hex characters are ignored when using the suffix `:hex`. However when the hex string is
supplied on the command line it must be a proper hex string with no spaces.
When a telegram is supplied on the command line, then any valid dll crcs will be automatically removed,
like when the telegram is suppled in a simulation file.
# Additional tools

Wyświetl plik

@ -1,3 +1,3 @@
# This telegram is not really broken, but the current dvparser fails, in particular the end triggers a varlen with
# not enough bytes in the telegram. When the protocol/dvparser is improved, a replacement telegram should be placed here.
telegram=|3444EE4D813929271608|811D|7A51000000|046D1912A62B036E000000|5170426CE1F1436E00000002FF2C00000259D6D0D4090265FC0902FD66A00044C4|
# The last byte C4 has been removed. This means that the dll crcs will not check out.
# Since the simulation will not remove the crcs unless they all check out, this will result in a broken telegram.
telegram=|3444EE4D813929271608|811D|7A51000000|046D1912A62B036E000000|5170426CE1F1436E00000002FF2C00000259D6D0D4090265FC0902FD66A00044|

Wyświetl plik

@ -0,0 +1,3 @@
# These telegrams have their dll crc:s still inside.
telegram=|734414867CC30B0003030D58A00EDF0700DC41343CEA390306FF0A0D44EADF07000DDF07000DDF07000DDF07000E44F9DF07000EDF07000EDF07000EDF07000E931EDF07000DDF07000DDF07000DDF0700035A4500000000374F0B20000000000000243412B31C07050C12280000000000002C002302062F19080F2F000000000000DCF5|
telegram=|3444EE4D813929271608|811D|7A51000000|046D1912A62B036E000000|5170426CE1F1436E00000002FF2C00000259D6D0D4090265FC0902FD66A00044C4|

Wyświetl plik

@ -4060,14 +4060,20 @@ LIST_OF_AFL_AUTH_TYPES
return AFLAuthenticationType::Reserved1;
}
bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
bool trimCRCsFrameFormatAInternal(std::vector<uchar> &payload, bool fail_is_ok)
{
if (payload.size() < 12) {
debug("(wmbus) not enough bytes! expected at least 12 but got (%zu)!\n", payload.size());
if (!fail_is_ok)
{
debug("(wmbus) not enough bytes! expected at least 12 but got (%zu)!\n", payload.size());
}
return false;
}
size_t len = payload.size();
debugPayload("(wmbus) trimming frame A", payload);
if (!fail_is_ok)
{
debugPayload("(wmbus) trimming frame A", payload);
}
vector<uchar> out;
@ -4080,7 +4086,10 @@ bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
return false;
}
out.insert(out.end(), payload.begin(), payload.begin()+10);
debug("(wmbus) ff a dll crc 0-%zu %04x ok\n", 10-1, calc_crc);
if (!fail_is_ok)
{
debug("(wmbus) ff a dll crc 0-%zu %04x ok\n", 10-1, calc_crc);
}
size_t pos = 12;
for (pos = 12; pos+18 <= len; pos += 18)
@ -4090,12 +4099,18 @@ bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
check_crc = payload[to] << 8 | payload[to+1];
if (calc_crc != check_crc && !FUZZING)
{
debug("(wmbus) ff a dll crc mid (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, pos, to-1);
if (!fail_is_ok)
{
debug("(wmbus) ff a dll crc mid (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, pos, to-1);
}
return false;
}
out.insert(out.end(), payload.begin()+pos, payload.begin()+pos+16);
debug("(wmbus) ff a dll crc mid %zu-%zu %04x ok\n", pos, to-1, calc_crc);
if (!fail_is_ok)
{
debug("(wmbus) ff a dll crc mid %zu-%zu %04x ok\n", pos, to-1, calc_crc);
}
}
if (pos < len-2)
@ -4106,12 +4121,23 @@ bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
check_crc = payload[tto] << 8 | payload[tto+1];
if (calc_crc != check_crc && !FUZZING)
{
debug("(wmbus) ff a dll crc final (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, pos, tto-1);
if (!fail_is_ok)
{
debug("(wmbus) ff a dll crc final (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, pos, tto-1);
}
return false;
}
out.insert(out.end(), payload.begin()+pos, payload.begin()+tto);
debug("(wmbus) ff a dll crc final %zu-%zu %04x ok\n", pos, tto-1, calc_crc);
if (!fail_is_ok)
{
debug("(wmbus) ff a dll crc final %zu-%zu %04x ok\n", pos, tto-1, calc_crc);
}
}
if (fail_is_ok)
{
debugPayload("(wmbus) trimming frame A", payload);
}
out[0] = out.size()-1;
@ -4120,20 +4146,26 @@ bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
payload = out;
size_t new_size = payload.size();
debug("(wmbus) trimmed %zu crc bytes from frame a and ignored %zu suffix bytes.\n", (len-new_len), (old_size-new_size)-(len-new_len));
debugPayload("(wmbus) trimmed frame A", payload);
debug("(wmbus) trimmed %zu dll crc bytes from frame a and ignored %zu suffix bytes.\n", (len-new_len), (old_size-new_size)-(len-new_len));
debugPayload("(wmbus) trimmed frame A", payload);
return true;
}
bool trimCRCsFrameFormatB(std::vector<uchar> &payload)
bool trimCRCsFrameFormatBInternal(std::vector<uchar> &payload, bool fail_is_ok)
{
if (payload.size() < 12) {
debug("(wmbus) not enough bytes! expected at least 12 but got (%zu)!\n", payload.size());
if (!fail_is_ok)
{
debug("(wmbus) not enough bytes! expected at least 12 but got (%zu)!\n", payload.size());
}
return false;
}
size_t len = payload.size();
debugPayload("(wmbus) trimming frame B", payload);
if (!fail_is_ok)
{
debugPayload("(wmbus) trimming frame B", payload);
}
vector<uchar> out;
size_t crc1_pos, crc2_pos;
@ -4153,12 +4185,18 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload)
if (calc_crc != check_crc && !FUZZING)
{
debug("(wmbus) ff b dll crc (calculated %04x) did not match (expected %04x) for bytes 0-%zu!\n", calc_crc, check_crc, crc1_pos);
if (!fail_is_ok)
{
debug("(wmbus) ff b dll crc (calculated %04x) did not match (expected %04x) for bytes 0-%zu!\n", calc_crc, check_crc, crc1_pos);
}
return false;
}
out.insert(out.end(), payload.begin(), payload.begin()+crc1_pos);
debug("(wmbus) ff b dll crc first 0-%zu %04x ok\n", crc1_pos, calc_crc);
if (!fail_is_ok)
{
debug("(wmbus) ff b dll crc first 0-%zu %04x ok\n", crc1_pos, calc_crc);
}
if (crc2_pos > 0)
{
@ -4167,13 +4205,24 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload)
if (calc_crc != check_crc && !FUZZING)
{
debug("(wmbus) ff b dll crc (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, crc1_pos+2, crc2_pos);
if (!fail_is_ok)
{
debug("(wmbus) ff b dll crc (calculated %04x) did not match (expected %04x) for bytes %zu-%zu!\n",
calc_crc, check_crc, crc1_pos+2, crc2_pos);
}
return false;
}
out.insert(out.end(), payload.begin()+crc1_pos+2, payload.begin()+crc2_pos);
debug("(wmbus) ff b dll crc final %zu-%zu %04x ok\n", crc1_pos+2, crc2_pos, calc_crc);
if (!fail_is_ok)
{
debug("(wmbus) ff b dll crc final %zu-%zu %04x ok\n", crc1_pos+2, crc2_pos, calc_crc);
}
}
if (fail_is_ok)
{
debugPayload("(wmbus) trimming frame B", payload);
}
out[0] = out.size()-1;
@ -4182,12 +4231,28 @@ bool trimCRCsFrameFormatB(std::vector<uchar> &payload)
payload = out;
size_t new_size = payload.size();
debug("(wmbus) trimmed %zu crc bytes from frame b and ignored %zu suffix bytes.\n", (len-new_len), (old_size-new_size)-(len-new_len));
debugPayload("(wmbus) trimmed frame B", payload);
debug("(wmbus) trimmed %zu dll crc bytes from frame b and ignored %zu suffix bytes.\n", (len-new_len), (old_size-new_size)-(len-new_len));
debugPayload("(wmbus) trimmed frame B", payload);
return true;
}
void removeAnyDLLCRCs(std::vector<uchar> &payload)
{
bool trimmed = trimCRCsFrameFormatAInternal(payload, true);
if (!trimmed) trimCRCsFrameFormatBInternal(payload, true);
}
bool trimCRCsFrameFormatA(std::vector<uchar> &payload)
{
return trimCRCsFrameFormatAInternal(payload, false);
}
bool trimCRCsFrameFormatB(std::vector<uchar> &payload)
{
return trimCRCsFrameFormatBInternal(payload, false);
}
FrameStatus checkWMBusFrame(vector<uchar> &data,
size_t *frame_length,
int *payload_len_out,

Wyświetl plik

@ -27,6 +27,7 @@
// Check and remove the data link layer CRCs from a wmbus telegram.
// If the CRCs do not pass the test, return false.
void removeAnyDLLCRCs(std::vector<uchar> &payload);
bool trimCRCsFrameFormatA(std::vector<uchar> &payload);
bool trimCRCsFrameFormatB(std::vector<uchar> &payload);

Wyświetl plik

@ -175,6 +175,13 @@ void WMBusSimulator::simulate()
error("Not a valid string of hex bytes! \"%s\"\n", l.c_str());
}
AboutTelegram about("", 0, FrameType::WMBUS);
// Since this is a simulation, try to remove any frame format A or B
// data link layer crcs. These might remain if we have received the telegram
// to be simulated, from a CUL device or some other devices that does not remove the crcs.
// Normally the dongle (im871a/amb8465/rc1180/rtlwmbus/rtl443) removes the dll-crcs.
// Removing dll-crcs are also done explicitly in the wmbus_cul.cc driver.
removeAnyDLLCRCs(payload);
handleTelegram(about, payload);
}
manager_->stop();

Wyświetl plik

@ -114,6 +114,9 @@ if [ "$?" != "0" ]; then RC="1"; fi
./tests/test_hex_cmdline.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
./tests/test_removing_dll_crcs.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi
./tests/test_broken.sh $PROG
if [ "$?" != "0" ]; then RC="1"; fi

Wyświetl plik

@ -0,0 +1,37 @@
#!/bin/sh
PROG="$1"
TEST=testoutput
mkdir -p $TEST
TESTNAME="Test auto removal of dll crcs in simulated telegrams"
TESTRESULT="ERROR"
cat > $TEST/test_expected.txt <<EOF
No meters configured. Printing id:s of all telegrams heard!
Received telegram from: 000bc37c
manufacturer: (APT) Unknown (0x8614)
type: Gas meter (0x03)
ver: 0x03
driver: apator08
Received telegram from: 27293981
manufacturer: (SON) Sontex, Switzerland (0x4dee)
type: Heat Cost Allocator (0x08)
ver: 0x16
driver: sontex868
EOF
$PROG simulations/simulation_dll_crcs.txt > $TEST/test_output.txt 2>&1
if [ "$?" = "0" ]
then
diff $TEST/test_expected.txt $TEST/test_output.txt
if [ "$?" = "0" ]
then
echo OK: $TESTNAME
TESTRESULT="OK"
fi
else
echo "wmbusmeters returned error code: $?"
cat $TEST/test_output.txt
fi