summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-lon.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-lon.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-lon.c')
-rw-r--r--epan/dissectors/packet-lon.c767
1 files changed, 767 insertions, 0 deletions
diff --git a/epan/dissectors/packet-lon.c b/epan/dissectors/packet-lon.c
new file mode 100644
index 00000000..33ce5566
--- /dev/null
+++ b/epan/dissectors/packet-lon.c
@@ -0,0 +1,767 @@
+/* packet-lon.c
+ * Traffic analyzer for Lontalk/EIA-709.1 networks
+ * Daniel Willmann <daniel@totalueberwachung.de>
+ * (c) 2011 Daniel Willmann
+ *
+ * Used some code by habibi_khalid <khalidhabibi@gmx.de> and
+ * Honorine_KEMGNE_NGUIFFO <honorinekemgne@yahoo.fr> from
+ * https://gitlab.com/wireshark/wireshark/-/issues/4704
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include <epan/expert.h>
+
+void proto_register_lon(void);
+void proto_reg_handoff_lon(void);
+
+static dissector_handle_t lon_handle;
+
+static const value_string pdu_fmt_vs[]=
+{
+ {0x00, "TPDU"},
+ {0x01, "SPDU"},
+ {0x02, "AuthPDU"},
+ {0x03, "APDU"},
+ {0, NULL}
+};
+
+static const value_string addr_fmt_vs[]=
+{
+ {0x00, "Broadcast (0)"},
+ {0x01, "Multicast (1)"},
+ {0x02, "Unicast (2a)/Multicast (2b)"},
+ {0x03, "Unicast (3)"},
+ {0, NULL}
+};
+
+static const value_string domain_length_vs[]=
+{
+ {0x00, "0 bit"},
+ {0x01, "8 bit"},
+ {0x02, "24 bit"},
+ {0x03, "48 bit"},
+ {0, NULL}
+};
+
+static const value_string tpdu_type_vs[]=
+{
+ {0x00, "ACKD"},
+ {0x01, "UnACKD_RPT"},
+ {0x02, "ACK"},
+ {0x04, "REMINDER"},
+ {0x05, "REM/MSG"},
+ {0, NULL}
+};
+
+static const value_string spdu_type_vs[]=
+{
+ {0x00, "REQUEST"},
+ {0x02, "RESPONSE"},
+ {0x04, "REMINDER"},
+ {0x05, "REM/MSG"},
+ {0, NULL}
+};
+
+static const value_string authpdu_type_vs[]=
+{
+ {0x00, "CHALLENGE"},
+ {0x02, "REPLY"},
+ {0, NULL}
+};
+
+static const value_string nm_code_vs[]=
+{
+ {0x61, "NM_QUERY_ID"},
+ {0x62, "NM_RESPOND_TO_QUERY"},
+ {0x63, "NM_UPDATE_DOMAIN"},
+ {0x64, "NM_LEAVE_DOMAIN"},
+ {0x65, "NM_UPDATE_KEY"},
+ {0x66, "NM_UPDATE_ADDR"},
+ {0x67, "NM_QUERY_ADDR"},
+ {0x68, "NM_QUERY_NV_CNFG"},
+ {0x69, "NM_UPDATE_GROUP_ADDR"},
+ {0x6A, "NM_QUERY_DOMAIN"},
+ {0x6B, "NM_UPDATE_NV_CNFG"},
+ {0x6C, "NM_SET_NODE_MODE"},
+ {0x6D, "NM_READ_MEMORY"},
+ {0x6E, "NM_WRITE_MEMORY"},
+ {0x6F, "NM_CHECKSUM_RECALC"},
+ {0x70, "NM_WINK"},
+ {0x71, "NM_MEMORY_REFRESH"},
+ {0x72, "NM_QUERY_SNVT"},
+ {0x73, "NM_NV_FETCH"},
+ {0x7F, "NM_MANUAL_SERVICE_REQUEST"},
+ { 0, NULL}
+};
+
+static const value_string nd_code_vs[]=
+{
+ {0x51, "ND_QUERY_STATUS"},
+ {0x52, "ND_PROXY_COMMAND"},
+ {0x53, "ND_CLEAR_STATUS"},
+ {0x54, "ND_QUERY_XCVR"},
+ {0, NULL}
+};
+
+static gint hf_lon_ppdu = -1;
+static gint hf_lon_ppdu_prio = -1;
+static gint hf_lon_ppdu_alt = -1;
+static gint hf_lon_ppdu_deltabl = -1;
+static gint hf_lon_npdu = -1;
+static gint hf_lon_npdu_version = -1;
+static gint hf_lon_npdu_pdu_fmt = -1;
+static gint hf_lon_npdu_addr_fmt = -1;
+static gint hf_lon_npdu_dom_len = -1;
+static gint hf_lon_addr_srcsub = -1;
+static gint hf_lon_addr_srcnode = -1;
+static gint hf_lon_addr_dstsub = -1;
+static gint hf_lon_addr_dstgrp = -1;
+static gint hf_lon_addr_dstnode = -1;
+static gint hf_lon_addr_grp = -1;
+static gint hf_lon_addr_grpmem = -1;
+static gint hf_lon_addr_uid = -1;
+static gint hf_lon_name = -1;
+static gint hf_lon_domain = -1;
+static gint hf_lon_tpdu = -1;
+static gint hf_lon_auth = -1;
+static gint hf_lon_tpdu_tpdu_type = -1;
+static gint hf_lon_trans_no = -1;
+static gint hf_lon_spdu = -1;
+static gint hf_lon_spdu_spdu_type = -1;
+static gint hf_lon_mlen = -1;
+static gint hf_lon_mlist = -1;
+static gint hf_lon_authpdu = -1;
+static gint hf_lon_authpdu_fmt = -1;
+static gint hf_lon_authpdu_authpdu_type = -1;
+static gint hf_lon_nv_dir = -1;
+static gint hf_lon_nv_selector = -1;
+static gint hf_lon_app_code = -1;
+static gint hf_lon_nm_code = -1;
+static gint hf_lon_nd_code = -1;
+static gint hf_lon_ff_code = -1;
+static gint hf_lon_nv = -1;
+static gint hf_lon_app = -1;
+static gint hf_lon_nm = -1;
+static gint hf_lon_nd = -1;
+static gint hf_lon_ff = -1;
+/* static gint hf_lon_checksum = -1; */
+static gint proto_lon = -1;
+
+
+static gint ett_lon = -1;
+static gint ett_ppdu = -1;
+static gint ett_npdu = -1;
+static gint ett_tpdu = -1;
+static gint ett_spdu = -1;
+static gint ett_authpdu = -1;
+static gint ett_apdu = -1;
+static gint ett_nv = -1;
+static gint ett_app = -1;
+static gint ett_nm = -1;
+static gint ett_nd = -1;
+static gint ett_ff = -1;
+
+static gint ett_address = -1;
+
+static expert_field ei_lon_tpdu_tpdu_type_unknown = EI_INIT;
+static expert_field ei_lon_tpdu_spdu_type_unknown = EI_INIT;
+static expert_field ei_lon_tpdu_authpdu_type_unknown = EI_INIT;
+static expert_field ei_lon_tpdu_apdu_dest_type = EI_INIT;
+
+static gint dissect_apdu(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ gint offset);
+
+static gint
+dissect_lon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
+{
+ gint offset = 0;
+
+ gint pdu_fmt, addr_fmt, dom_len, pdutype, length;
+ gint addr_a;
+
+ proto_tree *ti;
+ proto_tree *lon_tree;
+ gint npdu, type;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LON");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ npdu = tvb_get_guint8(tvb, 0);
+ type = tvb_get_guint8(tvb, 1);
+ type = (type&0x30)>>4;
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%sDelta_BL: %i Type: %s",
+ npdu&0x80?"Priority ":"",
+ npdu&0x3F,
+ val_to_str_const(type, pdu_fmt_vs, "Unknown"));
+
+ ti = proto_tree_add_item(tree, proto_lon, tvb, offset, -1, ENC_NA);
+ lon_tree = proto_item_add_subtree(ti, ett_lon);
+
+ {
+ static int * const ppdu_fields[] = {
+ &hf_lon_ppdu_prio,
+ &hf_lon_ppdu_alt,
+ &hf_lon_ppdu_deltabl,
+ NULL
+ };
+ proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_ppdu,
+ ett_ppdu, ppdu_fields, ENC_BIG_ENDIAN);
+ offset++;
+ }
+ {
+ static int * const npdu_fields[] = {
+ &hf_lon_npdu_version,
+ &hf_lon_npdu_pdu_fmt,
+ &hf_lon_npdu_addr_fmt,
+ &hf_lon_npdu_dom_len,
+ NULL
+ };
+ proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_npdu,
+ ett_npdu, npdu_fields, ENC_BIG_ENDIAN);
+
+ pdu_fmt = (tvb_get_guint8(tvb, offset) >> 4) & 0x03;
+ addr_fmt = (tvb_get_guint8(tvb, offset) >> 2) & 0x03;
+ dom_len = tvb_get_guint8(tvb, offset) & 0x03;
+ offset++;
+ }
+ /* Address part */
+ switch(addr_fmt)
+ {
+ case 0: /* Broadcast */
+ ti = proto_tree_add_subtree(lon_tree, tvb, offset, 3, ett_address, NULL, "Address type 0 (broadcast)");
+ proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ offset += 3;
+ break;
+ case 1: /* Multicast */
+ ti = proto_tree_add_subtree(lon_tree, tvb, offset, 3, ett_address, NULL, "Address type 1 (multicast)");
+ proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstgrp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ offset += 3;
+ break;
+ case 2: /* Unicast/Multicast */
+ addr_a = tvb_get_guint8(tvb, offset+1) >> 7;
+ if (addr_a) { /* Type 2a */
+ ti = proto_tree_add_subtree(lon_tree, tvb, offset, 4, ett_address, NULL, "Address type 2a (unicast)");
+ proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstnode, tvb, offset+3, 1, ENC_BIG_ENDIAN);
+ offset += 4;
+ } else { /* Type 2b */
+ ti = proto_tree_add_subtree(lon_tree, tvb, offset, 6, ett_address, NULL, "Address type 2b (multicast)");
+ proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstgrp, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstnode, tvb, offset+3, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_grp, tvb, offset+4, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_grpmem, tvb, offset+5, 1, ENC_BIG_ENDIAN);
+ offset += 6;
+ }
+ break;
+ case 3: /* UID */
+ ti = proto_tree_add_subtree(lon_tree, tvb, offset, 9, ett_address, NULL, "Address type 3 (UID)");
+ proto_tree_add_item(ti, hf_lon_addr_srcsub, tvb, offset, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_srcnode, tvb, offset+1, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_dstsub, tvb, offset+2, 1, ENC_BIG_ENDIAN);
+ proto_tree_add_item(ti, hf_lon_addr_uid, tvb, offset+3, 6, ENC_NA);
+ offset += 9;
+ break;
+ }
+ /* END Address part */
+ /* Domain */
+ switch(dom_len)
+ {
+ case 0: /* Domain-wide */
+ proto_tree_add_bytes_format(lon_tree, hf_lon_domain, tvb, offset, 0, NULL, "Domain wide addressing");
+ break;
+ case 1:
+ proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 1, ENC_NA);
+ offset++;
+ break;
+ case 2:
+ proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 3, ENC_NA);
+ offset += 3;
+ break;
+ case 3:
+ proto_tree_add_item(lon_tree, hf_lon_domain, tvb, offset, 6, ENC_NA);
+ offset += 6;
+ break;
+ }
+ /* END Domain */
+ /* *PDU */
+ switch(pdu_fmt)
+ {
+ case 0: /* TPDU */
+ {
+ static int * const tpdu_fields[] = {
+ &hf_lon_auth,
+ &hf_lon_tpdu_tpdu_type,
+ &hf_lon_trans_no,
+ NULL
+ };
+ proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_tpdu,
+ ett_tpdu, tpdu_fields, ENC_BIG_ENDIAN);
+
+ pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x07;
+ offset++;
+ switch(pdutype)
+ {
+ case 0:
+ case 1: /* ACKD and UnACKD_RPT */
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ case 2: /* ACK */
+ break;
+ case 4: /* REMINDER */
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
+ offset += length;
+ break;
+ case 5: /* REM/MSG */
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ if (length > 0)
+ proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
+ offset += length;
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ default:
+ expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_tpdu_type_unknown, "Unexpected TPDU type %i", pdutype);
+ break;
+ }
+ }
+ break;
+ case 1: /* SPDU */
+ {
+ static int * const spdu_fields[] = {
+ &hf_lon_auth,
+ &hf_lon_spdu_spdu_type,
+ &hf_lon_trans_no,
+ NULL
+ };
+ proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_spdu,
+ ett_spdu, spdu_fields, ENC_BIG_ENDIAN);
+ pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x07;
+ offset++;
+ switch(pdutype)
+ {
+ case 0: /* REQUEST */
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ case 2: /* RESPONSE */
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ case 4: /* REMINDER */
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
+ offset += length;
+ break;
+ case 5: /* REM/MSG */
+ length = tvb_get_guint8(tvb, offset);
+ proto_tree_add_item(lon_tree, hf_lon_mlen, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset++;
+ if (length > 0)
+ proto_tree_add_item(lon_tree, hf_lon_mlist, tvb, offset, length, ENC_BIG_ENDIAN);
+ offset += length;
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ default:
+ expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_spdu_type_unknown, "Unexpected SPDU type %i", pdutype);
+ break;
+ }
+ }
+ break;
+ case 2: /* AuthPDU */
+ {
+ /* TODO: these masks are not correct - have { 0xc0, 0x02, 0x0f } */
+ static int * const authpdu_fields[] = {
+ &hf_lon_authpdu_fmt,
+ &hf_lon_authpdu_authpdu_type,
+ &hf_lon_trans_no,
+ NULL
+ };
+ proto_tree_add_bitmask(lon_tree, tvb, offset, hf_lon_authpdu,
+ ett_authpdu, authpdu_fields, ENC_BIG_ENDIAN);
+
+ pdutype = (tvb_get_guint8(tvb, offset)>>4)& 0x03;
+ offset++;
+ switch(pdutype)
+ {
+ case 0: /* CHALLENGE */
+ case 2: /* REPLY */
+ offset += 9;
+ break;
+ default:
+ expert_add_info_format(pinfo, lon_tree, &ei_lon_tpdu_authpdu_type_unknown, "Unexpected AuthPDU type %i", pdutype);
+ break;
+ }
+ }
+ break;
+ case 3: /* APDU */
+ offset += dissect_apdu(lon_tree, pinfo, tvb, offset);
+ break;
+ }
+ /* END *PDU */
+
+ return offset;
+}
+
+static gint
+dissect_apdu(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ gint offset)
+{
+ tvbuff_t *next_tvb;
+ gint old_offset = offset, dest_type;
+
+ dest_type = tvb_get_guint8(tvb, offset);
+
+ if ((dest_type&0x80) == 0x80) { /* Network variable */
+ static int * const nv_fields[] = {
+ &hf_lon_nv_dir,
+ &hf_lon_nv_selector,
+ NULL
+ };
+ proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nv,
+ ett_nv, nv_fields, ENC_BIG_ENDIAN);
+ offset += 2;
+ } else if ((dest_type&0xc0) == 0) { /* Application */
+ static int * const app_fields[] = {
+ &hf_lon_app_code,
+ NULL
+ };
+ proto_tree_add_bitmask(tree, tvb, offset, hf_lon_app,
+ ett_app, app_fields, ENC_BIG_ENDIAN);
+ offset++;
+ } else if ((dest_type&0xe0) == 0x60) { /* Network Management */
+ static int * const nm_fields[] = {
+ &hf_lon_nm_code,
+ NULL
+ };
+ proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nm,
+ ett_nm, nm_fields, ENC_BIG_ENDIAN);
+ offset++;
+
+ if (dest_type == 0x7F) {
+ proto_tree_add_item(tree, hf_lon_addr_uid, tvb, offset, 6, ENC_NA);
+ offset += 6;
+ proto_tree_add_item(tree, hf_lon_name, tvb, offset, 8, ENC_NA);
+ offset += 8;
+ }
+
+ } else if ((dest_type&0xf0) == 0x50) { /* Network Diagnostic */
+ static int * const nd_fields[] = {
+ &hf_lon_nd_code,
+ NULL
+ };
+ proto_tree_add_bitmask(tree, tvb, offset, hf_lon_nd,
+ ett_nd, nd_fields, ENC_BIG_ENDIAN);
+ offset++;
+ } else if ((dest_type&0xf0) == 0x40) { /* Foreign Frame */
+ static int * const ff_fields[] = {
+ &hf_lon_ff_code,
+ NULL
+ };
+ proto_tree_add_bitmask(tree, tvb, offset, hf_lon_ff,
+ ett_ff, ff_fields, ENC_BIG_ENDIAN);
+ offset++;
+ } else { /* Shouldn't get here */
+ expert_add_info_format(pinfo, tree, &ei_lon_tpdu_apdu_dest_type, "Malformed APDU destin&type %i", dest_type);
+ }
+
+ next_tvb = tvb_new_subset_remaining(tvb, offset);
+
+ return offset - old_offset + call_data_dissector(next_tvb, pinfo, tree);
+}
+
+void
+proto_register_lon(void)
+{
+ static hf_register_info hf[] =
+ {
+ {&hf_lon_ppdu,
+ {"PPDU", "lon.ppdu",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_ppdu_prio,
+ {"Priority", "lon.prio",
+ FT_UINT8, BASE_DEC, NULL, 0x80,
+ "Priority packet", HFILL }
+ },
+ {&hf_lon_ppdu_alt,
+ {"Alt path", "lon.alt_path",
+ FT_UINT8, BASE_DEC, NULL, 0x40,
+ "Alternate path", HFILL }
+ },
+ {&hf_lon_ppdu_deltabl,
+ {"Delta BL", "lon.delta_bl",
+ FT_UINT8, BASE_DEC, NULL, 0x3f,
+ "How many packets to expect from this one", HFILL }
+ },
+ {&hf_lon_npdu,
+ {"NPDU", "lon.npdu",
+ FT_UINT8, BASE_DEC, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_npdu_version,
+ {"version", "lon.vers",
+ FT_UINT8, BASE_HEX, NULL, 0xc0,
+ "LON protocol version", HFILL }
+ },
+ {&hf_lon_npdu_pdu_fmt,
+ {"PDU format", "lon.pdufmt",
+ FT_UINT8, BASE_HEX, VALS(pdu_fmt_vs), 0x30,
+ NULL, HFILL }
+ },
+ {&hf_lon_npdu_addr_fmt,
+ {"Address format", "lon.addrfmt",
+ FT_UINT8, BASE_HEX, VALS(addr_fmt_vs), 0x0c,
+ NULL, HFILL }
+ },
+ {&hf_lon_npdu_dom_len,
+ {"Domain length", "lon.domainlen",
+ FT_UINT8, BASE_HEX, VALS(domain_length_vs), 0x03,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_srcsub,
+ {"Source subnet", "lon.srcnet",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_srcnode,
+ {"Source node", "lon.srcnode",
+ FT_UINT8, BASE_HEX, NULL, 0x7f,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_dstsub,
+ {"Destination subnet", "lon.dstnet",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_dstgrp,
+ {"Destination group", "lon.dstgrp",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_dstnode,
+ {"Destination node", "lon.dstnode",
+ FT_UINT8, BASE_HEX, NULL, 0x7f,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_grp,
+ {"Group", "lon.grp",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_grpmem,
+ {"Group member", "lon.grpmem",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_addr_uid,
+ {"Unique node ID", "lon.uid",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_domain,
+ {"Domain", "lon.domain",
+ FT_BYTES, BASE_NONE, NULL , 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_tpdu,
+ {"TPDU", "lon.tpdu",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_auth,
+ {"Auth", "lon.auth",
+ FT_UINT8, BASE_HEX, NULL, 0x80,
+ NULL, HFILL }
+ },
+ {&hf_lon_tpdu_tpdu_type,
+ {"TPDU type", "lon.tpdu_type",
+ FT_UINT8, BASE_HEX, VALS(tpdu_type_vs), 0x70,
+ NULL, HFILL }
+ },
+ {&hf_lon_trans_no,
+ {"Transaction number", "lon.trans_no",
+ FT_UINT8, BASE_HEX, NULL, 0x0f,
+ NULL, HFILL }
+ },
+ {&hf_lon_spdu,
+ {"SPDU", "lon.spdu",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_spdu_spdu_type,
+ {"SPDU type", "lon.spdu_type",
+ FT_UINT8, BASE_HEX, VALS(spdu_type_vs), 0x70,
+ NULL, HFILL }
+ },
+ {&hf_lon_mlen,
+ {"Length of M_List", "lon.spdu.mlen",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_mlist,
+ {"M_List", "lon.spdu.mlist",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_authpdu,
+ {"AuthPDU", "lon.authpdu",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_authpdu_fmt,
+ {"FMT (same as AddrFmt)", "lon.authpdu_addrfmt",
+ FT_UINT8, BASE_HEX, NULL, 0xc,
+ NULL, HFILL }
+ },
+ {&hf_lon_authpdu_authpdu_type,
+ {"AuthPDU type", "lon.authpdu_type",
+ FT_UINT8, BASE_HEX, VALS(authpdu_type_vs), 0x02,
+ NULL, HFILL }
+ },
+ {&hf_lon_nv,
+ {"Network Variable", "lon.nv",
+ FT_UINT16, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_nv_dir,
+ {"NV direction", "lon.nv.dir",
+ FT_UINT16, BASE_HEX, NULL, 0x4000,
+ NULL, HFILL }
+ },
+ {&hf_lon_nv_selector,
+ {"NV selector", "lon.nv.selector",
+ FT_UINT16, BASE_HEX, NULL, 0x3fff,
+ NULL, HFILL }
+ },
+ {&hf_lon_app,
+ {"Application", "lon.application",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_app_code,
+ {"Code", "lon.code",
+ FT_UINT8, BASE_HEX, NULL, 0x3f,
+ NULL, HFILL }
+ },
+ {&hf_lon_nm,
+ {"Network Management", "lon.nm",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_nm_code,
+ {"Code", "lon.code",
+ FT_UINT8, BASE_HEX, VALS(nm_code_vs), 0xff,
+ NULL, HFILL }
+ },
+ {&hf_lon_nd,
+ {"Network Diagnostic", "lon.nd",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_nd_code,
+ {"Code", "lon.code",
+ FT_UINT8, BASE_HEX, VALS(nd_code_vs), 0xff,
+ NULL, HFILL }
+ },
+ {&hf_lon_ff,
+ {"Foreign Frame", "lon.ff",
+ FT_UINT8, BASE_HEX, NULL, 0,
+ NULL, HFILL }
+ },
+ {&hf_lon_ff_code,
+ {"Code", "lon.code",
+ FT_UINT8, BASE_HEX, NULL, 0x0f,
+ NULL, HFILL }
+ },
+ {&hf_lon_name,
+ {"Node name", "lon.name",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ },
+#if 0
+ {&hf_lon_checksum,
+ {"Checksum", "lon.chksum",
+ FT_BYTES, BASE_NONE, NULL, 0,
+ NULL, HFILL }
+ }
+#endif
+ };
+
+ static gint *ett[] =
+ {
+ &ett_lon,
+ &ett_address,
+ &ett_ppdu,
+ &ett_npdu,
+ &ett_tpdu,
+ &ett_spdu,
+ &ett_authpdu,
+ &ett_apdu,
+ &ett_nv,
+ &ett_app,
+ &ett_nm,
+ &ett_nd,
+ &ett_ff
+ };
+
+ static ei_register_info ei[] = {
+ { &ei_lon_tpdu_tpdu_type_unknown, { "lon.tpdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected TPDU type", EXPFILL }},
+ { &ei_lon_tpdu_spdu_type_unknown, { "lon.spdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected SPDU type", EXPFILL }},
+ { &ei_lon_tpdu_authpdu_type_unknown, { "lon.authpdu_type.unknown", PI_PROTOCOL, PI_WARN, "Unexpected AuthPDU type", EXPFILL }},
+ { &ei_lon_tpdu_apdu_dest_type, { "lon.authpdu_dest_type.unknown", PI_PROTOCOL, PI_WARN, "Malformed APDU destin&type", EXPFILL }},
+ };
+
+ expert_module_t* expert_lon;
+
+ proto_lon = proto_register_protocol("Local Operating Network",
+ "LON", "lon");
+
+ proto_register_field_array (proto_lon, hf, array_length (hf));
+ proto_register_subtree_array (ett, array_length (ett));
+ expert_lon = expert_register_protocol(proto_lon);
+ expert_register_field_array(expert_lon, ei, array_length(ei));
+
+ lon_handle = register_dissector("lon", dissect_lon, proto_lon);
+}
+
+
+void
+proto_reg_handoff_lon(void)
+{
+ dissector_add_uint("cnip.protocol", 0, lon_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */