From 4f91d6a9fd1ec24b2e10216cbbab8081774d4686 Mon Sep 17 00:00:00 2001 From: Tri Quach Date: Thu, 10 Sep 2020 11:24:58 -0700 Subject: [PATCH] updates to address issues: #12, #13, #14, #15, #16, #17 --- scripts/consts.zeek | 36 ++++++++++++++++++++++- scripts/main.zeek | 72 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 105 insertions(+), 3 deletions(-) diff --git a/scripts/consts.zeek b/scripts/consts.zeek index f7bfbed..0e0f558 100644 --- a/scripts/consts.zeek +++ b/scripts/consts.zeek @@ -49,7 +49,7 @@ export { [4] = "Segment Acknowledge", [5] = "Error", [6] = "Reject", - [7] = "Abort ABORT" + [7] = "Abort", } &default=function(i: count):string { return fmt("apdu_type (%x)", i); } &redef; ## BACnet service choices @@ -546,6 +546,7 @@ export { const limit_enable = { [1] = "Event Low Limit Enable", [2] = "Event High Limit Enable", + [3] = "Event Both Limits Enable", } &default=function(i: count):string { return fmt("limit_enable (%x)", i); } &redef; ## BACnet action @@ -562,6 +563,9 @@ export { ## BACnet segmentations const segmentation_supports = { + [0] = "Segmented Both", + [1] = "Segmented Transmit", + [2] = "Segmented Receive", [3] = "No Segmentation", } &default=function(i: count):string { return fmt("segmentation (%x)", i); } &redef; @@ -757,6 +761,36 @@ export { [138] = "Invalid Value In This State", } &default=function(i: count):string { return fmt("error_code (%x)", i); } &redef; + ## reject reasons + const rejects = { + [0] = "Other", + [1] = "Buffer Overflow", + [2] = "Inconsistent Parameters", + [3] = "Invalid Parameter Data Type", + [4] = "Invalid Tag", + [5] = "Missing Required Parameter", + [6] = "Parameter Out Of Range", + [7] = "Too Many Arguments", + [8] = "Undefined Enumeration", + [9] = "Unrecognized Service", + } &default=function(i: count):string { return fmt("reject (%x)", i); } &redef; + + ## abort reasons + const aborts = { + [0] = "Other", + [1] = "Buffer Overflow", + [2] = "Invalid APDU In This State", + [3] = "Preempted By Higher Priority Task", + [4] = "Segmentation Not Supported", + [5] = "Security Error", + [6] = "Insufficient Security", + [7] = "Window Size Out Of Range", + [8] = "Application Exceeded Reply Time", + [9] = "Out Of Resources", + [10] = "TSM Timeout", + [11] = "APDU Too Long", + } &default=function(i: count):string { return fmt("abort (%x)", i); } &redef; + ## vendors const vendors = { [0] = "ASHRAE", diff --git a/scripts/main.zeek b/scripts/main.zeek index fbc33bb..22786e0 100644 --- a/scripts/main.zeek +++ b/scripts/main.zeek @@ -121,8 +121,45 @@ event bacnet(c:connection, is_orig:bool, if (control == 0x80 || control == 0x81) { local network_layer_message_type = bytestring_to_count(rest_of_data[rest_of_data_index]); + data[data_index] = fmt("network_layer_message=%s", network_layer_messages[network_layer_message_type]); rest_of_data_index += 1; - data[data_index] = fmt("%s", network_layer_messages[network_layer_message_type]); + data_index += 1; + ##! type, functiom, blvc len makes up 4 + bvlc_len -= 4; + ##! check if more data to parse + if (rest_of_data_index < bvlc_len) { + switch(network_layer_message_type) { + case 0x00: ##! Who Is Router To Network + break; + case 0x01: ##! I Am Router To Network + break; + case 0x02: ##! I Could Be Router To Network + break; + case 0x03, ##! Reject Message To Network + 0x04: ##! Router Busy To Network + if (network_layer_message_type == 0x03) { + ##! could enumerate if available: http://www.bacnet.org/Addenda/Add-135-2010ao.pdf#page=9 + data[data_index] = fmt("reason=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + data_index += 1; + } + local network_numbers: string = ""; + while (rest_of_data_index < bvlc_len) { + network_numbers += fmt("%d", bytestring_to_count(rest_of_data[rest_of_data_index: rest_of_data_index+2])); + rest_of_data_index += 2; + if (rest_of_data_index < bvlc_len) { + network_numbers += ";"; + } + } + data[data_index] = fmt("network_numbers=%s", network_numbers); + break; + case 0x05: ##! Router Available To Network + break; + case 0x06: ##! Initialize Routing Table + break; + case 0x07: ##! Initialize Available To Network + break; + } + } break; } else if (control == 0x08 || @@ -224,7 +261,7 @@ event bacnet(c:connection, is_orig:bool, data[data_index] = fmt("low_limit=%d", bytes_to_count(len, rest_of_data[rest_of_data_index:rest_of_data_index+len])); } else { - data[data_index] = fmt("time=%d:%02d:%02d.%d", bytestring_to_count(rest_of_data[rest_of_data_index]), + data[data_index] = fmt("time=%d:%02d:%02d.%02d", bytestring_to_count(rest_of_data[rest_of_data_index]), bytestring_to_count(rest_of_data[rest_of_data_index+1]), bytestring_to_count(rest_of_data[rest_of_data_index+2]), bytestring_to_count(rest_of_data[rest_of_data_index+3])); @@ -234,6 +271,19 @@ event bacnet(c:connection, is_orig:bool, } break; case 0x04: ##! segment ack + ##! parse data if negative ack is true + if ((apdu_type & 2) > 0) { + ##! from previous increment + rest_of_data_index -= 2; + ##! invoke id + data[data_index] = fmt("invoke_id=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + data_index += 1; + rest_of_data_index += 1; + data[data_index] = fmt("sequence_number=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + data_index += 1; + rest_of_data_index += 1; + data[data_index] = fmt("window_size=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + } break; case 0x05: ##! error c$bacnet$service_choice = confirmed_services[serviceChoice]; @@ -248,6 +298,24 @@ event bacnet(c:connection, is_orig:bool, rest_of_data_index += 1; data[data_index] = fmt("code=%s", error_codes[bytes_to_count(len, rest_of_data[rest_of_data_index:rest_of_data_index+len])]); break; + case 0x06: ##! reject + ##! from previous increment + rest_of_data_index -= 2; + ##! invoke id + data[data_index] = fmt("invoke_id=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + data_index += 1; + rest_of_data_index += 1; + data[data_index] = fmt("reason=%d", rejects[bytestring_to_count(rest_of_data[rest_of_data_index])]); + break; + case 0x07: ##! abort + ##! from previous increment + rest_of_data_index -= 2; + ##! invoke id + data[data_index] = fmt("invoke_id=%d", bytestring_to_count(rest_of_data[rest_of_data_index])); + data_index += 1; + rest_of_data_index += 1; + data[data_index] = fmt("reason=%d", aborts[bytestring_to_count(rest_of_data[rest_of_data_index])]); + break; default: c$bacnet$service_choice = confirmed_services[serviceChoice]; switch(serviceChoice) {