From 44c82412b922847e0a3b3babb86158ffda5ebcf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Sun, 2 Jun 2019 10:19:30 +0300 Subject: Protocol: fixed a critical bug. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Look at the diff and it will be obvious what was fixed. Signed-off-by: Ramūnas Mažeikis --- src/common/tlv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/tlv.c b/src/common/tlv.c index c25f008..5b5ca5e 100644 --- a/src/common/tlv.c +++ b/src/common/tlv.c @@ -41,7 +41,7 @@ int tlv_get(struct tlv_parser *parser, struct tlv *ret) retval = END_OF_PACKET; } else { memcpy(&ret->type, parser->data + parser->offset, sizeof(ret->type)); - parser->size += sizeof(ret->type); + parser->offset += sizeof(ret->type); ret->length = memcpy(&ret->length, parser->data + parser->offset, sizeof(ret->length)); parser->offset += sizeof(ret->length); if (parser->offset + ret->length >= parser->size) { -- cgit v1.2.3 From e801c0c7204df9c566b503a7c4c2d828166796f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Sun, 2 Jun 2019 13:55:38 +0300 Subject: Protocol: fixed typos and permissions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/tlv.h | 2 +- src/common/tlv.c | 0 2 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 src/common/tlv.c diff --git a/include/tlv.h b/include/tlv.h index b52763a..63507c1 100644 --- a/include/tlv.h +++ b/include/tlv.h @@ -150,7 +150,7 @@ struct tlv_parser { /** * Fills tlv structure to represent the next tlv in the packet. * - * Returns END_OF_PACKET if all tlv's were read of E_TLV_OVERFLOW, if the last + * Returns END_OF_PACKET if all tlv's were read or E_TLV_OVERFLOW, if the last * tlv, according to its declared size should not fit in a packet. */ int tlv_get(struct tlv_parser *parser, struct tlv *ret); diff --git a/src/common/tlv.c b/src/common/tlv.c old mode 100644 new mode 100755 -- cgit v1.2.3 From 9d8c56601d37e420143ef5aeec98d9ab9c5a60fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 4 Jun 2019 10:21:03 +0300 Subject: Protocol: reimplementation of tlv_get according to new spec. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- include/tlv.h | 34 +++++++++++++++++++------ src/common/tlv.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 93 insertions(+), 18 deletions(-) diff --git a/include/tlv.h b/include/tlv.h index 63507c1..75aa133 100644 --- a/include/tlv.h +++ b/include/tlv.h @@ -62,6 +62,8 @@ A few things to note: #include +#include +#include #define E_TLV_OVERFLOW (1 << 0) #define E_UNKNOWN_TYPE (1 << 1) @@ -79,7 +81,18 @@ extern "C" { */ typedef unsigned int msg_idx_t; +#if INT32_MAX == INT_MAX +#define READ_ENUM(data) htonl((data)) +#else INT_MAX == INT16_MAX +#define READ_ENUM(data) htons((data)) +#endif + enum tlv_type { + /** + * Explicitly states that this tlv is no longer valid for reading. + */ + INVALID = 0, + /** * NULL-terminated string. To be put in a queue to display on the * screen. @@ -132,8 +145,8 @@ enum tlv_type { * */ struct tlv { enum tlv_type type; - size_t length; - void *data; + uint16_t length; + const void *data; }; /** @@ -142,11 +155,18 @@ struct tlv { * Related functions return one tlv at a time. */ struct tlv_parser { - char *data; - size_t offset; - size_t size; + const char *data; + uint16_t offset; }; +/** + * Initialises parser to begin parsing the data. + * + * Returns the first tlv which should be a meta-tlv. If it is not --- you got + * problems. + */ +int tlv_parser_init(struct tlv_parser *parser, char *data, struct tlv *ret); + /** * Fills tlv structure to represent the next tlv in the packet. * @@ -175,14 +195,14 @@ size_t tlv_raw_size(const struct tlv *t); * Pushes tlv to buffer as contiguous data. Check tlv size with tlv_raw_size * beforehand. If you don't do that and overflow --- tough tiddy. */ -int tlv_get_raw(struct tlv *t, char *buf); +int tlv_get_raw(const struct tlv *t, char *buf); /** * Pushes data to tlv. Returns E_TLV_OVERFLOW if pushing data would cause the * final size to be greater than TLV_SZ_MAX_RAW. In case of such error the data is left * untouched. */ -int tlv_push_data(struct tlv *t, const char *data, size_t size); +int tlv_push_data(struct tlv *t, const char *data, uint16_t size); /** * Pushes a sub-tlv into the packet. 't' can only be REGURAL, HEARTBEAT or diff --git a/src/common/tlv.c b/src/common/tlv.c index 5b5ca5e..f02b714 100755 --- a/src/common/tlv.c +++ b/src/common/tlv.c @@ -27,32 +27,87 @@ #include #include #include +#include #include "tlv.h" #include "net.h" #include "utils.h" +struct tlv_header { + enum tlv_type type; + uint16_t size; +}; + +/** + * Returns tlv_size from packet + */ +uint16_t tlv_size(char *buf); + +/** + * Returns tlv_type from packet. + */ +enum tlv_type tlv_get_type(char *buf); + +/* Changes to be made: + * * Trust tlv size from raw data + * * Don't fail on 0 length. In that case data points to NULL + * * tlv_parser should be opaque. + * * Make a constructor that takes a user-supplied buffer. + */ int tlv_get(struct tlv_parser *parser, struct tlv *ret) { int retval = 0; - if (parser->offset + sizeof(ret->type) + sizeof(ret->length) >= parser->size) { - retval = E_TLV_OVERFLOW; - } else if (parser -> offset == parser->size) { - retval = END_OF_PACKET; + size_t packet_size; + size_t final_size; + struct tlv *crr_tlv = parser->data + parser->offset; + + packet_size = tlv_size(parser->data); + final_size = parser->offset + crr_tlv->length + sizeof(struct tlv_header); + if (final_size >= packet_size) { + return retval = E_TLV_OVERFLOW; } else { - memcpy(&ret->type, parser->data + parser->offset, sizeof(ret->type)); - parser->offset += sizeof(ret->type); - ret->length = memcpy(&ret->length, parser->data + parser->offset, sizeof(ret->length)); - parser->offset += sizeof(ret->length); - if (parser->offset + ret->length >= parser->size) { - retval = E_TLV_OVERFLOW; + if (crr_tlv->length != 0) { + ret->data = parser->data + parser->offset + sizeof(struct tlv_header); } else { - memcpy(ret->data, parser->data, ret->length); + ret->data = NULL; + } + ret->type = crr_tlv->type; + ret->length = crr_tlv->length; + parser->offset += sizeof(struct tlv_header) + ret->length; + if (final_size == packet_size) { + retval = END_OF_PACKET; } } + return retval; } +int tlv_parser_init(struct tlv_parser *parser, char *buf, struct tlv *ret) +{ + /* Data points to the beggining of the buffer for size and + * type acquisition purposes. + * */ + struct tlv_header *data = buf; + /* It is known that the first tlv will be of the meta kind. + * We can safely skip the header. + * */ + parser->data = buf + sizeof(struct tlv_header); + ret->type = data->type; + ret->length = data->size; +} + +uint16_t tlv_size(char *buf) +{ + struct tlv_header *data = buf; + return htons(data->size); +} + +enum tlv_type tlv_get_type(char *buf) +{ + struct tlv_header *data = buf; + return READ_ENUM(data->type); +} + size_t tlv_data_size(struct tlv_parser *parser) { size_t size; -- cgit v1.2.3 From caace1481ded27b03c47b822f8a7ec66837411c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C5=ABnas=20Ma=C5=BEeikis?= Date: Tue, 4 Jun 2019 10:27:05 +0300 Subject: Protocol: made the thing compile again. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ramūnas Mažeikis --- src/common/tlv.c | 17 +++++++++++------ src/device/main.ino | 1 - 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/common/tlv.c b/src/common/tlv.c index f02b714..72d0399 100755 --- a/src/common/tlv.c +++ b/src/common/tlv.c @@ -27,11 +27,16 @@ #include #include #include -#include #include "tlv.h" #include "net.h" #include "utils.h" +#ifdef unix +#include +#else +#include +#endif + struct tlv_header { enum tlv_type type; uint16_t size; @@ -92,14 +97,14 @@ int tlv_parser_init(struct tlv_parser *parser, char *buf, struct tlv *ret) * We can safely skip the header. * */ parser->data = buf + sizeof(struct tlv_header); - ret->type = data->type; - ret->length = data->size; + ret->type = READ_ENUM(data->type); + ret->length = ntohs(data->size); } uint16_t tlv_size(char *buf) { struct tlv_header *data = buf; - return htons(data->size); + return ntohs(data->size); } enum tlv_type tlv_get_type(char *buf) @@ -112,7 +117,7 @@ size_t tlv_data_size(struct tlv_parser *parser) { size_t size; - if (parser->offset + sizeof(enum tlv_type) + sizeof(size_t) >= parser->size) { + if (parser->offset + sizeof(enum tlv_type) + sizeof(size_t) >= tlv_size(parser)) { size = 0; } else { memcpy(&size, parser->data + parser->offset + sizeof(enum tlv_type), sizeof(size_t)); @@ -147,7 +152,7 @@ size_t tlv_raw_size(const struct tlv *t) return sizeof(*t) + t->length; } -int tlv_push_data(struct tlv *t, const char *data, size_t size) +int tlv_push_data(struct tlv *t, const char *data, uint16_t size) { int ret = 0; size_t final_size = tlv_raw_size(t) + size; diff --git a/src/device/main.ino b/src/device/main.ino index 24cfb9c..4376346 100644 --- a/src/device/main.ino +++ b/src/device/main.ino @@ -103,7 +103,6 @@ void loop(void) if (progstate.bytes_read > 0) { progstate.parser.data = progstate.in_packet_buf; progstate.parser.offset = 0; - progstate.parser.size = progstate.bytes_read; /* Ignore errors for now. */ while (tlv_get(&progstate.parser, &progstate.crr_data) == 0) { handle_tlv(&progstate.crr_data); -- cgit v1.2.3