diff options
author | Gilbert Ramirez <gram@alumni.rice.edu> | 2004-07-18 18:06:47 +0000 |
---|---|---|
committer | Gilbert Ramirez <gram@alumni.rice.edu> | 2004-07-18 18:06:47 +0000 |
commit | 669db206cb1f270046ad400fff7655e20c63e723 (patch) | |
tree | 4eff24a2e16c8963e497e1fc575f35e6af59bd26 /epan/dissectors/packet-bacnet.c | |
parent | ae46c27a38700af669ef907491081f09df6f6b2c (diff) |
Move dissectors to epan/dissectors directory.
Also move ncp222.py, x11-fields, process-x11-fields.pl,
make-reg-dotc, and make-reg-dotc.py.
Adjust #include lines in files that include packet-*.h
files.
svn path=/trunk/; revision=11410
Diffstat (limited to 'epan/dissectors/packet-bacnet.c')
-rw-r--r-- | epan/dissectors/packet-bacnet.c | 595 |
1 files changed, 595 insertions, 0 deletions
diff --git a/epan/dissectors/packet-bacnet.c b/epan/dissectors/packet-bacnet.c new file mode 100644 index 0000000000..46053b7e5a --- /dev/null +++ b/epan/dissectors/packet-bacnet.c @@ -0,0 +1,595 @@ +/* packet-bacnet.c + * Routines for BACnet (NPDU) dissection + * Copyright 2001, Hartmut Mueller <hartmut@abmlinux.org>, FH Dortmund + * + * $Id$ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from README.developer,v 1.23 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <glib.h> + +#include <epan/packet.h> + +#include "llcsaps.h" + +static dissector_handle_t bacapp_handle; +static dissector_handle_t data_handle; + +static const char* +bacnet_mesgtyp_name (guint8 bacnet_mesgtyp){ + static const char *type_names[] = { + "Who-Is-Router-To-Network", + "I-Am-Router-To-Network", + "I-Could-Be-Router-To-Network", + "Reject-Message-To-Network", + "Router-Busy-To-Network", + "Router-Available-To-Network", + "Initialize-Routing-Table", + "Initialize-Routing-Table-Ack", + "Establish-Connection-To-Network", + "Disconnect-Connection-To-Network" + }; + if(bacnet_mesgtyp < 0x0a) { + return type_names[bacnet_mesgtyp]; + } else { + return (bacnet_mesgtyp < 0x80)? "Reserved for Use by ASHRAE" : "Vendor Proprietary Message"; + } +} + +static const char* +bacnet_rejectreason_name (guint8 bacnet_rejectreason) { + static const char *type_names[] = { + "Other error.", + "The router is not directly connected to DNET and cannot find a router to DNET on any directly connected network using Who-Is-Router-To-Network messages.", + "The router is busy and unable to accept messages for the specified DNET at the present time.", + "It is an unknown network layer message type.", + "The message is too long to be routed to this DNET.", + "The router is no longer directly connected to DNET but can reconnect if requested.", + "The router is no longer directly connected to DNET and cannot reconnect even if requested." + }; + return (bacnet_rejectreason > 6)? "Invalid Rejection Reason.": type_names[bacnet_rejectreason]; +} + +/* Network Layer Control Information */ +#define BAC_CONTROL_NET 0x80 +#define BAC_CONTROL_RES1 0x40 +#define BAC_CONTROL_DEST 0x20 +#define BAC_CONTROL_RES2 0x10 +#define BAC_CONTROL_SRC 0x08 +#define BAC_CONTROL_EXPECT 0x04 +#define BAC_CONTROL_PRIO_HIGH 0x02 +#define BAC_CONTROL_PRIO_LOW 0x01 + +/* Network Layer Message Types */ +#define BAC_NET_WHO_R 0x00 +#define BAC_NET_IAM_R 0x01 +#define BAC_NET_ICB_R 0x02 +#define BAC_NET_REJ 0x03 +#define BAC_NET_R_BUSY 0x04 +#define BAC_NET_R_AVA 0x05 +#define BAC_NET_INIT_RTAB 0x06 +#define BAC_NET_INIT_RTAB_ACK 0x07 +#define BAC_NET_EST_CON 0x08 +#define BAC_NET_DISC_CON 0x09 + +static const true_false_string control_net_set_high = { + "network layer message, message type field present.", + "BACnet APDU, message type field absent." +}; + +static const true_false_string control_res_high = { + "Shall be zero, but is one.", + "Shall be zero and is zero." +}; +static const true_false_string control_dest_high = { + "DNET, DLEN and Hop Count present. If DLEN=0: broadcast, dest. address field absent.", + "DNET, DLEN, DADR and Hop Count absent." +}; + +static const true_false_string control_src_high = { + "SNET, SLEN and SADR present, SLEN=0 invalid, SLEN specifies length of SADR", + "SNET, SLEN and SADR absent" +}; + +static const true_false_string control_expect_high = { + "BACnet-Confirmed-Request-PDU, a segment of BACnet-ComplexACK-PDU or Network Message expecting a reply present.", + "Other than a BACnet-Confirmed-Request-PDU, segment of BACnet-ComplexACK-PDU or network layer message expecting a reply present." +}; + +static const true_false_string control_prio_high_high = { + "Life Safety or Critical Equipment message.", + "Not a Life Safety or Critical Equipment message." +}; + +static const true_false_string control_prio_low_high = { + "Urgent message", + "Normal message" +}; + + +static int proto_bacnet = -1; +static int hf_bacnet_version = -1; +static int hf_bacnet_control = -1; +static int hf_bacnet_control_net = -1; +static int hf_bacnet_control_res1 = -1; +static int hf_bacnet_control_dest = -1; +static int hf_bacnet_control_res2 = -1; +static int hf_bacnet_control_src = -1; +static int hf_bacnet_control_expect = -1; +static int hf_bacnet_control_prio_high = -1; +static int hf_bacnet_control_prio_low = -1; +static int hf_bacnet_dnet = -1; +static int hf_bacnet_dlen = -1; +static int hf_bacnet_dadr_eth = -1; +static int hf_bacnet_dadr_tmp = -1; +static int hf_bacnet_snet = -1; +static int hf_bacnet_slen = -1; +static int hf_bacnet_sadr_eth = -1; +static int hf_bacnet_sadr_tmp = -1; +static int hf_bacnet_hopc = -1; +static int hf_bacnet_mesgtyp = -1; +static int hf_bacnet_vendor = -1; +static int hf_bacnet_perf = -1; +static int hf_bacnet_rejectreason = -1; +static int hf_bacnet_rportnum = -1; +static int hf_bacnet_portid = -1; +static int hf_bacnet_pinfolen = -1; +static int hf_bacnet_pinfo = -1; + +static gint ett_bacnet = -1; +static gint ett_bacnet_control = -1; + +static void +dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_item *ct; + proto_tree *bacnet_tree; + proto_tree *control_tree; + + gint offset; + guint8 bacnet_version; + guint8 bacnet_control; + guint8 bacnet_dlen; + guint8 bacnet_slen; + guint8 bacnet_mesgtyp; + guint8 bacnet_rejectreason; + guint8 bacnet_rportnum; + guint8 bacnet_pinfolen; + guint8 i; + guint8 j; + tvbuff_t *next_tvb; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU"); + + offset = 0; + bacnet_version = tvb_get_guint8(tvb, offset); + bacnet_control = tvb_get_guint8(tvb, offset+1); + bacnet_dlen = 0; + bacnet_slen = 0; + bacnet_mesgtyp = 0; + bacnet_rejectreason = 0; + bacnet_rportnum = 0; + bacnet_pinfolen =0; + i = 0; + j = 0; + +/* I don't know the length of the NPDU by now. Setting the length after dissection */ + ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, FALSE); + + bacnet_tree = proto_item_add_subtree(ti, ett_bacnet); + + proto_tree_add_uint_format(bacnet_tree, hf_bacnet_version, tvb, + offset, 1, + bacnet_version,"Version: 0x%02x (%s)",bacnet_version, + (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown"); + offset ++; + ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control, + tvb, offset, 1, bacnet_control); + control_tree = proto_item_add_subtree(ct, ett_bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_net, + tvb, offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb, + offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb, + offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb, + offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb, + offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb, + offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high, + tvb, offset, 1, bacnet_control); + proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low, + tvb, offset, 1, bacnet_control); + offset ++; + if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */ + proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, + tvb, offset, 2, FALSE); + offset += 2; + bacnet_dlen = tvb_get_guint8(tvb, offset); + /* DLEN = 0 is broadcast on dest.network */ + if( bacnet_dlen == 0) { + /* append to hf_bacnet_dlen: broadcast */ + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, + "Destination MAC Layer Address Length: %d indicates Broadcast on Destination Network", + bacnet_dlen); + offset ++; + /* going to SNET */ + } else if (bacnet_dlen==6) { + proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, + tvb, offset, 1, bacnet_dlen); + offset ++; + /* Ethernet MAC */ + proto_tree_add_item(bacnet_tree, + hf_bacnet_dadr_eth, tvb, offset, + bacnet_dlen, FALSE); + offset += bacnet_dlen; + } else if (bacnet_dlen<7) { + proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen, + tvb, offset, 1, bacnet_dlen); + offset ++; + /* Other MAC formats should be included here */ + proto_tree_add_item(bacnet_tree, + hf_bacnet_dadr_tmp, tvb, offset, + bacnet_dlen, FALSE); + offset += bacnet_dlen; + } else { + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen, + "Destination MAC Layer Address Length: %d invalid!", + bacnet_dlen); + } + } + if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */ + /* SNET */ + proto_tree_add_uint(bacnet_tree, hf_bacnet_snet, + tvb, offset, 2, tvb_get_ntohs(tvb, offset)); + offset += 2; + bacnet_slen = tvb_get_guint8(tvb, offset); + if( bacnet_slen == 0) { /* SLEN = 0 invalid */ + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_slen, tvb, offset, 1, bacnet_slen, + "Source MAC Layer Address Length: %d invalid!", + bacnet_slen); + offset ++; + } else if (bacnet_slen==6) { + /* SLEN */ + proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, + tvb, offset, 1, bacnet_slen); + offset ++; + /* Ethernet MAC */ + proto_tree_add_item(bacnet_tree, + hf_bacnet_sadr_eth, tvb, offset, + bacnet_slen, FALSE); + offset += bacnet_slen; + } else if (bacnet_slen<6) { /* LON,ARCNET,MS/TP MAC */ + /* SLEN */ + proto_tree_add_uint(bacnet_tree, hf_bacnet_slen, + tvb, offset, 1, bacnet_slen); + offset ++; + /* Other MAC formats should be included here */ + proto_tree_add_item(bacnet_tree, + hf_bacnet_sadr_tmp, tvb, offset, + bacnet_slen, FALSE); + offset += bacnet_slen; + } else { + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_slen, tvb, offset, 1, bacnet_slen, + "Source MAC Layer Address Length: %d invalid!", + bacnet_slen); + offset ++; + } + } + if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */ + proto_tree_add_item(bacnet_tree, hf_bacnet_hopc, + tvb, offset, 1, FALSE); + offset ++; + } + /* Network Layer Message Type */ + if (bacnet_control & BAC_CONTROL_NET) { + bacnet_mesgtyp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp, + "Network Layer Message Type: %02x (%s)", bacnet_mesgtyp, + bacnet_mesgtyp_name(bacnet_mesgtyp)); + offset ++; + } + /* Vendor ID + * The standard says: "If Bit 7 of the control octet is 1 and + * the Message Type field contains a value in the range + * X'80' - X'FF', then a Vendor ID field shall be present (...)." + * We should not go any further in dissecting the packet if it's + * not present, but we don't know about that: No length field... + */ + if ((bacnet_mesgtyp > 0x7f) && (bacnet_control == BAC_CONTROL_NET)) { + proto_tree_add_item(bacnet_tree, hf_bacnet_vendor, + tvb, offset, 2, FALSE); + offset += 2; + /* attention: doesnt work here because of if(tree) */ + call_dissector(data_handle, + tvb_new_subset(tvb, offset, -1, -1), pinfo, tree); + } + /* Performance Index (in I-Could-Be-Router-To-Network) */ + if (bacnet_mesgtyp == BAC_NET_ICB_R) { + proto_tree_add_item(bacnet_tree, hf_bacnet_perf, + tvb, offset, 1, FALSE); + offset ++; + } + /* Reason, DNET (in Reject-Message-To-Network) */ + if (bacnet_mesgtyp == BAC_NET_REJ) { + bacnet_rejectreason = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(bacnet_tree, + hf_bacnet_rejectreason, + tvb, offset, 1, + bacnet_rejectreason, "Rejection Reason: %d (%s)", + bacnet_rejectreason, + bacnet_rejectreason_name(bacnet_rejectreason)); + offset ++; + proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, + tvb, offset, 2, FALSE); + offset += 2; + } + /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */ + if ((bacnet_mesgtyp == BAC_NET_R_BUSY) || + (bacnet_mesgtyp == BAC_NET_R_AVA) || (bacnet_mesgtyp == BAC_NET_IAM_R) ) { + while(tvb_reported_length_remaining(tvb, offset) > 1 ) { + proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, + tvb, offset, 2, FALSE); + offset += 2; + } + } + /* Initialize-Routing-Table */ + if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) || + (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) { + bacnet_rportnum = tvb_get_guint8(tvb, offset); + /* number of ports */ + proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum, + tvb, offset, 1, bacnet_rportnum); + offset ++; + for(i=0; i>bacnet_rportnum; i++) { + /* Connected DNET */ + proto_tree_add_item(bacnet_tree, hf_bacnet_dnet, + tvb, offset, 2, FALSE); + offset += 2; + /* Port ID */ + proto_tree_add_item(bacnet_tree, hf_bacnet_portid, + tvb, offset, 1, FALSE); + offset ++; + /* Port Info Length */ + bacnet_pinfolen = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen, + tvb, offset, 1, bacnet_pinfolen); + offset ++; + for(j=0; j>bacnet_pinfolen; j++){ + /* Port Info */ + proto_tree_add_item(bacnet_tree, hf_bacnet_pinfo, + tvb, offset, 1, FALSE); + offset ++; + } + } + } + proto_item_set_len(ti, offset); + +/* dissect BACnet APDU + */ + next_tvb = tvb_new_subset(tvb,offset,-1,-1); + if (bacnet_control & BAC_CONTROL_NET) { + /* Unknown function - dissect the payload as data */ + call_dissector(data_handle, next_tvb, pinfo, tree); + } else { + /* APDU - call the APDU dissector */ + call_dissector(bacapp_handle, next_tvb, pinfo, tree); + } +} + +void +proto_register_bacnet(void) +{ + static hf_register_info hf[] = { + { &hf_bacnet_version, + { "Version", "bacnet.version", + FT_UINT8, BASE_DEC, NULL, 0, + "BACnet Version", HFILL } + }, + { &hf_bacnet_control, + { "Control", "bacnet.control", + FT_UINT8, BASE_HEX, NULL, 0, + "BACnet Control", HFILL } + }, + { &hf_bacnet_control_net, + { "NSDU contains", + "bacnet.control_net", + FT_BOOLEAN, 8, TFS(&control_net_set_high), + BAC_CONTROL_NET, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_res1, + { "Reserved", + "bacnet.control_res1", + FT_BOOLEAN, 8, TFS(&control_res_high), + BAC_CONTROL_RES1, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_dest, + { "Destination Specifier", + "bacnet.control_dest", + FT_BOOLEAN, 8, TFS(&control_dest_high), + BAC_CONTROL_DEST, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_res2, + { "Reserved", + "bacnet.control_res2", + FT_BOOLEAN, 8, TFS(&control_res_high), + BAC_CONTROL_RES2, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_src, + { "Source specifier", + "bacnet.control_src", + FT_BOOLEAN, 8, TFS(&control_src_high), + BAC_CONTROL_SRC, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_expect, + { "Expecting Reply", + "bacnet.control_expect", + FT_BOOLEAN, 8, TFS(&control_expect_high), + BAC_CONTROL_EXPECT, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_prio_high, + { "Priority", + "bacnet.control_prio_high", + FT_BOOLEAN, 8, TFS(&control_prio_high_high), + BAC_CONTROL_PRIO_HIGH, "BACnet Control", HFILL } + }, + { &hf_bacnet_control_prio_low, + { "Priority", + "bacnet.control_prio_low", + FT_BOOLEAN, 8, TFS(&control_prio_low_high), + BAC_CONTROL_PRIO_LOW, "BACnet Control", HFILL } + }, + { &hf_bacnet_dnet, + { "Destination Network Address", "bacnet.dnet", + FT_UINT16, BASE_HEX, NULL, 0, + "Destination Network Address", HFILL } + }, + { &hf_bacnet_dlen, + { "Destination MAC Layer Address Length", "bacnet.dlen", + FT_UINT8, BASE_DEC, NULL, 0, + "Destination MAC Layer Address Length", HFILL } + }, + { &hf_bacnet_dadr_eth, + { "Destination ISO 8802-3 MAC Address", "bacnet.dadr_eth", + FT_ETHER, BASE_HEX, NULL, 0, + "Destination ISO 8802-3 MAC Address", HFILL } + }, + { &hf_bacnet_dadr_tmp, + { "Unknown Destination MAC", "bacnet.dadr_tmp", + FT_BYTES, BASE_HEX, NULL, 0, + "Unknown Destination MAC", HFILL } + }, + { &hf_bacnet_snet, + { "Source Network Address", "bacnet.snet", + FT_UINT16, BASE_HEX, NULL, 0, + "Source Network Address", HFILL } + }, + { &hf_bacnet_slen, + { "Source MAC Layer Address Length", "bacnet.slen", + FT_UINT8, BASE_DEC, NULL, 0, + "Source MAC Layer Address Length", HFILL } + }, + { &hf_bacnet_sadr_eth, + { "SADR", "bacnet.sadr_eth", + FT_ETHER, BASE_HEX, NULL, 0, + "Source ISO 8802-3 MAC Address", HFILL } + }, + { &hf_bacnet_sadr_tmp, + { "Unknown Source MAC", "bacnet.sadr_tmp", + FT_BYTES, BASE_HEX, NULL, 0, + "Unknown Source MAC", HFILL } + }, + { &hf_bacnet_hopc, + { "Hop Count", "bacnet.hopc", + FT_UINT8, BASE_DEC, NULL, 0, + "Hop Count", HFILL } + }, + { &hf_bacnet_mesgtyp, + { "Message Type", "bacnet.mesgtyp", + FT_UINT8, BASE_HEX, NULL, 0, + "Message Type", HFILL } + }, + { &hf_bacnet_vendor, + { "Vendor ID", "bacnet.vendor", + FT_UINT16, BASE_HEX, NULL, 0, + "Vendor ID", HFILL } + }, + { &hf_bacnet_perf, + { "Performance Index", "bacnet.perf", + FT_UINT8, BASE_DEC, NULL, 0, + "Performance Index", HFILL } + }, + { &hf_bacnet_rejectreason, + { "Reject Reason", "bacnet.rejectreason", + FT_UINT8, BASE_DEC, NULL, 0, + "Reject Reason", HFILL } + }, + { &hf_bacnet_rportnum, + { "Number of Port Mappings", "bacnet.rportnum", + FT_UINT8, BASE_DEC, NULL, 0, + "Number of Port Mappings", HFILL } + }, + { &hf_bacnet_pinfolen, + { "Port Info Length", "bacnet.pinfolen", + FT_UINT8, BASE_DEC, NULL, 0, + "Port Info Length", HFILL } + }, + { &hf_bacnet_portid, + { "Port ID", "bacnet.portid", + FT_UINT8, BASE_HEX, NULL, 0, + "Port ID", HFILL } + }, + { &hf_bacnet_pinfo, + { "Port Info", "bacnet.pinfo", + FT_UINT8, BASE_HEX, NULL, 0, + "Port Info", HFILL } + }, + }; + + static gint *ett[] = { + &ett_bacnet, + &ett_bacnet_control, + }; + + proto_bacnet = proto_register_protocol("Building Automation and Control Network NPDU", + "BACnet", "bacnet"); + + proto_register_field_array(proto_bacnet, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("bacnet", dissect_bacnet, proto_bacnet); +} + +void +proto_reg_handoff_bacnet(void) +{ + dissector_handle_t bacnet_handle; + + bacnet_handle = find_dissector("bacnet"); + dissector_add("bvlc.function", 0x04, bacnet_handle); + dissector_add("bvlc.function", 0x09, bacnet_handle); + dissector_add("bvlc.function", 0x0a, bacnet_handle); + dissector_add("bvlc.function", 0x0b, bacnet_handle); + dissector_add("llc.dsap", SAP_BACNET, bacnet_handle); + bacapp_handle = find_dissector("bacapp"); + data_handle = find_dissector("data"); +} |