From acf03d97ada0b3875b3e17bc296554d96e322fc8 Mon Sep 17 00:00:00 2001 From: sverma <saurabh.verma@iopsys.eu> Date: Wed, 16 Feb 2022 13:11:54 +0530 Subject: [PATCH] added validation for channal_scan_report CMDU --- src/Makefile | 1 + src/cmdu_validate.c | 112 ++++++++++++++++++++++++++++++++++++++++++++ src/cmdu_validate.h | 10 ++++ src/cntlr_map.c | 45 +++++++----------- 4 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 src/cmdu_validate.c create mode 100644 src/cmdu_validate.h diff --git a/src/Makefile b/src/Makefile index 92b8d0b3..a94b659d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,6 +15,7 @@ OBJS = \ cntlr_cmdu.o \ cntlr_acs.o \ cntlr_map_debug.o \ + cmdu_validate.o \ config.o \ main.o diff --git a/src/cmdu_validate.c b/src/cmdu_validate.c new file mode 100644 index 00000000..868c0a6d --- /dev/null +++ b/src/cmdu_validate.c @@ -0,0 +1,112 @@ + +#include <map2.h> +#include <cmdu.h> +#include "cmdu_validate.h" + + +bool validate_channel_scan_report(struct cmdu_buff *cmdu, struct tlv *tv_tsp[][16], + struct tlv *tv_scan[], int *num) +{ + int i, j; + struct tlv_policy d_policy_tsp[] = { + [0] = { + .type = MAP_TLV_TIMESTAMP, + .present = TLV_PRESENT_ONE, + .minlen = 1 + } + }; + struct tlv_policy d_policy_scan[] = { + [0] = { + .type = MAP_TLV_CHANNEL_SCAN_RES, + .present = TLV_PRESENT_MORE, + .minlen = 9 + } + }; + + cmdu_parse_tlvs(cmdu, tv_tsp, d_policy_tsp, 1); + cmdu_parse_tlv_single(cmdu, tv_scan, d_policy_scan, num); + + if (tv_tsp[0][0]) { + int offset = 0; + int tsp_len = 0; + uint8_t *t = (uint8_t *)tv_tsp[0][0]->data; + uint16_t tlv_len = tlv_length(tv_tsp[0][0]); + + tsp_len = t[offset]; + offset += 1; + if (offset+tsp_len > tlv_len) + return false; + } + + for (i = 0; i < *num; i++) { + int offset = 0; + uint8_t status = 0x00; + uint8_t *t = (uint8_t *)tv_scan[i]->data; + uint16_t tlv_len = tlv_length(tv_scan[i]); + + offset += 6; /* radio id */ + offset += 1; /* opclass */ + offset += 1; /* channel */ + status = t[offset]; + offset += 1; /* status */ + + if (status == CH_SCAN_STATUS_SUCCESS) { + int ts_len = 0; + uint16_t num_nb = 0; + + if (offset+1 > tlv_len) + return false; + + ts_len = t[offset]; + offset += 1; /* timestamp len */ + if (offset+ts_len+4 > tlv_len) + return false; + + offset += ts_len; /* timestamp */ + offset += 1; /* utilization */ + offset += 1; /* noise */ + num_nb = BUF_GET_BE16(t[offset]); + offset += 2; /* num neightbors */ + + for (j = 0; j < num_nb; j++) { + int ssid_len = 0; + int bw_len = 0; + uint8_t info = 0x00; + + if (offset+7 > tlv_len) + return false; + + offset += 6; /* bssid */ + ssid_len = t[offset]; + offset += 1; /* ssid len */ + if (offset+ssid_len+2 > tlv_len) + return false; + + offset += ssid_len; /* ssid */ + offset += 1; /* rcpi */ + bw_len = t[offset]; + offset += 1; /* bw len */ + if (offset+bw_len+1 > tlv_len) + return false; + + offset += bw_len; /* bandwidth */ + info = t[offset]; + offset += 1; /* info */ + + if (info & CH_SCAN_RESULT_BSSLOAD_PRESENT) { + if (offset+3 > tlv_len) + return false; + + offset += 1; /* channel utilization */ + offset += 2; /* station count */ + } + } + + if (offset+5 > tlv_len) + return false; + } + } + + return true; +} + diff --git a/src/cmdu_validate.h b/src/cmdu_validate.h new file mode 100644 index 00000000..3c029a12 --- /dev/null +++ b/src/cmdu_validate.h @@ -0,0 +1,10 @@ + + +#ifndef CMDU_VALIDATE +#define CMDU_VALIDATE + +bool validate_channel_scan_report(struct cmdu_buff *cmdu, struct tlv *tv_tsp[][16], + struct tlv *tv_scan[], int *num); + + +#endif // CMDU_VALIDATE diff --git a/src/cntlr_map.c b/src/cntlr_map.c index cb85f26d..c0716218 100644 --- a/src/cntlr_map.c +++ b/src/cntlr_map.c @@ -48,6 +48,7 @@ #include "cntlr_map_debug.h" #include "cntlr_cmdu.h" #include "cntlr_tlv.h" +#include "cmdu_validate.h" #define TIMESTAMP_MAX_LEN 256 @@ -2039,24 +2040,14 @@ int handle_channel_scan_report(void *cntlr, struct cmdu_buff *cmdu) uint8_t *tv_data; struct tlv *tv_tsp[1][16]; struct tlv *tv_scan[256]; - struct tlv_policy d_policy_tsp[] = { - [0] = { - .type = MAP_TLV_TIMESTAMP, - .present = TLV_PRESENT_ONE - } - }; - struct tlv_policy d_policy_scan[] = { - [0] = { - .type = MAP_TLV_CHANNEL_SCAN_RES, - .present = TLV_PRESENT_MORE - } - }; char timestamp[TIMESTAMP_MAX_LEN] = {0}; struct tlv_timestamp *p; - cmdu_parse_tlvs(cmdu, tv_tsp, d_policy_tsp, 1); - cmdu_parse_tlv_single(cmdu, tv_scan, d_policy_scan, &num); + if (!validate_channel_scan_report(cmdu, tv_tsp, tv_scan, &num)) { + dbg("cmdu validation: [CHANNEL_SCAN_REPORT] failed\n"); + return -1; + } if (!tv_tsp[0][0]) { dbg("No TIMESTAMP_TLV received!\n"); @@ -2067,10 +2058,6 @@ int handle_channel_scan_report(void *cntlr, struct cmdu_buff *cmdu) dbg("No RESULT_TLV received!\n"); return -1; } - if (tv_tsp[0][0]->type != MAP_TLV_TIMESTAMP) { - dbg("Wrong received TLV type!\n"); - return -1; - } dbg("\nTLV type: MAP_TLV_TIMESTAMP\n"); tv_data = (uint8_t *)tv_tsp[0][0]->data; @@ -2089,11 +2076,6 @@ int handle_channel_scan_report(void *cntlr, struct cmdu_buff *cmdu) dbg("\n"); for (i = 0; i < num; i++) { - if (tv_scan[i]->type != MAP_TLV_CHANNEL_SCAN_RES) { - dbg("Wrong received TLV type!\n"); - return -1; - } - dbg("\nTLV type: MAP_TLV_CHANNEL_SCAN_RES\n"); tv_data = (uint8_t *)tv_scan[i]->data; struct tlv_channel_scan_result *p1 = (struct tlv_channel_scan_result *)tv_data; @@ -2123,6 +2105,8 @@ int handle_channel_scan_report(void *cntlr, struct cmdu_buff *cmdu) dbg("\tnum_neighbor: %d\n", num_neightbor); offset += 2; for (j = 0; j < num_neightbor; j++) { + uint8_t info = 0x00; + dbg("\n\t\tbssid: " MACFMT "\n", MAC2STR(&tv_data[offset])); offset += 6; ssid_len = tv_data[offset++]; @@ -2137,13 +2121,16 @@ int handle_channel_scan_report(void *cntlr, struct cmdu_buff *cmdu) dbg("\t\tlen: %d\n", bw_len); dbg("\t\tbwstr: %d\n", atoi((char *)&tv_data[offset])); offset += bw_len; - dbg("\t\tinfo: %d\n", tv_data[offset]); - offset++; - dbg("\t\tch_util: %d\n", tv_data[offset]); - offset++; - dbg("\t\tsta_count: %d\n", tv_data[offset]); + info = tv_data[offset]; + dbg("\t\tinfo: %d\n", offset); offset++; - offset++; /* sta_count is 2 byte*/ + + if (info & CH_SCAN_RESULT_BSSLOAD_PRESENT) { + dbg("\t\t\tch_util: %d\n", tv_data[offset]); + offset++; + dbg("\t\t\tsta_count: %d\n", tv_data[offset]); + offset += 2; + } } } dbg("\n"); -- GitLab