summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2017-01-04 11:51:14 -0600
committerDan Williams <dcbw@redhat.com>2017-10-31 11:47:17 -0500
commitcec540cd738fed0de8483d8003e29203733e5e68 (patch)
tree579b99376491b616229094847a7298641da9419d
parent6b0c26152594f3fb9ef1f33629fcad150e607926 (diff)
downloadModemManager-cec540cd738fed0de8483d8003e29203733e5e68.tar.gz
hdlc: compare CRC against known good value rather than found CRC
Instead of bothering to pull the found CRC out of the decapsulated frame, we can just compare the calculated CRC to a known good value due to the way CRC-CCITT works.
-rw-r--r--src/mm-hdlc.c37
1 files changed, 12 insertions, 25 deletions
diff --git a/src/mm-hdlc.c b/src/mm-hdlc.c
index 731721c00..4fad9e96f 100644
--- a/src/mm-hdlc.c
+++ b/src/mm-hdlc.c
@@ -67,16 +67,11 @@ crc_update (guint16 crc, guint8 val)
return crc_table[(crc ^ val) & 0xff] ^ (crc >> 8);
}
-static guint16
-crc_finish (guint16 crc)
-{
- return ~crc;
-}
-
const guint8 HDLC_CONTROL = 0x7E; /* Control character */
const guint8 HDLC_ESC_CHAR = 0x7D; /* Escape sequence 1st character value */
const guint8 HDLC_ESC_MASK = 0x20; /* Escape sequence complement value */
const guint16 HDLC_CRC_INIT = 0xFFFF;
+const guint16 HDLC_CRC_GOOD = 0xF0B8;
static guint
framed_len (GByteArray *bytes)
@@ -136,8 +131,8 @@ mm_hdlc_encapsulate (GByteArray *bytes, GError **error)
escape_and_add (framed, bytes->data[i]);
}
- /* Append and escape the CRC */
- crc = crc_finish (crc);
+ /* Append and escape the complement of the CRC */
+ crc = ~crc;
escape_and_add (framed, crc & 0xFF);
escape_and_add (framed, (crc >> 8) & 0xFF);
@@ -178,7 +173,6 @@ mm_hdlc_decapsulate (GByteArray *bytes,
guint i, frame_len = 0;
gboolean unescaping = FALSE;
guint16 crc = HDLC_CRC_INIT;
- guint16 found_crc = 0;
if (out_bytes_used)
*out_bytes_used = 0;
@@ -214,33 +208,26 @@ mm_hdlc_decapsulate (GByteArray *bytes,
unframed = g_byte_array_sized_new (frame_len);
for (i = 0; i < frame_len; i++) {
- guint8 val;
+ guint8 val = bytes->data[i];
- if (bytes->data[i] == HDLC_ESC_CHAR) {
+ if (val == HDLC_ESC_CHAR) {
unescaping = TRUE;
continue;
- }
-
- if (unescaping) {
- val = bytes->data[i] ^ HDLC_ESC_MASK;
+ } else if (unescaping) {
+ val ^= HDLC_ESC_MASK;
unescaping = FALSE;
- } else
- val = bytes->data[i];
+ }
+ crc = crc_update (crc, val);
- /* Don't CRC the CRC */
- if (i < frame_len - 2) {
- crc = crc_update (crc, val);
+ /* Ignore the CRC when returning the frame */
+ if (i < frame_len - 2)
g_byte_array_append (unframed, &val, 1);
- } else if (i == frame_len - 2)
- found_crc = val;
- else if (i == frame_len - 1)
- found_crc |= val << 8;
}
if (out_bytes_used)
*out_bytes_used = frame_len + 1;
- if (crc_finish (crc) != found_crc) {
+ if (crc != HDLC_CRC_GOOD) {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "HDLC CRC mismatch");
g_byte_array_free (unframed, TRUE);
return NULL;