diff options
author | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-04-14 09:20:02 +0000 |
---|---|---|
committer | Ronnie Sahlberg <ronnie_sahlberg@ozemail.com.au> | 2005-04-14 09:20:02 +0000 |
commit | a5863ec066cc91e790bf839b3eb40eff451d80fd (patch) | |
tree | 28ede68419d93132a07eb5544433ddee5c1e773b /epan/dissectors/packet-bacapp.c | |
parent | 1d2c39cc60232a54f6fe906ab2b2a4b4d1175fda (diff) |
From Steve Karg
updates to BACNet
svn path=/trunk/; revision=14075
Diffstat (limited to 'epan/dissectors/packet-bacapp.c')
-rw-r--r-- | epan/dissectors/packet-bacapp.c | 744 |
1 files changed, 725 insertions, 19 deletions
diff --git a/epan/dissectors/packet-bacapp.c b/epan/dissectors/packet-bacapp.c index b89a5051c6..7f84585e75 100644 --- a/epan/dissectors/packet-bacapp.c +++ b/epan/dissectors/packet-bacapp.c @@ -1,6 +1,7 @@ /* packet-bacapp.c * Routines for BACnet (APDU) dissection * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund + * Enhanced by Steve Karg, 2005, <skarg@users.sourceforge.net> * * $Id$ * @@ -37,23 +38,294 @@ #include <epan/packet.h> +// BACnet PDU Types +#define BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST 0 +#define BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST 1 +#define BACAPP_TYPE_SIMPLE_ACK 2 +#define BACAPP_TYPE_COMPLEX_ACK 3 +#define BACAPP_TYPE_SEGMENT_ACK 4 +#define BACAPP_TYPE_ERROR 5 +#define BACAPP_TYPE_REJECT 6 +#define BACAPP_TYPE_ABORT 7 +#define MAX_BACAPP_TYPE 8 + +static const value_string bacapp_type_names[] = { + { BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST, "Confirmed-Request" }, + { BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST, "Unconfirmed-Request" }, + { BACAPP_TYPE_SIMPLE_ACK, "SimpleACK" }, + { BACAPP_TYPE_COMPLEX_ACK, "ComplexACK" }, + { BACAPP_TYPE_SEGMENT_ACK, "SegmentACK" }, + { BACAPP_TYPE_ERROR, "Error" }, + { BACAPP_TYPE_REJECT, "Reject" }, + { BACAPP_TYPE_ABORT, "Abort" }, + { 0, NULL } +}; +static const char *bacapp_unknown_str = "unknown"; +static const char *bacapp_unknown_service_str = "unknown service"; + +static const value_string bacapp_confirmed_service_names[] = { + { 0, "Acknowledge-Alarm" }, + { 1, "COV-Notification" }, + { 2, "Event-Notification" }, + { 3, "Get-Alarm-Summary" }, + { 4, "Get-Enrollment-Summary" }, + { 5, "Subscribe-COV" }, + { 6, "Atomic-Read-File" }, + { 7, "Atomic-Write-File" }, + { 8, "Add-List-Element" }, + { 9, "Remove-List-Element" }, + { 10, "Create-Object" }, + { 11, "Delete-Object" }, + { 12, "Read-Property" }, + { 13, "Read-Property-Conditional" }, + { 14, "Read-Property-Multiple" }, + { 15, "Write-Property" }, + { 16, "Write-Property-Multiple" }, + { 17, "Device-Communication-Control" }, + { 18, "Private-Transfer" }, + { 19, "Text-Message" }, + { 20, "Reinitialize-Device" }, + { 21, "VT-Open" }, + { 22, "VT-Close" }, + { 23, "VT-Data" }, + { 24, "Authenticate" }, + { 25, "Request-Key" }, + { 26, "Read-Range" }, + { 27, "Life-Safety_Operation" }, + { 28, "Subscribe-COV-Property" }, + { 29, "Get-Event-Information" }, + { 0, NULL } +}; + +#define SERVICE_UNCONFIRMED_I_AM 0 +#define SERVICE_UNCONFIRMED_I_HAVE 1 +#define SERVICE_UNCONFIRMED_COV_NOTIFICATION 2 +#define SERVICE_UNCONFIRMED_EVENT_NOTIFICATION 3 +#define SERVICE_UNCONFIRMED_PRIVATE_TRANSFER 4 +#define SERVICE_UNCONFIRMED_TEXT_MESSAGE 5 +#define SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION 6 +#define SERVICE_UNCONFIRMED_WHO_HAS 7 +#define SERVICE_UNCONFIRMED_WHO_IS 8 +#define SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION 9 +/* Other services to be added as they are defined. + All choice values in this production are reserved + for definition by ASHRAE. + Proprietary extensions are made by using the + UnconfirmedPrivateTransfer service. See Clause 23. +*/ +#define MAX_BACNET_UNCONFIRMED_SERVICE 10 + +static const value_string bacapp_unconfirmed_service_names[] = { + { SERVICE_UNCONFIRMED_I_AM, "I-Am" }, + { SERVICE_UNCONFIRMED_I_HAVE, "I-Have" }, + { SERVICE_UNCONFIRMED_COV_NOTIFICATION, "COV-Notification" }, + { SERVICE_UNCONFIRMED_EVENT_NOTIFICATION, "Event-Notification" }, + { SERVICE_UNCONFIRMED_PRIVATE_TRANSFER, "Private-Transfer" }, + { SERVICE_UNCONFIRMED_TEXT_MESSAGE, "Text-Message" }, + { SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION, "Time-Synchronization" }, + { SERVICE_UNCONFIRMED_WHO_HAS, "Who-Has" }, + { SERVICE_UNCONFIRMED_WHO_IS, "Who-Is" }, + { SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, "UTC-Time-Synchronization" }, + { 0, NULL } +}; + +static const char* +bacapp_reject_reason_name (guint8 bacapp_reason){ + static const char *reason_names[] = { + "Other", + "Buffer Overflow", + "Inconsistent Parameters", + "Invalid Parameter Data Type", + "Invalid Tag", + "Missing Required Parameter", + "Parameter Out of Range", + "Too Many Arguments", + "Undefined Enumeration", + "Unrecognized Service" + }; + if (bacapp_reason < 10) + return reason_names[bacapp_reason]; + else if (bacapp_reason < 64) + return "Reserved for Use by ASHRAE"; + + return "Vendor Proprietary Reason"; +} + static const char* -bacapp_type_name (guint8 bacapp_type){ - static const char *type_names[] = { - "Confirmed-Request-PDU", - "Unconfirmed-Request-PDU", - "SimpleACK-PDU", - "ComplexACK-PDU", - "SegmentACK-PDU", - "Error-PDU", - "Reject-PDU", - "Abort-PDU" +bacapp_abort_reason_name (guint8 bacapp_reason){ + static const char *reason_names[] = { + "Other", + "Buffer Overflow", + "Invalid APDU in this State", + "Preempted by Higher Priority Task", + "Segmentation Not Supported" }; - return (bacapp_type > 7)? "unknown PDU" : type_names[bacapp_type]; + if (bacapp_reason < 5) + return reason_names[bacapp_reason]; + else if (bacapp_reason < 64) + return "Reserved for Use by ASHRAE"; + + return "Vendor Proprietary Reason"; +} + +/* from clause 20.1.2.4 max-segments-accepted + returns the decoded value + + max-segments-accepted + B'000' Unspecified number of segments accepted. + B'001' 2 segments accepted. + B'010' 4 segments accepted. + B'011' 8 segments accepted. + B'100' 16 segments accepted. + B'101' 32 segments accepted. + B'110' 64 segments accepted. + B'111' Greater than 64 segments accepted. +*/ +static guint8 decode_max_segs(guint8 octet) +{ + guint8 max_segs = 0; + + switch (octet & 0xF0) + { + case 0: + max_segs = 0; + break; + case 0x10: + max_segs = 2; + break; + case 0x20: + max_segs = 4; + break; + case 0x30: + max_segs = 8; + break; + case 0x40: + max_segs = 16; + break; + case 0x50: + max_segs = 32; + break; + case 0x60: + max_segs = 64; + break; + case 0x70: + max_segs = 65; + break; + default: + break; + } + + return max_segs; +} + +/* from clause 20.1.2.5 max-APDU-length-accepted + returns the decoded value + + max-APDU-length-accepted + B'0000' Up to MinimumMessageSize (50 octets) + B'0001' Up to 128 octets + B'0010' Up to 206 octets (fits in a LonTalk frame) + B'0011' Up to 480 octets (fits in an ARCNET frame) + B'0100' Up to 1024 octets + B'0101' Up to 1476 octets (fits in an ISO 8802-3 frame) + B'0110' reserved by ASHRAE + B'0111' reserved by ASHRAE + B'1000' reserved by ASHRAE + B'1001' reserved by ASHRAE + B'1010' reserved by ASHRAE + B'1011' reserved by ASHRAE + B'1100' reserved by ASHRAE + B'1101' reserved by ASHRAE + B'1110' reserved by ASHRAE + B'1111' reserved by ASHRAE +*/ +static guint16 decode_max_apdu(guint8 octet) +{ + guint16 max_apdu = 0; + + switch (octet & 0x0F) + { + case 0: + max_apdu = 50; + break; + case 1: + max_apdu = 128; + break; + case 2: + max_apdu = 206; + break; + case 3: + max_apdu = 480; + break; + case 4: + max_apdu = 1024; + break; + case 5: + max_apdu = 1476; + break; + default: + break; + } + + return max_apdu; } +#define BACAPP_SEGMENTED_REQUEST 0x08 +static const true_false_string tfs_segmented_request = { + "Segmented Request.", + "Unsegmented Request." +}; +#define BACAPP_MORE_SEGMENTS 0x04 +static const true_false_string tfs_more_segments = { + "More Segments Follow.", + "No More Segments Follow." +}; +#define BACAPP_SEGMENTED_RESPONSE 0x02 +static const true_false_string tfs_segmented_response = { + "Segmented Response Accepted.", + "Segmented Response Not Accepted." +}; +#define BACAPP_SEGMENT_NAK 0x02 +static const true_false_string tfs_segment_nak = { + "Negative Acknowledgement. Segment out of Order.", + "Normal Acknowledgement." +}; +#define BACAPP_SENT_BY 0x01 +static const true_false_string tfs_sent_by = { + "Sent By Server.", + "Sent By Client." +}; +static const true_false_string tfs_reserved_bit = { + "Shall be zero, but is one.", + "Shall be zero and is zero." +}; + static int proto_bacapp = -1; + static int hf_bacapp_type = -1; +static int hf_bacapp_segmented_request = -1; +static int hf_bacapp_more_segments = -1; +static int hf_bacapp_segmented_response = -1; +static int hf_bacapp_max_segments = -1; +static int hf_bacapp_max_response = -1; +static int hf_bacapp_invoke_id = -1; +static int hf_bacapp_sequence_number = -1; +static int hf_bacapp_window_size = -1; +static int hf_bacapp_service_choice = -1; +static int hf_bacapp_segment_nak = -1; +static int hf_bacapp_sent_by = -1; +static int hf_bacapp_error_choice = -1; +static int hf_bacapp_reject_reason = -1; +static int hf_bacapp_abort_reason = -1; +/* generic reserved bits */ +static int hf_bacapp_reserved_bit_0 = -1; +static int hf_bacapp_reserved_bit_1 = -1; +static int hf_bacapp_reserved_bit_2 = -1; +static int hf_bacapp_reserved_bit_3 = -1; +static int hf_bacapp_reserved_bit_4 = -1; +static int hf_bacapp_reserved_bit_5 = -1; +static int hf_bacapp_reserved_bit_6 = -1; +static int hf_bacapp_reserved_bit_7 = -1; static gint ett_bacapp = -1; @@ -66,6 +338,15 @@ dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree *bacapp_tree; guint8 offset; guint8 bacapp_type; + guint8 bacapp_type_seg; + guint8 bacapp_service; + guint8 bacapp_reason; + guint8 bacapp_max_seg_resp; + guint8 bacapp_invoke_id; + guint8 bacapp_sequence_number; + guint8 bacapp_window_size; + guint8 max_segs; + guint16 max_apdu; tvbuff_t *next_tvb; if (check_col(pinfo->cinfo, COL_PROTOCOL)) @@ -74,11 +355,80 @@ dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) col_add_str(pinfo->cinfo, COL_INFO, "BACnet APDU "); offset = 0; - bacapp_type = (tvb_get_guint8(tvb, offset) >> 4) & 0x0f; - + bacapp_type_seg = tvb_get_guint8(tvb, offset); + bacapp_type = (bacapp_type_seg >> 4) & 0xf; + + /* show some descriptive text in the INFO column */ if (check_col(pinfo->cinfo, COL_INFO)) - col_append_fstr(pinfo->cinfo, COL_INFO, "(%s)", - bacapp_type_name(bacapp_type)); + { + col_clear(pinfo->cinfo, COL_INFO); + col_add_str(pinfo->cinfo, COL_INFO, + val_to_str(bacapp_type, bacapp_type_names, bacapp_unknown_str)); + switch (bacapp_type) + { + case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: + /* segmented messages have 2 additional bytes */ + if (bacapp_type_seg & BACAPP_SEGMENTED_REQUEST) + bacapp_service = tvb_get_guint8(tvb, offset + 5); + else + bacapp_service = tvb_get_guint8(tvb, offset + 3); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + break; + case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: + bacapp_service = tvb_get_guint8(tvb, offset + 1); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + val_to_str(bacapp_service, + bacapp_unconfirmed_service_names, + bacapp_unknown_service_str)); + break; + case BACAPP_TYPE_SIMPLE_ACK: + bacapp_service = tvb_get_guint8(tvb, offset + 2); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + break; + case BACAPP_TYPE_COMPLEX_ACK: + /* segmented messages have 2 additional bytes */ + if (bacapp_type_seg & BACAPP_SEGMENTED_REQUEST) + bacapp_service = tvb_get_guint8(tvb, offset + 4); + else + bacapp_service = tvb_get_guint8(tvb, offset + 2); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + break; + case BACAPP_TYPE_SEGMENT_ACK: + /* nothing more to add */ + break; + case BACAPP_TYPE_ERROR: + bacapp_service = tvb_get_guint8(tvb, offset + 2); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + break; + case BACAPP_TYPE_REJECT: + bacapp_reason = tvb_get_guint8(tvb, offset + 2); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + bacapp_reject_reason_name(bacapp_reason)); + break; + case BACAPP_TYPE_ABORT: + bacapp_reason = tvb_get_guint8(tvb, offset + 2); + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", + bacapp_abort_reason_name(bacapp_reason)); + break; + /* UNKNOWN */ + default: + /* nothing more to add */ + break; + } + } + if (tree) { ti = proto_tree_add_item(tree, proto_bacapp, tvb, offset, -1, FALSE); @@ -86,9 +436,240 @@ dissect_bacapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_uint_format(bacapp_tree, hf_bacapp_type, tvb, offset, 1, bacapp_type, "APDU Type: %u (%s)", bacapp_type, - bacapp_type_name(bacapp_type)); - offset ++; - + val_to_str(bacapp_type, bacapp_type_names, bacapp_unknown_str)); + switch (bacapp_type) + { + case BACAPP_TYPE_CONFIRMED_SERVICE_REQUEST: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_segmented_request, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_more_segments, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_segmented_response, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_max_seg_resp = tvb_get_guint8(tvb, offset); + max_segs = decode_max_segs(bacapp_max_seg_resp); + if (max_segs > 64) + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_max_segments, + tvb, offset, 1, bacapp_max_seg_resp, + "Maximum Segments Accepted: %u " + "(Greater than 64 segments accepted).", + ((bacapp_max_seg_resp >> 4) & 0x0f)); + else + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_max_segments, + tvb, offset, 1, bacapp_max_seg_resp, + "Maximum Segments Accepted: %u (%u segments accepted).", + ((bacapp_max_seg_resp >> 4) & 0x0f), max_segs); + max_apdu = decode_max_apdu(bacapp_max_seg_resp); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_max_response, + tvb, offset, 1, bacapp_max_seg_resp, + "Maximum APDU Accepted: %u (%u octets)", + bacapp_max_seg_resp,max_apdu); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + /* segmented messages have 2 additional bytes */ + if (bacapp_type_seg & BACAPP_SEGMENTED_REQUEST) + { + bacapp_sequence_number = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_sequence_number, + tvb, offset, 1, bacapp_sequence_number); + offset++; + bacapp_window_size = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_window_size, + tvb, offset, 1, bacapp_window_size); + offset++; + } + bacapp_service = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_service_choice, + tvb, offset, 1, bacapp_service, + "Service Choice: %u (%s)", bacapp_service, + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + offset++; + break; + case BACAPP_TYPE_UNCONFIRMED_SERVICE_REQUEST: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_service = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_service_choice, + tvb, offset, 1, bacapp_service, + "Service Choice: %u (%s)", bacapp_service, + val_to_str(bacapp_service, + bacapp_unconfirmed_service_names, + bacapp_unknown_service_str)); + offset++; + break; + case BACAPP_TYPE_SIMPLE_ACK: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + bacapp_service = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_service_choice, + tvb, offset, 1, bacapp_service, + "Service Choice: %u (%s)", bacapp_service, + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + offset++; + break; + case BACAPP_TYPE_COMPLEX_ACK: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_segmented_request, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_more_segments, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + /* segmented messages have 2 additional bytes */ + if (bacapp_type_seg & BACAPP_SEGMENTED_REQUEST) + { + bacapp_sequence_number = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_sequence_number, + tvb, offset, 1, bacapp_sequence_number); + offset++; + bacapp_window_size = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_window_size, + tvb, offset, 1, bacapp_window_size); + offset++; + } + bacapp_service = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_service_choice, + tvb, offset, 1, bacapp_service, + "Service Choice: %u (%s)", bacapp_service, + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + offset++; + break; + case BACAPP_TYPE_SEGMENT_ACK: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_segment_nak, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_sent_by, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + bacapp_sequence_number = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_sequence_number, + tvb, offset, 1, bacapp_sequence_number); + offset++; + bacapp_window_size = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_window_size, + tvb, offset, 1, bacapp_window_size); + offset++; + break; + case BACAPP_TYPE_ERROR: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + bacapp_service = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_error_choice, + tvb, offset, 1, bacapp_service, + "Error Choice: %u (%s)", bacapp_service, + val_to_str(bacapp_service, + bacapp_confirmed_service_names, + bacapp_unknown_service_str)); + offset++; + break; + case BACAPP_TYPE_REJECT: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + bacapp_reason = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_reject_reason, + tvb, offset, 1, bacapp_reason, + "Reject Reason: %u (%s)", bacapp_reason, + bacapp_reject_reason_name(bacapp_reason)); + offset++; + break; + case BACAPP_TYPE_ABORT: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + bacapp_invoke_id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacapp_tree, hf_bacapp_invoke_id, + tvb, offset, 1, bacapp_invoke_id); + offset++; + bacapp_reason = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacapp_tree, hf_bacapp_reject_reason, + tvb, offset, 1, bacapp_reason, + "Abort Reason: %u (%s)", bacapp_reason, + bacapp_abort_reason_name(bacapp_reason)); + offset++; + break; + default: + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_3, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_2, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_1, + tvb, offset, 1, bacapp_type_seg); + proto_tree_add_boolean(bacapp_tree, hf_bacapp_reserved_bit_0, + tvb, offset, 1, bacapp_type_seg); + offset++; + break; + } } next_tvb = tvb_new_subset(tvb,offset,-1,-1); call_dissector(data_handle,next_tvb, pinfo, tree); @@ -100,10 +681,135 @@ proto_register_bacapp(void) { static hf_register_info hf[] = { { &hf_bacapp_type, - { "APDU Type", "bacapp.bacapp_type", + { "APDU Type", + "bacapp.apdu_type", FT_UINT8, BASE_DEC, NULL, 0xf0, "APDU Type", HFILL } }, + { &hf_bacapp_segmented_request, + { "Segmented Request", + "bacapp.segmented_request", + FT_BOOLEAN, 8, TFS(&tfs_segmented_request), + BACAPP_SEGMENTED_REQUEST, "Segmented Request", HFILL } + }, + { &hf_bacapp_more_segments, + { "More Segments", + "bacapp.more_segments", + FT_BOOLEAN, 8, TFS(&tfs_more_segments), + BACAPP_MORE_SEGMENTS, "More Segments", HFILL } + }, + { &hf_bacapp_segmented_response, + { "Segmented Response", + "bacapp.segmented_response", + FT_BOOLEAN, 8, TFS(&tfs_segmented_response), + BACAPP_SEGMENTED_RESPONSE, "Segmented Response", HFILL } + }, + { &hf_bacapp_max_segments, + { "Maximum Segments Accepted", + "bacapp.max_segments_accepted", + FT_UINT8, BASE_DEC, NULL, 0x70, "Maximum Segments Accepted", HFILL } + }, + { &hf_bacapp_max_response, + { "Maximum APDU accepted", + "bacapp.max_apdu_accepted", + FT_UINT8, BASE_DEC, NULL, 0x0f, "Maximum APDU accepted", HFILL } + }, + { &hf_bacapp_invoke_id, + { "Invoke ID", + "bacapp.invoke_id", + FT_UINT8, BASE_DEC, NULL, 0, "Invoke ID", HFILL } + }, + { &hf_bacapp_sequence_number, + { "Sequence Number", + "bacapp.segment_sequence_number", + FT_UINT8, BASE_DEC, NULL, 0, "Sequence Number", HFILL } + }, + { &hf_bacapp_window_size, + { "Proposed Window Size", + "bacapp.segment_window_size", + FT_UINT8, BASE_DEC, NULL, 0, "Proposed Window Size", HFILL } + }, + { &hf_bacapp_service_choice, + { "Service Choice", + "bacapp.service_choice", + FT_UINT8, BASE_DEC, NULL, 0, "Service Choice", HFILL } + }, + { &hf_bacapp_segment_nak, + { "Segment NAK", + "bacapp.segment_nak", + FT_BOOLEAN, 8, TFS(&tfs_segment_nak), + BACAPP_SEGMENT_NAK, "Segment NAK", HFILL } + }, + { &hf_bacapp_sent_by, + { "Sent By", + "bacapp.segment_sent_by", + FT_BOOLEAN, 8, TFS(&tfs_sent_by), + BACAPP_SENT_BY, "Sent By", HFILL } + }, + { &hf_bacapp_error_choice, + { "Error Choice", + "bacapp.error_choice", + FT_UINT8, BASE_DEC, NULL, 0, "Error Choice", HFILL } + }, + { &hf_bacapp_reject_reason, + { "Reject Reason", + "bacapp.reject_reason", + FT_UINT8, BASE_DEC, NULL, 0, "Reject Reason", HFILL } + }, + { &hf_bacapp_abort_reason, + { "Abort Reason", + "bacapp.abort_reason", + FT_UINT8, BASE_DEC, NULL, 0, "Abort Reason", HFILL } + }, + { &hf_bacapp_reserved_bit_0, + { "Reserved Bit 0", + "bacapp.reserved_bit_0", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x01, "Reserved Bit 0", HFILL } + }, + { &hf_bacapp_reserved_bit_1, + { "Reserved Bit 1", + "bacapp.reserved_bit_1", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x02, "Reserved Bit 1", HFILL } + }, + { &hf_bacapp_reserved_bit_2, + { "Reserved Bit 2", + "bacapp.reserved_bit_2", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x04, "Reserved Bit 2", HFILL } + }, + { &hf_bacapp_reserved_bit_3, + { "Reserved Bit 3", + "bacapp.reserved_bit_3", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x08, "Reserved Bit 3", HFILL } + }, + { &hf_bacapp_reserved_bit_4, + { "Reserved Bit 4", + "bacapp.reserved_bit_4", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x10, "Reserved Bit 4", HFILL } + }, + { &hf_bacapp_reserved_bit_5, + { "Reserved Bit 5", + "bacapp.reserved_bit_5", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x20, "Reserved Bit 5", HFILL } + }, + { &hf_bacapp_reserved_bit_6, + { "Reserved Bit 6", + "bacapp.reserved_bit_6", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x40, "Reserved Bit 6", HFILL } + }, + { &hf_bacapp_reserved_bit_7, + { "Reserved Bit 7", + "bacapp.reserved_bit_7", + FT_BOOLEAN, 8, TFS(&tfs_reserved_bit), + 0x80, "Reserved Bit 7", HFILL } + }, }; + static gint *ett[] = { &ett_bacapp, }; |